Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 03 Jun 2014 17:50:44 -0400
changeset 205710 e7f2825aed544e4eeae78ddbcec10f089f5762c3
parent 205709 8e18f2d480692b19b359ca9c788810a5973cc706 (current diff)
parent 205647 668f29cd71b3a7e49cdfc2bd34aea0f94f25d83d (diff)
child 205711 875df781fa8bf83c4f6b056706269ec75daf258a
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone32.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team.
dom/datastore/DataStoreImpl.jsm
dom/datastore/DataStoreService.js
dom/datastore/DataStoreServiceInternal.jsm
dom/telephony/gonk/TelephonyProvider.js
dom/telephony/gonk/TelephonyProvider.manifest
dom/telephony/ipc/TelephonyIPCProvider.cpp
dom/telephony/ipc/TelephonyIPCProvider.h
dom/telephony/nsIGonkTelephonyProvider.idl
dom/telephony/nsITelephonyProvider.idl
dom/webidl/Identity.webidl
testing/tps/INSTALL.sh
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9100fa82fc355f5201e23e400fc6b40e875304ed"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--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="6e2a3b589d1e8cc1d9df25f5e630ce30a0aa39f3">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--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="276ce45e78b09c4a4ee643646f691d22804754c1">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
-  <project name="librecovery" patch="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <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="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8e4420c0c5c8e8c8e58a000278a7129403769f96"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9100fa82fc355f5201e23e400fc6b40e875304ed"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--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="6e2a3b589d1e8cc1d9df25f5e630ce30a0aa39f3">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
@@ -114,17 +114,17 @@
   <project name="platform/system/netd" path="system/netd" revision="ea8103eae5642621ca8202e00620f4ca954ed413"/>
   <project name="platform/system/security" path="system/security" revision="360f51f7af191316cd739f229db1c5f7233be063"/>
   <project name="platform/system/vold" path="system/vold" revision="153df4d067a4149c7d78f1c92fed2ce2bd6a272e"/>
   <default remote="caf" revision="jb_3.2" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="34ed8345250bb97262d70a052217a92e83444ede"/>
   <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="95423152b66d4a41032414fc3fb8c3d9a0636c7d"/>
-  <project name="kernel/msm" path="kernel" revision="228d59147ff524e90774c566eef03260cc6857b8"/>
+  <project name="kernel/msm" path="kernel" revision="e3895712aa9ddb955f0fdac880aa553556e64c41"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="81c4a859d75d413ad688067829d21b7ba9205f81"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
   <project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
   <project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="494c177966fdc31183a5f7af82dc9130f523da4b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="5b934dc57dae25f286b0e7210dc6ff47f3244927"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "d69102eda2275b178a4b5c2916522fb82feb05f5", 
+    "revision": "33a8ca00e3128502d0c4c834236be335c0060f43", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <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="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <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="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <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,20 +12,20 @@
   <!--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="6e2a3b589d1e8cc1d9df25f5e630ce30a0aa39f3">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <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"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,22 +12,22 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="dd9e74d196675b0b05170f0ab94a80a36697a551"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="1d4f6f7312882e78b57971152de75d1281a26187"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="531cf670e485649c69746e46d567929fcd54cbc5"/>
   <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="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="600ef6ddc915ceffc1a89d51b7be8453fe709992"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="994fa9a1f7ce0e63c880a48d571c3ab3e01884a3"/>
   <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="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -425,18 +425,18 @@
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
 @BINPATH@/components/MmsService.js
 @BINPATH@/components/MmsService.manifest
 @BINPATH@/components/MobileMessageDatabaseService.js
 @BINPATH@/components/MobileMessageDatabaseService.manifest
 @BINPATH@/components/RadioInterfaceLayer.js
 @BINPATH@/components/RadioInterfaceLayer.manifest
 @BINPATH@/components/RILContentHelper.js
-@BINPATH@/components/TelephonyProvider.js
-@BINPATH@/components/TelephonyProvider.manifest
+@BINPATH@/components/TelephonyService.js
+@BINPATH@/components/TelephonyService.manifest
 #endif // MOZ_WIDGET_GONK && MOZ_B2G_RIL
 
 #ifndef MOZ_WIDGET_GONK
 @BINPATH@/components/extensions.manifest
 @BINPATH@/components/addonManager.js
 @BINPATH@/components/amContentHandler.js
 @BINPATH@/components/amInstallTrigger.js
 @BINPATH@/components/amWebInstallListener.js
@@ -808,17 +808,17 @@ bin/components/@DLL_PREFIX@nkgnomevfs@DL
 #endif
 
 #ifdef MOZ_SERVICES_FXACCOUNTS
 @BINPATH@/components/FxAccountsUIGlue.js
 @BINPATH@/components/services_fxaccounts.xpt
 #endif
 
 @BINPATH@/components/DataStore.manifest
-@BINPATH@/components/DataStoreService.js
+@BINPATH@/components/DataStoreImpl.js
 @BINPATH@/components/dom_datastore.xpt
 
 #ifdef MOZ_WEBSPEECH
 @BINPATH@/components/dom_webspeechsynth.xpt
 #endif
 
 #ifdef XP_MACOSX
 @BINPATH@/@DLL_PREFIX@plugin_child_interpose@DLL_SUFFIX@
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -46,17 +46,20 @@ registerCleanupFunction(function() {
 
   // Debugger tests use a lot of memory, so force a GC to help fragmentation.
   info("Forcing GC after debugger test.");
   Cu.forceGC();
 });
 
 // Import the GCLI test helper
 let testDir = gTestPath.substr(0, gTestPath.lastIndexOf("/"));
-Services.scriptloader.loadSubScript(testDir + "../../../commandline/test/helpers.js", this);
+testDir = testDir.replace(/\/\//g, '/');
+testDir = testDir.replace("chrome:/mochitest", "chrome://mochitest");
+let helpersjs = testDir + "/../../commandline/test/helpers.js";
+Services.scriptloader.loadSubScript(helpersjs, this);
 
 // Redeclare dbg_assert with a fatal behavior.
 function dbg_assert(cond, e) {
   if (!cond) {
     throw e;
   }
 }
 
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -852,17 +852,17 @@ bin/libfreebl_32int64_3.so
 @BINPATH@/metro/chrome/pdfjs/*
 #endif
 @BINPATH@/metro/components
 @BINPATH@/metro/defaults
 @BINPATH@/metro/modules
 #endif
 
 @BINPATH@/components/DataStore.manifest
-@BINPATH@/components/DataStoreService.js
+@BINPATH@/components/DataStoreImpl.js
 @BINPATH@/components/dom_datastore.xpt
 
 
 #ifdef MOZ_ASAN
 #ifdef CLANG_CXX
 @BINPATH@/llvm-symbolizer
 #endif
 #endif
--- a/build/automation.py.in
+++ b/build/automation.py.in
@@ -809,17 +809,17 @@ class Automation(object):
   def checkForCrashes(self, minidumpDir, symbolsPath):
     return mozcrash.check_for_crashes(minidumpDir, symbolsPath, test_name=self.lastTestSeen)
 
   def runApp(self, testURL, env, app, profileDir, extraArgs,
              runSSLTunnel = False, utilityPath = None,
              xrePath = None, certPath = None,
              debuggerInfo = None, symbolsPath = None,
              timeout = -1, maxTime = None, onLaunch = None,
-             webapprtChrome = False, screenshotOnFail=False):
+             webapprtChrome = False, screenshotOnFail=False, testPath=None):
     """
     Run the app, log the duration it took to execute, return the status code.
     Kills the app if it runs for longer than |maxTime| seconds, or outputs nothing for |timeout| seconds.
     """
 
     if utilityPath == None:
       utilityPath = self.DIST_BIN
     if xrePath == None:
--- a/configure.in
+++ b/configure.in
@@ -9182,16 +9182,17 @@ if test -z "$direct_nspr_config"; then
     CC="$_SUBDIR_CC"
     CXX="$_SUBDIR_CXX"
     CFLAGS="$_SUBDIR_CFLAGS"
     CPPFLAGS="$_SUBDIR_CPPFLAGS"
     CXXFLAGS="$_SUBDIR_CXXFLAGS"
     LDFLAGS="$_SUBDIR_LDFLAGS"
     HOST_CC="$_SUBDIR_HOST_CC"
     HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS"
+    HOST_CXXFLAGS="$_SUBDIR_HOST_CXXFLAGS"
     HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS"
     RC=
 fi
 
 unset MAKEFILES
 unset CONFIG_FILES
 
 # Run all configure scripts specified by a subconfigure
@@ -9284,16 +9285,17 @@ dnl ====================================
 CC="$_SUBDIR_CC"
 CXX="$_SUBDIR_CXX"
 CFLAGS="$_SUBDIR_CFLAGS"
 CPPFLAGS="$_SUBDIR_CPPFLAGS"
 CXXFLAGS="$_SUBDIR_CXXFLAGS"
 LDFLAGS="$_SUBDIR_LDFLAGS"
 HOST_CC="$_SUBDIR_HOST_CC"
 HOST_CFLAGS="$_SUBDIR_HOST_CFLAGS"
+HOST_CXXFLAGS="$_SUBDIR_HOST_CXXFLAGS"
 HOST_LDFLAGS="$_SUBDIR_HOST_LDFLAGS"
 RC=
 
 if test -n "$ENABLE_CLANG_PLUGIN"; then
     ac_configure_args="$_SUBDIR_CONFIG_ARGS"
     AC_OUTPUT_SUBDIRS(build/clang-plugin)
 fi
 
--- a/content/base/public/nsIDocument.h
+++ b/content/base/public/nsIDocument.h
@@ -133,17 +133,18 @@ typedef CallbackObjectHolder<NodeFilter,
 #define NS_IDOCUMENT_IID \
 { 0x0300e2e0, 0x24c9, 0x4ecf, \
   { 0x81, 0xec, 0x64, 0x26, 0x9a, 0x4b, 0xef, 0x18 } }
 
 // Enum for requesting a particular type of document when creating a doc
 enum DocumentFlavor {
   DocumentFlavorLegacyGuess, // compat with old code until made HTML5-compliant
   DocumentFlavorHTML, // HTMLDocument with HTMLness bit set to true
-  DocumentFlavorSVG // SVGDocument
+  DocumentFlavorSVG, // SVGDocument
+  DocumentFlavorPlain, // Just a Document
 };
 
 // Document states
 
 // RTL locale: specific to the XUL localedir attribute
 #define NS_DOCUMENT_STATE_RTL_LOCALE              NS_DEFINE_EVENT_STATE_MACRO(0)
 // Window activation status
 #define NS_DOCUMENT_STATE_WINDOW_INACTIVE         NS_DEFINE_EVENT_STATE_MACRO(1)
@@ -2680,17 +2681,18 @@ private:
   uint32_t                mMicroTaskLevel;
 };
 
 // XXX These belong somewhere else
 nsresult
 NS_NewHTMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
 
 nsresult
-NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false);
+NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData = false,
+                  bool aIsPlainDocument = false);
 
 nsresult
 NS_NewSVGDocument(nsIDocument** aInstancePtrResult);
 
 nsresult
 NS_NewImageDocument(nsIDocument** aInstancePtrResult);
 
 nsresult
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -12062,17 +12062,17 @@ nsIDocument::Constructor(const GlobalObj
                       NullString(),
                       EmptyString(),
                       nullptr,
                       uri,
                       uri,
                       prin->GetPrincipal(),
                       true,
                       global,
-                      DocumentFlavorLegacyGuess);
+                      DocumentFlavorPlain);
   if (NS_FAILED(res)) {
     rv.Throw(res);
     return nullptr;
   }
 
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(document);
   doc->SetReadyStateInternal(nsIDocument::READYSTATE_COMPLETE);
 
--- a/content/base/test/mochitest.ini
+++ b/content/base/test/mochitest.ini
@@ -561,16 +561,17 @@ run-if = os == 'linux'
 [test_copyimage.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || toolkit != 'gtk2' && toolkit != 'gtk3' && toolkit != 'windows' || e10s #b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_copypaste.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 904183 # b2g(clipboard undefined) b2g-debug(clipboard undefined) b2g-desktop(clipboard undefined)
 [test_copypaste.xhtml]
 skip-if = buildapp == 'b2g' || toolkit == 'android' #bug 904183 # b2g(bug 904183) b2g-debug(bug 904183) b2g-desktop(bug 904183)
 [test_createHTMLDocument.html]
 [test_declare_stylesheet_obsolete.html]
+[test_document_constructor.html]
 [test_domparser_null_char.html]
 [test_domparsing.html]
 [test_elementTraversal.html]
 [test_encodeToStringWithMaxLength.html]
 [test_fileapi.html]
 skip-if = e10s
 [test_fileapi_slice.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #bug 775227
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_document_constructor.html
@@ -0,0 +1,31 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1017932
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1017932</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1017932 **/
+   var doc = new Document;
+   ok(doc instanceof Document, "Should have a document");
+   ok(!(doc instanceof XMLDocument), "Should not be an XMLDocument");
+   ok(!("load" in doc), "Should not have a load() method");
+   is(Object.getPrototypeOf(doc), Document.prototype,
+      "Should have the right proto");
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1017932">Mozilla Bug 1017932</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/content/xml/document/src/XMLDocument.cpp
+++ b/content/xml/document/src/XMLDocument.cpp
@@ -45,16 +45,17 @@
 #include "nsNodeUtils.h"
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIHTMLDocument.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/EventDispatcher.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/XMLDocumentBinding.h"
+#include "mozilla/dom/DocumentBinding.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 // ==================================================================
 // =
 // ==================================================================
 
@@ -82,17 +83,20 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
   nsCOMPtr<nsIDocument> d;
   bool isHTML = false;
   bool isXHTML = false;
   if (aFlavor == DocumentFlavorSVG) {
     rv = NS_NewSVGDocument(getter_AddRefs(d));
   } else if (aFlavor == DocumentFlavorHTML) {
     rv = NS_NewHTMLDocument(getter_AddRefs(d));
     isHTML = true;
+  } else if (aFlavor == DocumentFlavorPlain) {
+    rv = NS_NewXMLDocument(getter_AddRefs(d), aLoadedAsData, true);
   } else if (aDoctype) {
+    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
     nsAutoString publicId, name;
     aDoctype->GetPublicId(publicId);
     if (publicId.IsEmpty()) {
       aDoctype->GetName(name);
     }
     if (name.EqualsLiteral("html") ||
         publicId.EqualsLiteral("-//W3C//DTD HTML 4.01//EN") ||
         publicId.EqualsLiteral("-//W3C//DTD HTML 4.01 Frameset//EN") ||
@@ -112,16 +116,17 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
     else if (publicId.EqualsLiteral("-//W3C//DTD SVG 1.1//EN")) {
       rv = NS_NewSVGDocument(getter_AddRefs(d));
     }
     // XXX Add support for XUL documents.
     else {
       rv = NS_NewXMLDocument(getter_AddRefs(d));
     }
   } else {
+    MOZ_ASSERT(aFlavor == DocumentFlavorLegacyGuess);
     rv = NS_NewXMLDocument(getter_AddRefs(d));
   }
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aEventObject)) {
@@ -167,28 +172,30 @@ NS_NewDOMDocument(nsIDOMDocument** aInst
 
   *aInstancePtrResult = doc;
   NS_ADDREF(*aInstancePtrResult);
 
   return NS_OK;
 }
 
 nsresult
-NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData)
+NS_NewXMLDocument(nsIDocument** aInstancePtrResult, bool aLoadedAsData,
+                  bool aIsPlainDocument)
 {
   nsRefPtr<XMLDocument> doc = new XMLDocument();
 
   nsresult rv = doc->Init();
 
   if (NS_FAILED(rv)) {
     *aInstancePtrResult = nullptr;
     return rv;
   }
 
   doc->SetLoadedAsData(aLoadedAsData);
+  doc->mIsPlainDocument = aIsPlainDocument;
   doc.forget(aInstancePtrResult);
 
   return NS_OK;
 }
 
 nsresult
 NS_NewXBLDocument(nsIDOMDocument** aInstancePtrResult,
                   nsIURI* aDocumentURI,
@@ -592,20 +599,25 @@ XMLDocument::Clone(nsINodeInfo *aNodeInf
                "Can't import this document into another document!");
 
   nsRefPtr<XMLDocument> clone = new XMLDocument();
   nsresult rv = CloneDocHelper(clone);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // State from XMLDocument
   clone->mAsync = mAsync;
+  clone->mIsPlainDocument = mIsPlainDocument;
 
   return CallQueryInterface(clone.get(), aResult);
 }
 
 JSObject*
 XMLDocument::WrapNode(JSContext *aCx)
 {
+  if (mIsPlainDocument) {
+    return DocumentBinding::Wrap(aCx, this);
+  }
+
   return XMLDocumentBinding::Wrap(aCx, this);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/content/xml/document/src/XMLDocument.h
+++ b/content/xml/document/src/XMLDocument.h
@@ -65,23 +65,29 @@ public:
   using nsIDocument::GetLocation;
   // But then we need to also pull in the nsDocument XPCOM version
   // because nsXULDocument tries to forward to it.
   using nsDocument::GetLocation;
 
 protected:
   virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
 
+  friend nsresult (::NS_NewXMLDocument)(nsIDocument**, bool, bool);
+
+
   // mChannelIsPending indicates whether we're currently asynchronously loading
   // data from mChannel (via document.load() or normal load).  It's set to true
   // when we first find out about the channel (StartDocumentLoad) and set to
   // false in EndLoad or if ResetToURI() is called.  In the latter case our
   // mChannel is also cancelled.  Note that if this member is true, mChannel
   // cannot be null.
   bool mChannelIsPending;
   bool mAsync;
   bool mLoopingForSyncLoad;
+
+  // If true. we're really a Document, not an XMLDocument
+  bool mIsPlainDocument;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_XMLDocument_h
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -77,17 +77,17 @@
 #include "AudioChannelManager.h"
 #endif
 
 #ifdef MOZ_B2G_FM
 #include "mozilla/dom/FMRadio.h"
 #endif
 
 #include "nsIDOMGlobalPropertyInitializer.h"
-#include "nsIDataStoreService.h"
+#include "mozilla/dom/DataStoreService.h"
 #include "nsJSUtils.h"
 
 #include "nsScriptNameSpaceManager.h"
 
 #include "mozilla/dom/NavigatorBinding.h"
 #include "mozilla/dom/Promise.h"
 
 #include "nsIUploadChannel2.h"
@@ -1461,18 +1461,17 @@ Navigator::GetDataStores(nsPIDOMWindow* 
                          const nsAString& aName,
                          ErrorResult& aRv)
 {
   if (!aWindow || !aWindow->GetDocShell()) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
-  nsCOMPtr<nsIDataStoreService> service =
-    do_GetService("@mozilla.org/datastore-service;1");
+  nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
   if (!service) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsCOMPtr<nsISupports> promise;
   aRv = service->GetDataStores(aWindow, aName, getter_AddRefs(promise));
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -4334,23 +4334,17 @@ nsGlobalWindow::GetOwnPropertyNames(JSCo
     nameSpaceManager->EnumerateGlobalNames(EnumerateGlobalName, &closure);
   }
 }
 
 /* static */ bool
 nsGlobalWindow::IsChromeWindow(JSContext* aCx, JSObject* aObj)
 {
   // For now, have to deal with XPConnect objects here.
-  nsGlobalWindow* win;
-  nsresult rv = UNWRAP_OBJECT(Window, aObj, win);
-  if (NS_FAILED(rv)) {
-    nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aObj);
-    win = static_cast<nsGlobalWindow*>(piWin.get());
-  }
-  return win->IsChromeWindow();
+  return xpc::WindowOrNull(aObj)->IsChromeWindow();
 }
 
 nsIDOMOfflineResourceList*
 nsGlobalWindow::GetApplicationCache(ErrorResult& aError)
 {
   FORWARD_TO_INNER_OR_THROW(GetApplicationCache, (aError), aError, nullptr);
 
   if (!mApplicationCache) {
@@ -4466,19 +4460,19 @@ nsGlobalWindow::GetControllers(nsIContro
   ErrorResult rv;
   nsCOMPtr<nsIControllers> controllers = GetControllers(rv);
   controllers.forget(aResult);
 
   return rv.ErrorCode();
 }
 
 nsIDOMWindow*
-nsGlobalWindow::GetOpener(ErrorResult& aError)
-{
-  FORWARD_TO_OUTER_OR_THROW(GetOpener, (aError), aError, nullptr);
+nsGlobalWindow::GetOpenerWindow(ErrorResult& aError)
+{
+  FORWARD_TO_OUTER_OR_THROW(GetOpenerWindow, (aError), aError, nullptr);
 
   nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
   if (!opener) {
     return nullptr;
   }
 
   // First, check if we were called from a privileged chrome script
   if (nsContentUtils::IsCallerChrome()) {
@@ -4507,81 +4501,115 @@ nsGlobalWindow::GetOpener(ErrorResult& a
         return opener;
       }
     }
   }
 
   return nullptr;
 }
 
+JS::Value
+nsGlobalWindow::GetOpener(JSContext* aCx, ErrorResult& aError)
+{
+  nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(aError);
+  if (aError.Failed() || !opener) {
+    return JS::NullValue();
+  }
+
+  JS::Rooted<JS::Value> val(aCx);
+  aError = nsContentUtils::WrapNative(aCx, opener, &val);
+  return val;
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::GetScriptableOpener(JSContext* aCx,
+                                    JS::MutableHandle<JS::Value> aOpener)
+{
+  ErrorResult rv;
+  aOpener.set(GetOpener(aCx, rv));
+
+  return rv.ErrorCode();
+}
+
 NS_IMETHODIMP
 nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
 {
   ErrorResult rv;
-  nsCOMPtr<nsIDOMWindow> opener = GetOpener(rv);
+  nsCOMPtr<nsIDOMWindow> opener = GetOpenerWindow(rv);
   opener.forget(aOpener);
-
-  return rv.ErrorCode();
-}
-
-void
-nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener, ErrorResult& aError)
+  return rv.ErrorCode();
+}
+
+void
+nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
+                          ErrorResult& aError)
 {
   // Check if we were called from a privileged chrome script.  If not, and if
   // aOpener is not null, just define aOpener on our inner window's JS object,
   // wrapped into the current compartment so that for Xrays we define on the
   // Xray expando object, but don't set it on the outer window, so that it'll
   // get reset on navigation.  This is just like replaceable properties, but
   // we're not quite readonly.
-  if (aOpener && !nsContentUtils::IsCallerChrome()) {
-    // JS_WrapObject will outerize, so we don't care if aOpener is an inner.
-    nsCOMPtr<nsIGlobalObject> glob = do_QueryInterface(aOpener);
-    if (!glob) {
-      aError.Throw(NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    AutoJSContext cx;
-    JSAutoRequest ar(cx);
-    // Note we explicitly do NOT enter any particular compartment here; we want
-    // the caller compartment in cases when we have a caller, so that we define
-    // expandos on Xrays as needed.
-
-    JS::Rooted<JSObject*> otherObj(cx, glob->GetGlobalJSObject());
-    if (!otherObj) {
-      aError.Throw(NS_ERROR_UNEXPECTED);
-      return;
-    }
-
-    JS::Rooted<JSObject*> thisObj(cx, GetWrapperPreserveColor());
+  if (!aOpener.isNull() && !nsContentUtils::IsCallerChrome()) {
+    JS::Rooted<JSObject*> thisObj(aCx, GetWrapperPreserveColor());
     if (!thisObj) {
       aError.Throw(NS_ERROR_UNEXPECTED);
       return;
     }
 
-    if (!JS_WrapObject(cx, &otherObj) ||
-        !JS_WrapObject(cx, &thisObj) ||
-        !JS_DefineProperty(cx, thisObj, "opener", otherObj, JSPROP_ENUMERATE,
+    if (!JS_WrapObject(aCx, &thisObj) ||
+        !JS_DefineProperty(aCx, thisObj, "opener", aOpener, JSPROP_ENUMERATE,
                            JS_PropertyStub, JS_StrictPropertyStub)) {
       aError.Throw(NS_ERROR_FAILURE);
     }
 
     return;
   }
 
-  SetOpenerWindow(aOpener, false);
+  if (!aOpener.isObjectOrNull()) {
+    // Chrome code trying to set some random value as opener
+    aError.Throw(NS_ERROR_INVALID_ARG);
+    return;
+  }
+
+  nsGlobalWindow* win = nullptr;
+  if (aOpener.isObject()) {
+    JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
+                                            /* stopAtOuter = */ false);
+    if (!unwrapped) {
+      aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
+      return;
+    }
+
+    win = xpc::WindowOrNull(unwrapped);
+    if (!win) {
+      // Wasn't a window
+      aError.Throw(NS_ERROR_INVALID_ARG);
+      return;
+    }
+  }
+
+  SetOpenerWindow(win, false);
+}
+
+NS_IMETHODIMP
+nsGlobalWindow::SetScriptableOpener(JSContext* aCx,
+                                    JS::Handle<JS::Value> aOpener)
+{
+  ErrorResult rv;
+  SetOpener(aCx, aOpener, rv);
+
+  return rv.ErrorCode();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
 {
-  ErrorResult rv;
-  SetOpener(aOpener, rv);
-
-  return rv.ErrorCode();
+  SetOpenerWindow(aOpener, false);
+  return NS_OK;
 }
 
 void
 nsGlobalWindow::GetStatus(nsAString& aStatus, ErrorResult& aError)
 {
   FORWARD_TO_OUTER_OR_THROW(GetStatus, (aStatus, aError), aError, );
 
   aStatus = mStatus;
@@ -13694,23 +13722,17 @@ nsGlobalModalWindow::SetReturnValue(nsIV
   return NS_OK;
 }
 
 /* static */
 bool
 nsGlobalWindow::IsModalContentWindow(JSContext* aCx, JSObject* aGlobal)
 {
   // For now, have to deal with XPConnect objects here.
-  nsGlobalWindow* win;
-  nsresult rv = UNWRAP_OBJECT(Window, aGlobal, win);
-  if (NS_FAILED(rv)) {
-    nsCOMPtr<nsPIDOMWindow> piWin = do_QueryWrapper(aCx, aGlobal);
-    win = static_cast<nsGlobalWindow*>(piWin.get());
-  }
-  return win->IsModalContentWindow();
+  return xpc::WindowOrNull(aGlobal)->IsModalContentWindow();
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::GetConsole(JSContext* aCx,
                            JS::MutableHandle<JS::Value> aConsole)
 {
   ErrorResult rv;
   nsRefPtr<Console> console = GetConsole(rv);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -831,18 +831,22 @@ public:
   already_AddRefed<nsIDOMWindow> GetFrames(mozilla::ErrorResult& aError);
   uint32_t Length();
   already_AddRefed<nsIDOMWindow> GetTop(mozilla::ErrorResult& aError)
   {
     nsCOMPtr<nsIDOMWindow> top;
     aError = GetScriptableTop(getter_AddRefs(top));
     return top.forget();
   }
-  nsIDOMWindow* GetOpener(mozilla::ErrorResult& aError);
-  void SetOpener(nsIDOMWindow* aOpener, mozilla::ErrorResult& aError);
+protected:
+  nsIDOMWindow* GetOpenerWindow(mozilla::ErrorResult& aError);
+public:
+  JS::Value GetOpener(JSContext* aCx, mozilla::ErrorResult& aError);
+  void SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
+                 mozilla::ErrorResult& aError);
   using nsIDOMWindow::GetParent;
   already_AddRefed<nsIDOMWindow> GetParent(mozilla::ErrorResult& aError);
   mozilla::dom::Element* GetFrameElement(mozilla::ErrorResult& aError);
   already_AddRefed<nsIDOMWindow> Open(const nsAString& aUrl,
                                       const nsAString& aName,
                                       const nsAString& aOptions,
                                       mozilla::ErrorResult& aError);
   mozilla::dom::Navigator* GetNavigator(mozilla::ErrorResult& aError);
--- a/dom/base/test/test_setting_opener.html
+++ b/dom/base/test/test_setting_opener.html
@@ -54,16 +54,35 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function continueOpenerTest(win) {
     is(win.opener, window, "Navigating a window should have reset the opener we stashed on it temporarily");
     is(evalsb("win.opener", sb1), window,
        "Navigating a window should have reset the opener in sb1");
     is(evalsb("win.opener", sb2), window,
        "Navigating a window should have reset the opener in sb2");
 
+    win.opener = 5;
+    evalsb("win.opener = 5", sb1);
+    evalsb("win.opener = 5", sb2);
+    is(win.opener, 5, "Should be able to set an opener to a primitive");
+    is(evalsb("win.opener", sb1), 5,
+       "Should be able to set the opener to a primitive in a sandbox one");
+    is(evalsb("win.opener", sb2), 5,
+       "Should be able to set the opener to a primitive in a sandbox two");
+    win.location = "data:text/html,<script>opener.setTimeout(opener.continueOpenerTest2, 0, this);</" + "script>";
+  }
+
+  function continueOpenerTest2(win) {
+    is(win.opener, window,
+       "Navigating a window again should have reset the opener we stashed on it temporarily");
+    is(evalsb("win.opener", sb1), window,
+       "Navigating a window again should have reset the opener in sb1");
+    is(evalsb("win.opener", sb2), window,
+       "Navigating a window again should have reset the opener in sb2");
+
     win.opener = null;
     is(win.opener, null, "Should be able to set the opener to null");
     is(evalsb("win.opener", sb1), null,
        "Setting the opener to null should be visible in sb1");
     is(evalsb("win.opener", sb2), null,
        "Setting the opener to null should be visible in sb2");
 
     win.location = "data:text/html,Loaded";
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -81,18 +81,20 @@ CallbackObject::CallSetup::CallSetup(Cal
   nsIGlobalObject* globalObject = nullptr;
 
   {
     // Bug 955660: we cannot do "proper" rooting here because we need the
     // global to get a context. Everything here is simple getters that cannot
     // GC, so just paper over the necessary dataflow inversion.
     JS::AutoSuppressGCAnalysis nogc;
     if (mIsMainThread) {
-      // Now get the global and JSContext for this callback.
-      nsGlobalWindow* win = xpc::WindowGlobalOrNull(realCallback);
+      // Now get the global and JSContext for this callback.  Note that for the
+      // case of JS-implemented WebIDL we never have a window here.
+      nsGlobalWindow* win =
+        aIsJSImplementedWebIDL ? nullptr : xpc::WindowGlobalOrNull(realCallback);
       if (win) {
         // Make sure that if this is a window it's the current inner, since the
         // nsIScriptContext and hence JSContext are associated with the outer
         // window.  Which means that if someone holds on to a function from a
         // now-unloaded document we'd have the new document as the script entry
         // point...
         MOZ_ASSERT(win->IsInnerWindow());
         nsPIDOMWindow* outer = win->GetOuterWindow();
@@ -146,17 +148,19 @@ CallbackObject::CallSetup::CallSetup(Cal
     // operations _after_ the Push() above, which lets us take advantage of the
     // JSAutoRequest embedded in the pusher.
     //
     // We can do this even though we're not in the right compartment yet, because
     // Rooted<> does not care about compartments.
     mRootedCallable.construct(cx, aCallback->Callback());
   }
 
-  if (mIsMainThread) {
+  // JS-implemented WebIDL is always OK to run, since it runs with Chrome
+  // privileges anyway.
+  if (mIsMainThread && !aIsJSImplementedWebIDL) {
     // Check that it's ok to run this callback at all.
     // Make sure to use realCallback to get the global of the callback object,
     // not the wrapper.
     bool allowed = nsContentUtils::GetSecurityManager()->
       ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
 
     if (!allowed) {
       return;
@@ -215,34 +219,34 @@ CallbackObject::CallSetup::~CallSetup()
   // so we end up reporting them while in the compartment of our entry point,
   // not whatever cross-compartment wrappper mCallback might be.
   // Be careful: the JSAutoCompartment might not have been constructed at all!
   mAc.destroyIfConstructed();
 
   // Now, if we have a JSContext, report any pending errors on it, unless we
   // were told to re-throw them.
   if (mCx) {
-    bool dealtWithPendingException = false;
+    bool needToDealWithException = JS_IsExceptionPending(mCx);
     if ((mCompartment && mExceptionHandling == eRethrowContentExceptions) ||
         mExceptionHandling == eRethrowExceptions) {
       // Restore the old context options
       JS::ContextOptionsRef(mCx) = mSavedJSContextOptions;
       mErrorResult.MightThrowJSException();
-      if (JS_IsExceptionPending(mCx)) {
+      if (needToDealWithException) {
         JS::Rooted<JS::Value> exn(mCx);
         if (JS_GetPendingException(mCx, &exn) &&
             ShouldRethrowException(exn)) {
           mErrorResult.ThrowJSException(mCx, exn);
           JS_ClearPendingException(mCx);
-          dealtWithPendingException = true;
+          needToDealWithException = false;
         }
       }
     }
 
-    if (!dealtWithPendingException) {
+    if (needToDealWithException) {
       // Either we're supposed to report our exceptions, or we're supposed to
       // re-throw them but we failed to JS_GetPendingException.  Either way,
       // just report the pending exception, if any.
       //
       // We don't use nsJSUtils::ReportPendingException here because all it
       // does at this point is JS_SaveFrameChain and enter a compartment around
       // a JS_ReportPendingException call.  But our mAutoEntryScript should
       // already do a JS_SaveFrameChain and we are already in the compartment
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7478,53 +7478,56 @@ class CGMemberJITInfo(CGThing):
     def __init__(self, descriptor, member):
         self.member = member
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
     def defineJitInfo(self, infoName, opName, opType, infallible, movable,
-                      aliasSet, hasSlot, slotIndex, returnTypes, args):
+                      aliasSet, alwaysInSlot, lazilyInSlot, slotIndex,
+                      returnTypes, args):
         """
         aliasSet is a JSJitInfo::AliasSet value, without the "JSJitInfo::" bit.
 
         args is None if we don't want to output argTypes for some
         reason (e.g. we have overloads or we're not a method) and
         otherwise an iterable of the arguments for this method.
         """
         assert(not movable or aliasSet != "AliasEverything")  # Can't move write-aliasing things
-        assert(not hasSlot or movable)  # Things with slots had better be movable
+        assert(not alwaysInSlot or movable)  # Things always in slots had better be movable
 
         def jitInfoInitializer(isTypedMethod):
             initializer = fill(
                 """
                 {
                  { ${opName} },
                   prototypes::id::${name},
                   PrototypeTraits<prototypes::id::${name}>::Depth,
                   JSJitInfo::${opType},
                   JSJitInfo::${aliasSet}, /* aliasSet.  Not relevant for setters. */
                   ${returnType},  /* returnType.  Not relevant for setters. */
                   ${isInfallible},  /* isInfallible. False in setters. */
                   ${isMovable},  /* isMovable.  Not relevant for setters. */
-                  ${isInSlot},  /* isInSlot.  Only relevant for getters. */
+                  ${isAlwaysInSlot}, /* isAlwaysInSlot.  Only relevant for getters. */
+                  ${isLazilyCachedInSlot}, /* isLazilyCachedInSlot.  Only relevant for getters. */
                   ${isTypedMethod},  /* isTypedMethod.  Only relevant for methods. */
                   ${slotIndex}   /* Reserved slot index, if we're stored in a slot, else 0. */
                 }
                 """,
                 opName=opName,
                 name=self.descriptor.name,
                 opType=opType,
                 aliasSet=aliasSet,
                 returnType=reduce(CGMemberJITInfo.getSingleReturnType, returnTypes,
                                   ""),
                 isInfallible=toStringBool(infallible),
                 isMovable=toStringBool(movable),
-                isInSlot=toStringBool(hasSlot),
+                isAlwaysInSlot=toStringBool(alwaysInSlot),
+                isLazilyCachedInSlot=toStringBool(lazilyInSlot),
                 isTypedMethod=toStringBool(isTypedMethod),
                 slotIndex=slotIndex)
             return initializer.rstrip()
 
         if args is not None:
             argTypes = "%s_argTypes" % infoName
             args = [CGMemberJITInfo.getJSArgType(arg.type) for arg in args]
             args.append("JSJitInfo::ArgTypeListEnd")
@@ -7563,39 +7566,44 @@ class CGMemberJITInfo(CGThing):
                 aliasSet = "AliasNone"
             elif getterpure:
                 aliasSet = "AliasDOMSets"
             else:
                 aliasSet = "AliasEverything"
             movable = getterpure and getterinfal
 
             getterinfal = getterinfal and infallibleForMember(self.member, self.member.type, self.descriptor)
-            isInSlot = self.member.getExtendedAttribute("StoreInSlot")
-            if isInSlot:
+            isAlwaysInSlot = self.member.getExtendedAttribute("StoreInSlot")
+            if self.member.slotIndex is not None:
+                assert isAlwaysInSlot or self.member.getExtendedAttribute("Cached")
+                isLazilyCachedInSlot = not isAlwaysInSlot
                 slotIndex = memberReservedSlot(self.member)
                 # We'll statically assert that this is not too big in
-                # CGUpdateMemberSlotsMethod
-            else:
+                # CGUpdateMemberSlotsMethod, in the case when
+                # isAlwaysInSlot is true.
+            else:
+                isLazilyCachedInSlot = False
                 slotIndex = "0"
 
             result = self.defineJitInfo(getterinfo, getter, "Getter",
                                         getterinfal, movable, aliasSet,
-                                        isInSlot, slotIndex,
+                                        isAlwaysInSlot, isLazilyCachedInSlot,
+                                        slotIndex,
                                         [self.member.type], None)
             if (not self.member.readonly or
                 self.member.getExtendedAttribute("PutForwards") is not None or
                 self.member.getExtendedAttribute("Replaceable") is not None):
                 setterinfo = ("%s_setterinfo" % self.member.identifier.name)
                 # Actually a JSJitSetterOp, but JSJitGetterOp is first in the
                 # union.
                 setter = ("(JSJitGetterOp)set_%s" % self.member.identifier.name)
                 # Setters are always fallible, since they have to do a typed unwrap.
                 result += self.defineJitInfo(setterinfo, setter, "Setter",
                                              False, False, "AliasEverything",
-                                             False, "0",
+                                             False, False, "0",
                                              [BuiltinTypes[IDLBuiltinType.Types.void]],
                                              None)
             return result
         if self.member.isMethod():
             methodinfo = ("%s_methodinfo" % self.member.identifier.name)
             name = CppKeywords.checkMethodName(self.member.identifier.name)
             if self.member.returnsPromise():
                 name = CGMethodPromiseWrapper.makeName(name)
@@ -7636,17 +7644,18 @@ class CGMemberJITInfo(CGThing):
                 else:
                     args = None
 
             if args is not None:
                 aliasSet = "AliasDOMSets"
             else:
                 aliasSet = "AliasEverything"
             result = self.defineJitInfo(methodinfo, method, "Method",
-                                        methodInfal, movable, aliasSet, False, "0",
+                                        methodInfal, movable, aliasSet,
+                                        False, False, "0",
                                         [s[0] for s in sigs], args)
             return result
         raise TypeError("Illegal member type to CGPropertyJITInfo")
 
     @staticmethod
     def getJSReturnTypeTag(t):
         if t.nullable():
             # Sometimes it might return null, sometimes not
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -224,17 +224,17 @@ TelephonyListener::NotifyError(uint32_t 
 
   if (aCallIndex > 0) {
     // In order to not miss any related call state transition.
     // It's possible that 3G network signal lost for unknown reason.
     // If a call is released abnormally, NotifyError() will be called,
     // instead of CallStateChanged(). We need to reset the call array state
     // via setting CALL_STATE_DISCONNECTED
     hfp->HandleCallStateChanged(aCallIndex,
-                                nsITelephonyProvider::CALL_STATE_DISCONNECTED,
+                                nsITelephonyService::CALL_STATE_DISCONNECTED,
                                 aError, EmptyString(), false, false, true);
     BT_WARNING("Reset the call state due to call transition ends abnormally");
   }
 
   BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
   return NS_OK;
 }
 
@@ -278,25 +278,25 @@ TelephonyListener::NotifyCdmaCallWaiting
   hfp->UpdateSecondNumber(aNumber);
 
   return NS_OK;
 }
 
 bool
 TelephonyListener::Listen(bool aStart)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, false);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, false);
 
   nsresult rv;
   if (aStart) {
-    rv = provider->RegisterListener(this);
+    rv = service->RegisterListener(this);
   } else {
-    rv = provider->UnregisterListener(this);
+    rv = service->UnregisterListener(this);
   }
 
   return NS_SUCCEEDED(rv);
 }
 
 /**
  *  BluetoothRilListener
  */
@@ -389,24 +389,24 @@ BluetoothRilListener::ServiceChanged(uin
 
   BT_LOGR("%d client %d. new mClientId %d", aRegistered, aClientId,
           (mClientId < mMobileConnListeners.Length()) ? mClientId : -1);
 }
 
 void
 BluetoothRilListener::EnumerateCalls()
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE_VOID(provider);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
 
   nsCOMPtr<nsITelephonyListener> listener(
     do_QueryObject(mTelephonyListener));
 
-  provider->EnumerateCalls(listener);
+  service->EnumerateCalls(listener);
 }
 
 bool
 BluetoothRilListener::ListenMobileConnAndIccInfo(bool aStart)
 {
   /**
    * mClientId < number of total clients:
    *   The client with mClientId is available. Start/Stop listening
--- a/dom/bluetooth/BluetoothRilListener.h
+++ b/dom/bluetooth/BluetoothRilListener.h
@@ -8,17 +8,17 @@
 #define mozilla_dom_bluetooth_bluetoothrillistener_h__
 
 #include "BluetoothCommon.h"
 
 #include "nsAutoPtr.h"
 
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionProvider.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothRilListener;
 
 class IccListener : public nsIIccListener
 {
 public:
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -18,17 +18,17 @@
 #include "nsIAudioManager.h"
 #include "nsIDOMIccInfo.h"
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionProvider.h"
 #include "nsIMobileNetworkInfo.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #define MOZSETTINGS_CHANGED_ID               "mozsettings-changed"
 #define AUDIO_VOLUME_BT_SCO_ID               "audio.volume.bt_sco"
 
 /**
@@ -331,26 +331,26 @@ Call::Set(const nsAString& aNumber, cons
   if (aNumber.Length() && aNumber[0] == '+') {
     mType = BTHF_CALL_ADDRTYPE_INTERNATIONAL;
   }
 }
 
 void
 Call::Reset()
 {
-  mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  mState = nsITelephonyService::CALL_STATE_DISCONNECTED;
   mDirection = BTHF_CALL_DIRECTION_OUTGOING;
   mNumber.Truncate();
   mType = BTHF_CALL_ADDRTYPE_UNKNOWN;
 }
 
 bool
 Call::IsActive()
 {
-  return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
+  return (mState == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 
 /**
  *  BluetoothHfpManager
  */
 BluetoothHfpManager::BluetoothHfpManager() : mPhoneType(PhoneType::NONE)
 {
   Reset();
@@ -669,18 +669,18 @@ BluetoothHfpManager::ProcessAtCnum()
   SendResponse(BTHF_AT_RESPONSE_OK);
 }
 
 void
 BluetoothHfpManager::ProcessAtCind()
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  int numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-  int numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+  int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+  int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
 
   bt_status_t status = sBluetoothHfpInterface->cind_response(
                           mService,
                           numActive,
                           numHeld,
                           ConvertToBthfCallState(GetCallSetupState()),
                           mSignal,
                           mRoam,
@@ -725,20 +725,20 @@ BluetoothHfpManager::ProcessUnknownAt(ch
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
     sBluetoothHfpInterface->at_response(BTHF_AT_RESPONSE_ERROR, 0));
 }
 
 void
 BluetoothHfpManager::ProcessKeyPressed()
 {
   bool hasActiveCall =
-    (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED) > 0);
+    (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
 
   // Refer to AOSP HeadsetStateMachine.processKeyPressed
-  if (FindFirstCall(nsITelephonyProvider::CALL_STATE_INCOMING)
+  if (FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING)
       && !hasActiveCall) {
     /**
      * Bluetooth HSP spec 4.2.2
      * There is an incoming call, notify Dialer to pick up the phone call
      * and SCO will be established after we get the CallStateChanged event
      * indicating the call is answered successfully.
      */
     ProcessAnswerCall();
@@ -970,28 +970,28 @@ BluetoothHfpManager::HandleShutdown()
   DisconnectSco();
   sBluetoothHfpManager = nullptr;
 }
 
 void
 BluetoothHfpManager::SendCLCC(Call& aCall, int aIndex)
 {
   NS_ENSURE_TRUE_VOID(aCall.mState !=
-                        nsITelephonyProvider::CALL_STATE_DISCONNECTED);
+                        nsITelephonyService::CALL_STATE_DISCONNECTED);
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   bthf_call_state_t callState = ConvertToBthfCallState(aCall.mState);
 
   if (mPhoneType == PhoneType::CDMA && aIndex == 1 && aCall.IsActive()) {
     callState = (mCdmaSecondCall.IsActive()) ? BTHF_CALL_STATE_HELD :
                                                BTHF_CALL_STATE_ACTIVE;
   }
 
   if (callState == BTHF_CALL_STATE_INCOMING &&
-      FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+      FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
     callState = BTHF_CALL_STATE_WAITING;
   }
 
   bt_status_t status = sBluetoothHfpInterface->clcc_response(
                           aIndex,
                           aCall.mDirection,
                           callState,
                           BTHF_CALL_TYPE_VOICE,
@@ -1017,18 +1017,18 @@ BluetoothHfpManager::SendResponse(bthf_a
     sBluetoothHfpInterface->at_response(aResponseCode, 0));
 }
 
 void
 BluetoothHfpManager::UpdatePhoneCIND(uint32_t aCallIndex)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  int numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-  int numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+  int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+  int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
   bthf_call_state_t callSetupState =
     ConvertToBthfCallState(GetCallSetupState());
   nsAutoCString number =
     NS_ConvertUTF16toUTF8(mCurrentCallArray[aCallIndex].mNumber);
   bthf_call_addrtype_t type = mCurrentCallArray[aCallIndex].mType;
 
   BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] setupstate[%d]",
           aCallIndex, mCurrentCallArray[aCallIndex].mState,
@@ -1083,43 +1083,43 @@ BluetoothHfpManager::GetNumberOfCalls(ui
 
 uint16_t
 BluetoothHfpManager::GetCallSetupState()
 {
   uint32_t callLength = mCurrentCallArray.Length();
 
   for (uint32_t i = 1; i < callLength; ++i) {
     switch (mCurrentCallArray[i].mState) {
-      case nsITelephonyProvider::CALL_STATE_INCOMING:
-      case nsITelephonyProvider::CALL_STATE_DIALING:
-      case nsITelephonyProvider::CALL_STATE_ALERTING:
+      case nsITelephonyService::CALL_STATE_INCOMING:
+      case nsITelephonyService::CALL_STATE_DIALING:
+      case nsITelephonyService::CALL_STATE_ALERTING:
         return mCurrentCallArray[i].mState;
       default:
         break;
     }
   }
 
-  return nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  return nsITelephonyService::CALL_STATE_DISCONNECTED;
 }
 
 bthf_call_state_t
 BluetoothHfpManager::ConvertToBthfCallState(int aCallState)
 {
   bthf_call_state_t state;
 
   // Refer to AOSP BluetoothPhoneService.convertCallState
-  if (aCallState == nsITelephonyProvider::CALL_STATE_INCOMING) {
+  if (aCallState == nsITelephonyService::CALL_STATE_INCOMING) {
     state = BTHF_CALL_STATE_INCOMING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_DIALING) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_DIALING) {
     state = BTHF_CALL_STATE_DIALING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_ALERTING) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_ALERTING) {
     state = BTHF_CALL_STATE_ALERTING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_CONNECTED) {
     state = BTHF_CALL_STATE_ACTIVE;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_HELD) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_HELD) {
     state = BTHF_CALL_STATE_HELD;
   } else { // disconnected
     state = BTHF_CALL_STATE_IDLE;
   }
 
   return state;
 }
 
@@ -1132,21 +1132,21 @@ BluetoothHfpManager::IsTransitionState(u
    * - the call becomes held, and numHeld > 1 or an incoming call exists
    *
    * TODO:
    * 1) handle CHLD=1 transition state
    * 2) handle conference call cases
    */
   if (!aIsConference) {
     switch (aCallState) {
-      case nsITelephonyProvider::CALL_STATE_CONNECTED:
+      case nsITelephonyService::CALL_STATE_CONNECTED:
         return (GetNumberOfCalls(aCallState) > 1);
-      case nsITelephonyProvider::CALL_STATE_HELD:
+      case nsITelephonyService::CALL_STATE_HELD:
         return (GetNumberOfCalls(aCallState) > 1 ||
-                FindFirstCall(nsITelephonyProvider::CALL_STATE_INCOMING));
+                FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING));
       default:
         break;
     }
   }
 
   return false;
 }
 
@@ -1183,27 +1183,27 @@ BluetoothHfpManager::HandleCallStateChan
 
   // Notify bluedroid of phone state change if this
   // call state change is not during transition state
   if (!IsTransitionState(aCallState, aIsConference)) {
     UpdatePhoneCIND(aCallIndex);
   }
 
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       // We've send Dialer a dialing request and this is the response.
       if (!mDialingRequestProcessed) {
         SendResponse(BTHF_AT_RESPONSE_OK);
         mDialingRequestProcessed = true;
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+    case nsITelephonyService::CALL_STATE_DISCONNECTED:
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
-          GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_DISCONNECTED)) {
+          GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
         // we postpone the timing of dropping SCO.
         if (aError.EqualsLiteral("BusyError")) {
           // FIXME: UpdatePhoneCIND later since it causes SCO close but
           // Dialer is still playing busy tone via HF.
           BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_CLOSE_SCO);
         }
 
@@ -1248,17 +1248,17 @@ BluetoothHfpManager::UpdateSecondNumber(
 
 void
 BluetoothHfpManager::AnswerWaitingCall()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Pick up second call. First call is held now.
-  mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
+  mCdmaSecondCall.mState = nsITelephonyService::CALL_STATE_CONNECTED;
   // FIXME: check CDMA + bluedroid
   //UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
 
   //sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
   //SendCommand("+CIEV: ", CINDType::CALLHELD);
 }
 
 void
@@ -1275,18 +1275,18 @@ BluetoothHfpManager::IgnoreWaitingCall()
 void
 BluetoothHfpManager::ToggleCalls()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
-                             nsITelephonyProvider::CALL_STATE_HELD :
-                             nsITelephonyProvider::CALL_STATE_CONNECTED;
+                             nsITelephonyService::CALL_STATE_HELD :
+                             nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
 bool
 BluetoothHfpManager::ConnectSco()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE(!sInShutdown, false);
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp
@@ -25,17 +25,17 @@
 #include "nsServiceManagerUtils.h"
 
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMIccInfo.h"
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionProvider.h"
 #include "nsIMobileNetworkInfo.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 #include "nsRadioInterfaceLayer.h"
 #endif
 
 /**
  * BRSF bitmask of AG supported features. See 4.34.1 "Bluetooth Defined AT
  * Capabilities" in Bluetooth hands-free profile 1.6
  */
 #define BRSF_BIT_THREE_WAY_CALLING         1
@@ -328,27 +328,27 @@ IsMandatoryIndicator(const CINDType aTyp
 Call::Call()
 {
   Reset();
 }
 
 void
 Call::Reset()
 {
-  mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  mState = nsITelephonyService::CALL_STATE_DISCONNECTED;
   mDirection = false;
   mIsConference = false;
   mNumber.Truncate();
   mType = TOA_UNKNOWN;
 }
 
 bool
 Call::IsActive()
 {
-  return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
+  return (mState == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 #endif // MOZ_B2G_RIL
 
 /**
  *  BluetoothHfpManager
  */
 BluetoothHfpManager::BluetoothHfpManager()
 {
@@ -1200,45 +1200,45 @@ BluetoothHfpManager::SendCCWA(const nsAS
     ccwaMsg.AppendInt(aType);
     SendLine(ccwaMsg.get());
   }
 }
 
 bool
 BluetoothHfpManager::SendCLCC(const Call& aCall, int aIndex)
 {
-  if (aCall.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+  if (aCall.mState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     return true;
   }
 
   nsAutoCString message(RESPONSE_CLCC);
   message.AppendInt(aIndex);
   message.Append(',');
   message.AppendInt(aCall.mDirection);
   message.Append(',');
 
   int status = 0;
   switch (aCall.mState) {
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       if (mPhoneType == PhoneType::CDMA && aIndex == 1) {
         status = (mCdmaSecondCall.IsActive()) ? 1 : 0;
       }
       message.AppendInt(status);
       break;
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       message.AppendInt(1);
       break;
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       message.AppendInt(2);
       break;
-    case nsITelephonyProvider::CALL_STATE_ALERTING:
+    case nsITelephonyService::CALL_STATE_ALERTING:
       message.AppendInt(3);
       break;
-    case nsITelephonyProvider::CALL_STATE_INCOMING:
-      if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+    case nsITelephonyService::CALL_STATE_INCOMING:
+      if (!FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         message.AppendInt(4);
       } else {
         message.AppendInt(5);
       }
       break;
     default:
       BT_WARNING("Not handling call status for CLCC");
       break;
@@ -1452,21 +1452,21 @@ BluetoothHfpManager::HandleCallStateChan
     mCurrentCallArray[aCallIndex].mType = TOA_INTERNATIONAL;
   }
   mCurrentCallArray[aCallIndex].mNumber = aNumber;
 
   nsRefPtr<nsRunnable> sendRingTask;
   nsString address;
 
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_CONNECTED: {
-          uint32_t numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-          uint32_t numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+        case nsITelephonyService::CALL_STATE_CONNECTED: {
+          uint32_t numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+          uint32_t numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
           uint32_t numConCalls = GetNumberOfConCalls();
 
           /**
            * An active call becomes a held call.
            *
            * If this call is not a conference call,
            * - callheld state = ONHOLD_NOACTIVE if no active call remains;
            * - callheld state = ONHOLD_ACTIVE otherwise.
@@ -1484,42 +1484,42 @@ BluetoothHfpManager::HandleCallStateChan
             if (numActive + numHeld == 1) {
               // A single active call is put on hold.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
             } else {
               // An active call is placed on hold or active/held calls swapped.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             }
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
-          } else if (GetNumberOfConCalls(nsITelephonyProvider::CALL_STATE_HELD)
+          } else if (GetNumberOfConCalls(nsITelephonyService::CALL_STATE_HELD)
                      == numConCalls) {
             if (numActive + numHeld == numConCalls) {
               // An active conference call is put on hold.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
             } else {
               // Active calls are placed on hold or active/held calls swapped.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             }
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
           }
           break;
         }
-        case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+        case nsITelephonyService::CALL_STATE_DISCONNECTED:
           // The call state changed from DISCONNECTED to HELD. It could happen
           // when user held a call before Bluetooth got connected.
-          if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+          if (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
             // callheld = ONHOLD_ACTIVE if an active call already exists.
             sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
           }
           break;
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_INCOMING:
-      if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+    case nsITelephonyService::CALL_STATE_INCOMING:
+      if (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         SendCCWA(aNumber, mCurrentCallArray[aCallIndex].mType);
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
       } else {
         // Start sending RING indicator to HF
         sStopSendingRingFlag = false;
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
 
         if (mBSIR) {
@@ -1534,114 +1534,114 @@ BluetoothHfpManager::HandleCallStateChan
 
         MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           new SendRingIndicatorTask(number,
                                     mCurrentCallArray[aCallIndex].mType),
           sRingInterval);
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       if (!mDialingRequestProcessed) {
         SendLine("OK");
         mDialingRequestProcessed = true;
       }
 
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING, aSend);
       ConnectSco();
       break;
-    case nsITelephonyProvider::CALL_STATE_ALERTING:
+    case nsITelephonyService::CALL_STATE_ALERTING:
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING_ALERTING, aSend);
 
       // If there's an ongoing call when the headset is just connected, we have
       // to open a sco socket here.
       ConnectSco();
       break;
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       /**
        * A call becomes active because:
        * - user answers an incoming call,
        * - user dials a outgoing call and it is answered, or
        * - SLC is connected when a call is active.
        */
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_INCOMING:
-        case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+        case nsITelephonyService::CALL_STATE_INCOMING:
+        case nsITelephonyService::CALL_STATE_DISCONNECTED:
           // Incoming call, no break
           sStopSendingRingFlag = true;
           ConnectSco();
           // NO BREAK HERE. continue to next statement
-        case nsITelephonyProvider::CALL_STATE_DIALING:
-        case nsITelephonyProvider::CALL_STATE_ALERTING:
+        case nsITelephonyService::CALL_STATE_DIALING:
+        case nsITelephonyService::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend);
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
 
-          if (FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+          if (FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
             // callheld state = ONHOLD_ACTIVE if a held call already exists.
             UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
           }
           break;
-        case nsITelephonyProvider::CALL_STATE_CONNECTED:
+        case nsITelephonyService::CALL_STATE_CONNECTED:
           // User wants to add a held call to the conversation.
           // The original connected call becomes a conference call here.
           if (aIsConference) {
             UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
           }
           break;
-        case nsITelephonyProvider::CALL_STATE_HELD:
-          if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+        case nsITelephonyService::CALL_STATE_HELD:
+          if (!FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
             if (aIsConference && !prevCallIsConference) {
               // The held call was merged and becomes a conference call.
               UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
             } else if (sCINDItems[CINDType::CALLHELD].value ==
                        CallHeldState::ONHOLD_NOACTIVE) {
               // The held call(s) become connected call(s).
               UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
             }
           }
           break;
 
         default:
           BT_WARNING("Not handling state changed");
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+    case nsITelephonyService::CALL_STATE_DISCONNECTED:
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_INCOMING:
+        case nsITelephonyService::CALL_STATE_INCOMING:
           // Incoming call, no break
           sStopSendingRingFlag = true;
-        case nsITelephonyProvider::CALL_STATE_DIALING:
-        case nsITelephonyProvider::CALL_STATE_ALERTING:
+        case nsITelephonyService::CALL_STATE_DIALING:
+        case nsITelephonyService::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
           break;
-        case nsITelephonyProvider::CALL_STATE_CONNECTED:
+        case nsITelephonyService::CALL_STATE_CONNECTED:
           // No call is ongoing
           if (sCINDItems[CINDType::CALLHELD].value ==
               CallHeldState::NO_CALLHELD) {
             UpdateCIND(CINDType::CALL, CallState::NO_CALL, aSend);
           }
           break;
         default:
           BT_WARNING("Not handling state changed");
       }
 
       // Handle held calls separately
-      if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+      if (!FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
-      } else if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+      } else if (!FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_NOACTIVE, aSend);
       } else {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
       }
 
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
-          GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_DISCONNECTED)) {
+          GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
         // we postpone the timing of dropping SCO.
         if (!(aError.EqualsLiteral("BusyError"))) {
           DisconnectSco();
         } else {
           // Close Sco later since Dialer is still playing busy tone via HF.
           MessageLoop::current()->PostDelayedTask(FROM_HERE,
                                                   new CloseScoTask(),
@@ -1694,17 +1694,17 @@ BluetoothHfpManager::UpdateSecondNumber(
 
 void
 BluetoothHfpManager::AnswerWaitingCall()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Pick up second call. First call is held now.
-  mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
+  mCdmaSecondCall.mState = nsITelephonyService::CALL_STATE_CONNECTED;
   UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
 
   sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
   SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
 }
 
 void
 BluetoothHfpManager::IgnoreWaitingCall()
@@ -1719,18 +1719,18 @@ BluetoothHfpManager::IgnoreWaitingCall()
 void
 BluetoothHfpManager::ToggleCalls()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
-                             nsITelephonyProvider::CALL_STATE_HELD :
-                             nsITelephonyProvider::CALL_STATE_CONNECTED;
+                             nsITelephonyService::CALL_STATE_HELD :
+                             nsITelephonyService::CALL_STATE_CONNECTED;
 }
 #endif // MOZ_B2G_RIL
 
 void
 BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
 {
   MOZ_ASSERT(aSocket);
 #ifdef MOZ_B2G_RIL
--- a/dom/bluetooth2/BluetoothRilListener.cpp
+++ b/dom/bluetooth2/BluetoothRilListener.cpp
@@ -224,17 +224,17 @@ TelephonyListener::NotifyError(uint32_t 
 
   if (aCallIndex > 0) {
     // In order to not miss any related call state transition.
     // It's possible that 3G network signal lost for unknown reason.
     // If a call is released abnormally, NotifyError() will be called,
     // instead of CallStateChanged(). We need to reset the call array state
     // via setting CALL_STATE_DISCONNECTED
     hfp->HandleCallStateChanged(aCallIndex,
-                                nsITelephonyProvider::CALL_STATE_DISCONNECTED,
+                                nsITelephonyService::CALL_STATE_DISCONNECTED,
                                 aError, EmptyString(), false, false, true);
     BT_WARNING("Reset the call state due to call transition ends abnormally");
   }
 
   BT_WARNING(NS_ConvertUTF16toUTF8(aError).get());
   return NS_OK;
 }
 
@@ -278,25 +278,25 @@ TelephonyListener::NotifyCdmaCallWaiting
   hfp->UpdateSecondNumber(aNumber);
 
   return NS_OK;
 }
 
 bool
 TelephonyListener::Listen(bool aStart)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, false);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, false);
 
   nsresult rv;
   if (aStart) {
-    rv = provider->RegisterListener(this);
+    rv = service->RegisterListener(this);
   } else {
-    rv = provider->UnregisterListener(this);
+    rv = service->UnregisterListener(this);
   }
 
   return NS_SUCCEEDED(rv);
 }
 
 /**
  *  BluetoothRilListener
  */
@@ -389,24 +389,24 @@ BluetoothRilListener::ServiceChanged(uin
 
   BT_LOGR("%d client %d. new mClientId %d", aRegistered, aClientId,
           (mClientId < mMobileConnListeners.Length()) ? mClientId : -1);
 }
 
 void
 BluetoothRilListener::EnumerateCalls()
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE_VOID(provider);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
 
   nsCOMPtr<nsITelephonyListener> listener(
     do_QueryObject(mTelephonyListener));
 
-  provider->EnumerateCalls(listener);
+  service->EnumerateCalls(listener);
 }
 
 bool
 BluetoothRilListener::ListenMobileConnAndIccInfo(bool aStart)
 {
   /**
    * mClientId < number of total clients:
    *   The client with mClientId is available. Start/Stop listening
--- a/dom/bluetooth2/BluetoothRilListener.h
+++ b/dom/bluetooth2/BluetoothRilListener.h
@@ -8,17 +8,17 @@
 #define mozilla_dom_bluetooth_bluetoothrillistener_h__
 
 #include "BluetoothCommon.h"
 
 #include "nsAutoPtr.h"
 
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionProvider.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothRilListener;
 
 class IccListener : public nsIIccListener
 {
 public:
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -18,17 +18,17 @@
 #include "nsIAudioManager.h"
 #include "nsIDOMIccInfo.h"
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionProvider.h"
 #include "nsIMobileNetworkInfo.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 
 #define MOZSETTINGS_CHANGED_ID               "mozsettings-changed"
 #define AUDIO_VOLUME_BT_SCO_ID               "audio.volume.bt_sco"
 
 /**
@@ -331,26 +331,26 @@ Call::Set(const nsAString& aNumber, cons
   if (aNumber.Length() && aNumber[0] == '+') {
     mType = BTHF_CALL_ADDRTYPE_INTERNATIONAL;
   }
 }
 
 void
 Call::Reset()
 {
-  mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  mState = nsITelephonyService::CALL_STATE_DISCONNECTED;
   mDirection = BTHF_CALL_DIRECTION_OUTGOING;
   mNumber.Truncate();
   mType = BTHF_CALL_ADDRTYPE_UNKNOWN;
 }
 
 bool
 Call::IsActive()
 {
-  return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
+  return (mState == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 
 /**
  *  BluetoothHfpManager
  */
 BluetoothHfpManager::BluetoothHfpManager() : mPhoneType(PhoneType::NONE)
 {
   Reset();
@@ -669,18 +669,18 @@ BluetoothHfpManager::ProcessAtCnum()
   SendResponse(BTHF_AT_RESPONSE_OK);
 }
 
 void
 BluetoothHfpManager::ProcessAtCind()
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  int numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-  int numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+  int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+  int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
 
   bt_status_t status = sBluetoothHfpInterface->cind_response(
                           mService,
                           numActive,
                           numHeld,
                           ConvertToBthfCallState(GetCallSetupState()),
                           mSignal,
                           mRoam,
@@ -725,20 +725,20 @@ BluetoothHfpManager::ProcessUnknownAt(ch
   NS_ENSURE_TRUE_VOID(BT_STATUS_SUCCESS ==
     sBluetoothHfpInterface->at_response(BTHF_AT_RESPONSE_ERROR, 0));
 }
 
 void
 BluetoothHfpManager::ProcessKeyPressed()
 {
   bool hasActiveCall =
-    (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED) > 0);
+    (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED) > 0);
 
   // Refer to AOSP HeadsetStateMachine.processKeyPressed
-  if (FindFirstCall(nsITelephonyProvider::CALL_STATE_INCOMING)
+  if (FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING)
       && !hasActiveCall) {
     /**
      * Bluetooth HSP spec 4.2.2
      * There is an incoming call, notify Dialer to pick up the phone call
      * and SCO will be established after we get the CallStateChanged event
      * indicating the call is answered successfully.
      */
     ProcessAnswerCall();
@@ -970,28 +970,28 @@ BluetoothHfpManager::HandleShutdown()
   DisconnectSco();
   sBluetoothHfpManager = nullptr;
 }
 
 void
 BluetoothHfpManager::SendCLCC(Call& aCall, int aIndex)
 {
   NS_ENSURE_TRUE_VOID(aCall.mState !=
-                        nsITelephonyProvider::CALL_STATE_DISCONNECTED);
+                        nsITelephonyService::CALL_STATE_DISCONNECTED);
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
   bthf_call_state_t callState = ConvertToBthfCallState(aCall.mState);
 
   if (mPhoneType == PhoneType::CDMA && aIndex == 1 && aCall.IsActive()) {
     callState = (mCdmaSecondCall.IsActive()) ? BTHF_CALL_STATE_HELD :
                                                BTHF_CALL_STATE_ACTIVE;
   }
 
   if (callState == BTHF_CALL_STATE_INCOMING &&
-      FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+      FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
     callState = BTHF_CALL_STATE_WAITING;
   }
 
   bt_status_t status = sBluetoothHfpInterface->clcc_response(
                           aIndex,
                           aCall.mDirection,
                           callState,
                           BTHF_CALL_TYPE_VOICE,
@@ -1017,18 +1017,18 @@ BluetoothHfpManager::SendResponse(bthf_a
     sBluetoothHfpInterface->at_response(aResponseCode, 0));
 }
 
 void
 BluetoothHfpManager::UpdatePhoneCIND(uint32_t aCallIndex)
 {
   NS_ENSURE_TRUE_VOID(sBluetoothHfpInterface);
 
-  int numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-  int numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+  int numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+  int numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
   bthf_call_state_t callSetupState =
     ConvertToBthfCallState(GetCallSetupState());
   nsAutoCString number =
     NS_ConvertUTF16toUTF8(mCurrentCallArray[aCallIndex].mNumber);
   bthf_call_addrtype_t type = mCurrentCallArray[aCallIndex].mType;
 
   BT_LOGR("[%d] state %d => BTHF: active[%d] held[%d] setupstate[%d]",
           aCallIndex, mCurrentCallArray[aCallIndex].mState,
@@ -1083,43 +1083,43 @@ BluetoothHfpManager::GetNumberOfCalls(ui
 
 uint16_t
 BluetoothHfpManager::GetCallSetupState()
 {
   uint32_t callLength = mCurrentCallArray.Length();
 
   for (uint32_t i = 1; i < callLength; ++i) {
     switch (mCurrentCallArray[i].mState) {
-      case nsITelephonyProvider::CALL_STATE_INCOMING:
-      case nsITelephonyProvider::CALL_STATE_DIALING:
-      case nsITelephonyProvider::CALL_STATE_ALERTING:
+      case nsITelephonyService::CALL_STATE_INCOMING:
+      case nsITelephonyService::CALL_STATE_DIALING:
+      case nsITelephonyService::CALL_STATE_ALERTING:
         return mCurrentCallArray[i].mState;
       default:
         break;
     }
   }
 
-  return nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  return nsITelephonyService::CALL_STATE_DISCONNECTED;
 }
 
 bthf_call_state_t
 BluetoothHfpManager::ConvertToBthfCallState(int aCallState)
 {
   bthf_call_state_t state;
 
   // Refer to AOSP BluetoothPhoneService.convertCallState
-  if (aCallState == nsITelephonyProvider::CALL_STATE_INCOMING) {
+  if (aCallState == nsITelephonyService::CALL_STATE_INCOMING) {
     state = BTHF_CALL_STATE_INCOMING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_DIALING) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_DIALING) {
     state = BTHF_CALL_STATE_DIALING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_ALERTING) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_ALERTING) {
     state = BTHF_CALL_STATE_ALERTING;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_CONNECTED) {
     state = BTHF_CALL_STATE_ACTIVE;
-  } else if (aCallState == nsITelephonyProvider::CALL_STATE_HELD) {
+  } else if (aCallState == nsITelephonyService::CALL_STATE_HELD) {
     state = BTHF_CALL_STATE_HELD;
   } else { // disconnected
     state = BTHF_CALL_STATE_IDLE;
   }
 
   return state;
 }
 
@@ -1132,21 +1132,21 @@ BluetoothHfpManager::IsTransitionState(u
    * - the call becomes held, and numHeld > 1 or an incoming call exists
    *
    * TODO:
    * 1) handle CHLD=1 transition state
    * 2) handle conference call cases
    */
   if (!aIsConference) {
     switch (aCallState) {
-      case nsITelephonyProvider::CALL_STATE_CONNECTED:
+      case nsITelephonyService::CALL_STATE_CONNECTED:
         return (GetNumberOfCalls(aCallState) > 1);
-      case nsITelephonyProvider::CALL_STATE_HELD:
+      case nsITelephonyService::CALL_STATE_HELD:
         return (GetNumberOfCalls(aCallState) > 1 ||
-                FindFirstCall(nsITelephonyProvider::CALL_STATE_INCOMING));
+                FindFirstCall(nsITelephonyService::CALL_STATE_INCOMING));
       default:
         break;
     }
   }
 
   return false;
 }
 
@@ -1183,27 +1183,27 @@ BluetoothHfpManager::HandleCallStateChan
 
   // Notify bluedroid of phone state change if this
   // call state change is not during transition state
   if (!IsTransitionState(aCallState, aIsConference)) {
     UpdatePhoneCIND(aCallIndex);
   }
 
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       // We've send Dialer a dialing request and this is the response.
       if (!mDialingRequestProcessed) {
         SendResponse(BTHF_AT_RESPONSE_OK);
         mDialingRequestProcessed = true;
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+    case nsITelephonyService::CALL_STATE_DISCONNECTED:
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
-          GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_DISCONNECTED)) {
+          GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
         // we postpone the timing of dropping SCO.
         if (aError.Equals(NS_LITERAL_STRING("BusyError"))) {
           // FIXME: UpdatePhoneCIND later since it causes SCO close but
           // Dialer is still playing busy tone via HF.
           BT_HF_DISPATCH_MAIN(MainThreadTaskCmd::POST_TASK_CLOSE_SCO);
         }
 
@@ -1248,17 +1248,17 @@ BluetoothHfpManager::UpdateSecondNumber(
 
 void
 BluetoothHfpManager::AnswerWaitingCall()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Pick up second call. First call is held now.
-  mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
+  mCdmaSecondCall.mState = nsITelephonyService::CALL_STATE_CONNECTED;
   // FIXME: check CDMA + bluedroid
   //UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
 
   //sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
   //SendCommand("+CIEV: ", CINDType::CALLHELD);
 }
 
 void
@@ -1275,18 +1275,18 @@ BluetoothHfpManager::IgnoreWaitingCall()
 void
 BluetoothHfpManager::ToggleCalls()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
-                             nsITelephonyProvider::CALL_STATE_HELD :
-                             nsITelephonyProvider::CALL_STATE_CONNECTED;
+                             nsITelephonyService::CALL_STATE_HELD :
+                             nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
 bool
 BluetoothHfpManager::ConnectSco()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   NS_ENSURE_TRUE(!sInShutdown, false);
--- a/dom/bluetooth2/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluez/BluetoothHfpManager.cpp
@@ -25,17 +25,17 @@
 #include "nsServiceManagerUtils.h"
 
 #ifdef MOZ_B2G_RIL
 #include "nsIDOMIccInfo.h"
 #include "nsIIccProvider.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionProvider.h"
 #include "nsIMobileNetworkInfo.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 #include "nsRadioInterfaceLayer.h"
 #endif
 
 /**
  * BRSF bitmask of AG supported features. See 4.34.1 "Bluetooth Defined AT
  * Capabilities" in Bluetooth hands-free profile 1.6
  */
 #define BRSF_BIT_THREE_WAY_CALLING         1
@@ -328,27 +328,27 @@ IsMandatoryIndicator(const CINDType aTyp
 Call::Call()
 {
   Reset();
 }
 
 void
 Call::Reset()
 {
-  mState = nsITelephonyProvider::CALL_STATE_DISCONNECTED;
+  mState = nsITelephonyService::CALL_STATE_DISCONNECTED;
   mDirection = false;
   mIsConference = false;
   mNumber.Truncate();
   mType = TOA_UNKNOWN;
 }
 
 bool
 Call::IsActive()
 {
-  return (mState == nsITelephonyProvider::CALL_STATE_CONNECTED);
+  return (mState == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 #endif // MOZ_B2G_RIL
 
 /**
  *  BluetoothHfpManager
  */
 BluetoothHfpManager::BluetoothHfpManager()
 {
@@ -1200,45 +1200,45 @@ BluetoothHfpManager::SendCCWA(const nsAS
     ccwaMsg.AppendInt(aType);
     SendLine(ccwaMsg.get());
   }
 }
 
 bool
 BluetoothHfpManager::SendCLCC(const Call& aCall, int aIndex)
 {
-  if (aCall.mState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+  if (aCall.mState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     return true;
   }
 
   nsAutoCString message(RESPONSE_CLCC);
   message.AppendInt(aIndex);
   message.Append(',');
   message.AppendInt(aCall.mDirection);
   message.Append(',');
 
   int status = 0;
   switch (aCall.mState) {
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       if (mPhoneType == PhoneType::CDMA && aIndex == 1) {
         status = (mCdmaSecondCall.IsActive()) ? 1 : 0;
       }
       message.AppendInt(status);
       break;
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       message.AppendInt(1);
       break;
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       message.AppendInt(2);
       break;
-    case nsITelephonyProvider::CALL_STATE_ALERTING:
+    case nsITelephonyService::CALL_STATE_ALERTING:
       message.AppendInt(3);
       break;
-    case nsITelephonyProvider::CALL_STATE_INCOMING:
-      if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+    case nsITelephonyService::CALL_STATE_INCOMING:
+      if (!FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         message.AppendInt(4);
       } else {
         message.AppendInt(5);
       }
       break;
     default:
       BT_WARNING("Not handling call status for CLCC");
       break;
@@ -1452,21 +1452,21 @@ BluetoothHfpManager::HandleCallStateChan
     mCurrentCallArray[aCallIndex].mType = TOA_INTERNATIONAL;
   }
   mCurrentCallArray[aCallIndex].mNumber = aNumber;
 
   nsRefPtr<nsRunnable> sendRingTask;
   nsString address;
 
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_CONNECTED: {
-          uint32_t numActive = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_CONNECTED);
-          uint32_t numHeld = GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_HELD);
+        case nsITelephonyService::CALL_STATE_CONNECTED: {
+          uint32_t numActive = GetNumberOfCalls(nsITelephonyService::CALL_STATE_CONNECTED);
+          uint32_t numHeld = GetNumberOfCalls(nsITelephonyService::CALL_STATE_HELD);
           uint32_t numConCalls = GetNumberOfConCalls();
 
           /**
            * An active call becomes a held call.
            *
            * If this call is not a conference call,
            * - callheld state = ONHOLD_NOACTIVE if no active call remains;
            * - callheld state = ONHOLD_ACTIVE otherwise.
@@ -1484,42 +1484,42 @@ BluetoothHfpManager::HandleCallStateChan
             if (numActive + numHeld == 1) {
               // A single active call is put on hold.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
             } else {
               // An active call is placed on hold or active/held calls swapped.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             }
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
-          } else if (GetNumberOfConCalls(nsITelephonyProvider::CALL_STATE_HELD)
+          } else if (GetNumberOfConCalls(nsITelephonyService::CALL_STATE_HELD)
                      == numConCalls) {
             if (numActive + numHeld == numConCalls) {
               // An active conference call is put on hold.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_NOACTIVE;
             } else {
               // Active calls are placed on hold or active/held calls swapped.
               sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             }
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
           }
           break;
         }
-        case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+        case nsITelephonyService::CALL_STATE_DISCONNECTED:
           // The call state changed from DISCONNECTED to HELD. It could happen
           // when user held a call before Bluetooth got connected.
-          if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+          if (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
             // callheld = ONHOLD_ACTIVE if an active call already exists.
             sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
             SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
           }
           break;
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_INCOMING:
-      if (FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+    case nsITelephonyService::CALL_STATE_INCOMING:
+      if (FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         SendCCWA(aNumber, mCurrentCallArray[aCallIndex].mType);
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
       } else {
         // Start sending RING indicator to HF
         sStopSendingRingFlag = false;
         UpdateCIND(CINDType::CALLSETUP, CallSetupState::INCOMING, aSend);
 
         if (mBSIR) {
@@ -1534,114 +1534,114 @@ BluetoothHfpManager::HandleCallStateChan
 
         MessageLoop::current()->PostDelayedTask(
           FROM_HERE,
           new SendRingIndicatorTask(number,
                                     mCurrentCallArray[aCallIndex].mType),
           sRingInterval);
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       if (!mDialingRequestProcessed) {
         SendLine("OK");
         mDialingRequestProcessed = true;
       }
 
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING, aSend);
       ConnectSco();
       break;
-    case nsITelephonyProvider::CALL_STATE_ALERTING:
+    case nsITelephonyService::CALL_STATE_ALERTING:
       UpdateCIND(CINDType::CALLSETUP, CallSetupState::OUTGOING_ALERTING, aSend);
 
       // If there's an ongoing call when the headset is just connected, we have
       // to open a sco socket here.
       ConnectSco();
       break;
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       /**
        * A call becomes active because:
        * - user answers an incoming call,
        * - user dials a outgoing call and it is answered, or
        * - SLC is connected when a call is active.
        */
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_INCOMING:
-        case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+        case nsITelephonyService::CALL_STATE_INCOMING:
+        case nsITelephonyService::CALL_STATE_DISCONNECTED:
           // Incoming call, no break
           sStopSendingRingFlag = true;
           ConnectSco();
           // NO BREAK HERE. continue to next statement
-        case nsITelephonyProvider::CALL_STATE_DIALING:
-        case nsITelephonyProvider::CALL_STATE_ALERTING:
+        case nsITelephonyService::CALL_STATE_DIALING:
+        case nsITelephonyService::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALL, CallState::IN_PROGRESS, aSend);
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
 
-          if (FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+          if (FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
             // callheld state = ONHOLD_ACTIVE if a held call already exists.
             UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
           }
           break;
-        case nsITelephonyProvider::CALL_STATE_CONNECTED:
+        case nsITelephonyService::CALL_STATE_CONNECTED:
           // User wants to add a held call to the conversation.
           // The original connected call becomes a conference call here.
           if (aIsConference) {
             UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
           }
           break;
-        case nsITelephonyProvider::CALL_STATE_HELD:
-          if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+        case nsITelephonyService::CALL_STATE_HELD:
+          if (!FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
             if (aIsConference && !prevCallIsConference) {
               // The held call was merged and becomes a conference call.
               UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
             } else if (sCINDItems[CINDType::CALLHELD].value ==
                        CallHeldState::ONHOLD_NOACTIVE) {
               // The held call(s) become connected call(s).
               UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
             }
           }
           break;
 
         default:
           BT_WARNING("Not handling state changed");
       }
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+    case nsITelephonyService::CALL_STATE_DISCONNECTED:
       switch (prevCallState) {
-        case nsITelephonyProvider::CALL_STATE_INCOMING:
+        case nsITelephonyService::CALL_STATE_INCOMING:
           // Incoming call, no break
           sStopSendingRingFlag = true;
-        case nsITelephonyProvider::CALL_STATE_DIALING:
-        case nsITelephonyProvider::CALL_STATE_ALERTING:
+        case nsITelephonyService::CALL_STATE_DIALING:
+        case nsITelephonyService::CALL_STATE_ALERTING:
           // Outgoing call
           UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, aSend);
           break;
-        case nsITelephonyProvider::CALL_STATE_CONNECTED:
+        case nsITelephonyService::CALL_STATE_CONNECTED:
           // No call is ongoing
           if (sCINDItems[CINDType::CALLHELD].value ==
               CallHeldState::NO_CALLHELD) {
             UpdateCIND(CINDType::CALL, CallState::NO_CALL, aSend);
           }
           break;
         default:
           BT_WARNING("Not handling state changed");
       }
 
       // Handle held calls separately
-      if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_HELD)) {
+      if (!FindFirstCall(nsITelephonyService::CALL_STATE_HELD)) {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::NO_CALLHELD, aSend);
-      } else if (!FindFirstCall(nsITelephonyProvider::CALL_STATE_CONNECTED)) {
+      } else if (!FindFirstCall(nsITelephonyService::CALL_STATE_CONNECTED)) {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_NOACTIVE, aSend);
       } else {
         UpdateCIND(CINDType::CALLHELD, CallHeldState::ONHOLD_ACTIVE, aSend);
       }
 
       // -1 is necessary because call 0 is an invalid (padding) call object.
       if (mCurrentCallArray.Length() - 1 ==
-          GetNumberOfCalls(nsITelephonyProvider::CALL_STATE_DISCONNECTED)) {
+          GetNumberOfCalls(nsITelephonyService::CALL_STATE_DISCONNECTED)) {
         // In order to let user hear busy tone via connected Bluetooth headset,
         // we postpone the timing of dropping SCO.
         if (!(aError.Equals(NS_LITERAL_STRING("BusyError")))) {
           DisconnectSco();
         } else {
           // Close Sco later since Dialer is still playing busy tone via HF.
           MessageLoop::current()->PostDelayedTask(FROM_HERE,
                                                   new CloseScoTask(),
@@ -1694,17 +1694,17 @@ BluetoothHfpManager::UpdateSecondNumber(
 
 void
 BluetoothHfpManager::AnswerWaitingCall()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Pick up second call. First call is held now.
-  mCdmaSecondCall.mState = nsITelephonyProvider::CALL_STATE_CONNECTED;
+  mCdmaSecondCall.mState = nsITelephonyService::CALL_STATE_CONNECTED;
   UpdateCIND(CINDType::CALLSETUP, CallSetupState::NO_CALLSETUP, true);
 
   sCINDItems[CINDType::CALLHELD].value = CallHeldState::ONHOLD_ACTIVE;
   SendCommand(RESPONSE_CIEV, CINDType::CALLHELD);
 }
 
 void
 BluetoothHfpManager::IgnoreWaitingCall()
@@ -1719,18 +1719,18 @@ BluetoothHfpManager::IgnoreWaitingCall()
 void
 BluetoothHfpManager::ToggleCalls()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mPhoneType == PhoneType::CDMA);
 
   // Toggle acitve and held calls
   mCdmaSecondCall.mState = (mCdmaSecondCall.IsActive()) ?
-                             nsITelephonyProvider::CALL_STATE_HELD :
-                             nsITelephonyProvider::CALL_STATE_CONNECTED;
+                             nsITelephonyService::CALL_STATE_HELD :
+                             nsITelephonyService::CALL_STATE_CONNECTED;
 }
 #endif // MOZ_B2G_RIL
 
 void
 BluetoothHfpManager::OnSocketConnectSuccess(BluetoothSocket* aSocket)
 {
   MOZ_ASSERT(aSocket);
 #ifdef MOZ_B2G_RIL
--- a/dom/datastore/DataStore.manifest
+++ b/dom/datastore/DataStore.manifest
@@ -1,2 +1,2 @@
-component {d193d0e2-c677-4a7b-bb0a-19155b470f2e} DataStoreService.js
-contract @mozilla.org/datastore-service;1 {d193d0e2-c677-4a7b-bb0a-19155b470f2e}
+component {db5c9602-030f-4bff-a3de-881a8de370f2} DataStoreImpl.js
+contract @mozilla.org/dom/datastore;1 {db5c9602-030f-4bff-a3de-881a8de370f2}
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreCallbacks.h
@@ -0,0 +1,48 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_DataStoreCallbacks_h
+#define mozilla_dom_DataStoreCallbacks_h
+
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+class DataStoreDB;
+
+class DataStoreDBCallback
+{
+public:
+  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
+  NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
+
+  virtual void Run(DataStoreDB* aDb, bool aSuccess) = 0;
+
+protected:
+  virtual ~DataStoreDBCallback()
+  {
+  }
+};
+
+class DataStoreRevisionCallback
+{
+public:
+  NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
+  NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
+
+  virtual void Run(const nsAString& aRevisionID) = 0;
+
+protected:
+  virtual ~DataStoreRevisionCallback()
+  {
+  }
+};
+
+} // dom namespace
+} // mozilla namespace
+
+#endif // mozilla_dom_DataStoreCallbacks_h
--- a/dom/datastore/DataStoreChangeNotifier.jsm
+++ b/dom/datastore/DataStoreChangeNotifier.jsm
@@ -7,19 +7,16 @@
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 this.EXPORTED_SYMBOLS = ["DataStoreChangeNotifier"];
 
 function debug(s) {
   //dump('DEBUG DataStoreChangeNotifier: ' + s + '\n');
 }
 
-// DataStoreServiceInternal should not be converted into a lazy getter as it
-// runs code during initialization.
-Cu.import('resource://gre/modules/DataStoreServiceInternal.jsm');
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                    "@mozilla.org/parentprocessmessagemanager;1",
                                    "nsIMessageBroadcaster");
 
 this.DataStoreChangeNotifier = {
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreDB.cpp
@@ -0,0 +1,319 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DataStoreDB.h"
+
+#include "DataStoreCallbacks.h"
+#include "mozilla/dom/IDBDatabaseBinding.h"
+#include "mozilla/dom/IDBFactoryBinding.h"
+#include "mozilla/dom/indexedDB/IDBDatabase.h"
+#include "mozilla/dom/indexedDB/IDBFactory.h"
+#include "mozilla/dom/indexedDB/IDBIndex.h"
+#include "mozilla/dom/indexedDB/IDBObjectStore.h"
+#include "mozilla/dom/indexedDB/IDBRequest.h"
+#include "nsIDOMEvent.h"
+
+#define DATASTOREDB_VERSION        1
+#define DATASTOREDB_NAME           "DataStoreDB"
+#define DATASTOREDB_REVISION_INDEX "revisionIndex"
+
+using namespace mozilla::dom::indexedDB;
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_ISUPPORTS(DataStoreDB, nsIDOMEventListener)
+
+DataStoreDB::DataStoreDB(const nsAString& aManifestURL, const nsAString& aName)
+  : mState(Inactive)
+{
+  mDatabaseName.Assign(aName);
+  mDatabaseName.AppendASCII("|");
+  mDatabaseName.Append(aManifestURL);
+}
+
+DataStoreDB::~DataStoreDB()
+{
+}
+
+nsresult
+DataStoreDB::CreateFactoryIfNeeded()
+{
+  if (!mFactory) {
+    nsresult rv = IDBFactory::Create(nullptr, getter_AddRefs(mFactory));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+DataStoreDB::Open(IDBTransactionMode aMode, const Sequence<nsString>& aDbs,
+                  DataStoreDBCallback* aCallback)
+{
+  MOZ_ASSERT(mState == Inactive);
+
+  nsresult rv = CreateFactoryIfNeeded();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  ErrorResult error;
+  mRequest = mFactory->Open(mDatabaseName, DATASTOREDB_VERSION, error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  rv = AddEventListeners();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mState = Active;
+  mTransactionMode = aMode;
+  mObjectStores = aDbs;
+  mCallback = aCallback;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DataStoreDB::HandleEvent(nsIDOMEvent* aEvent)
+{
+  nsString type;
+  nsresult rv = aEvent->GetType(type);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (type.EqualsASCII("success")) {
+    RemoveEventListeners();
+    mState = Inactive;
+
+    rv = DatabaseOpened();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      mCallback->Run(this, false);
+    } else {
+      mCallback->Run(this, true);
+    }
+
+    mRequest = nullptr;
+    return NS_OK;
+  }
+
+  if (type.EqualsASCII("upgradeneeded")) {
+    return UpgradeSchema();
+  }
+
+  if (type.EqualsASCII("error") || type.EqualsASCII("blocked")) {
+    RemoveEventListeners();
+    mState = Inactive;
+    mCallback->Run(this, false);
+    mRequest = nullptr;
+    return NS_OK;
+  }
+
+  MOZ_ASSUME_UNREACHABLE("This should not happen");
+  return NS_OK;
+}
+
+nsresult
+DataStoreDB::UpgradeSchema()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  AutoSafeJSContext cx;
+
+  ErrorResult error;
+  JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  MOZ_ASSERT(result.isObject());
+
+  IDBDatabase* database = nullptr;
+  nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Didn't get the object we expected!");
+    return rv;
+  }
+
+  {
+    RootedDictionary<IDBObjectStoreParameters> params(cx);
+    params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }"));
+    nsRefPtr<IDBObjectStore> store =
+      database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_NAME),
+                                  params, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.ErrorCode();
+    }
+  }
+
+  nsRefPtr<IDBObjectStore> store;
+
+  {
+    RootedDictionary<IDBObjectStoreParameters> params(cx);
+    params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }"));
+
+    store =
+      database->CreateObjectStore(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION),
+                                  params, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.ErrorCode();
+    }
+  }
+
+  {
+    RootedDictionary<IDBIndexParameters> params(cx);
+    params.Init(NS_LITERAL_STRING("{ \"unique\": true }"));
+    nsRefPtr<IDBIndex> index =
+      store->CreateIndex(cx, NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX),
+                         NS_LITERAL_STRING("revisionId"), params, error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.ErrorCode();
+    }
+  }
+
+  return NS_OK;
+}
+
+nsresult
+DataStoreDB::DatabaseOpened()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  AutoSafeJSContext cx;
+
+  ErrorResult error;
+  JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  MOZ_ASSERT(result.isObject());
+
+  nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), mDatabase);
+  if (NS_FAILED(rv)) {
+    NS_WARNING("Didn't get the object we expected!");
+    return rv;
+  }
+
+  nsRefPtr<IDBTransaction> txn = mDatabase->Transaction(mObjectStores,
+                                                        mTransactionMode,
+                                                        error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  mTransaction = txn.forget();
+  return NS_OK;
+}
+
+nsresult
+DataStoreDB::Delete()
+{
+  MOZ_ASSERT(mState == Inactive);
+
+  nsresult rv = CreateFactoryIfNeeded();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mTransaction = nullptr;
+
+  if (mDatabase) {
+    rv = mDatabase->Close();
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    mDatabase = nullptr;
+  }
+
+  ErrorResult error;
+  nsRefPtr<IDBOpenDBRequest> request =
+    mFactory->DeleteDatabase(mDatabaseName, IDBOpenDBOptions(), error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  return NS_OK;
+}
+
+indexedDB::IDBTransaction*
+DataStoreDB::Transaction() const
+{
+  MOZ_ASSERT(mTransaction);
+  MOZ_ASSERT(mTransaction->IsOpen());
+  return mTransaction;
+}
+
+nsresult
+DataStoreDB::AddEventListeners()
+{
+  nsresult rv;
+  rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
+                                               this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("upgradeneeded"),
+                                               this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("error"),
+                                               this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("blocked"),
+                                               this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+DataStoreDB::RemoveEventListeners()
+{
+  nsresult rv;
+  rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("success"),
+                                     this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("upgradeneeded"),
+                                     this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("error"),
+                                     this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = mRequest->RemoveEventListener(NS_LITERAL_STRING("blocked"),
+                                     this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreDB.h
@@ -0,0 +1,82 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_DataStoreDB_h
+#define mozilla_dom_DataStoreDB_h
+
+#include "mozilla/dom/IDBTransactionBinding.h"
+#include "nsAutoPtr.h"
+#include "nsIDOMEventListener.h"
+#include "nsISupportsImpl.h"
+#include "nsString.h"
+
+#define DATASTOREDB_REVISION       "revision"
+
+namespace mozilla {
+namespace dom {
+
+namespace indexedDB {
+class IDBDatabase;
+class IDBFactory;
+class IDBObjectStore;
+class IDBOpenDBRequest;
+class IDBTransaction;
+}
+
+class DataStoreDBCallback;
+
+class DataStoreDB MOZ_FINAL : public nsIDOMEventListener
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  DataStoreDB(const nsAString& aManifestURL, const nsAString& aName);
+  ~DataStoreDB();
+
+  nsresult Open(IDBTransactionMode aMode, const Sequence<nsString>& aDb,
+                DataStoreDBCallback* aCallback);
+
+  nsresult Delete();
+
+  indexedDB::IDBTransaction* Transaction() const;
+
+  // nsIDOMEventListener
+  NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+private:
+  nsresult CreateFactoryIfNeeded();
+
+  nsresult UpgradeSchema();
+
+  nsresult DatabaseOpened();
+
+  nsresult AddEventListeners();
+
+  nsresult RemoveEventListeners();
+
+  nsString mDatabaseName;
+
+  nsRefPtr<indexedDB::IDBFactory> mFactory;
+  nsRefPtr<indexedDB::IDBOpenDBRequest> mRequest;
+  nsRefPtr<indexedDB::IDBDatabase> mDatabase;
+  nsRefPtr<indexedDB::IDBTransaction> mTransaction;
+
+  nsRefPtr<DataStoreDBCallback> mCallback;
+
+  // Internal state to avoid strange use of this class.
+  enum StateType {
+    Inactive,
+    Active
+  } mState;
+
+  IDBTransactionMode mTransactionMode;
+  Sequence<nsString> mObjectStores;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_DataStoreDB_h
rename from dom/datastore/DataStoreImpl.jsm
rename to dom/datastore/DataStoreImpl.js
--- a/dom/datastore/DataStoreImpl.jsm
+++ b/dom/datastore/DataStoreImpl.js
@@ -1,18 +1,16 @@
 /* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict'
 
-this.EXPORTED_SYMBOLS = ["DataStore"];
-
 function debug(s) {
   //dump('DEBUG DataStore: ' + s + '\n');
 }
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 const REVISION_ADDED = "added";
 const REVISION_UPDATED = "updated";
@@ -54,27 +52,26 @@ function validateId(aId) {
     return aId.length;
   }
 
   aId = parseInt(aId);
   return (!isNaN(aId) && aId > 0);
 }
 
 /* DataStore object */
-this.DataStore = function(aWindow, aName, aOwner, aReadOnly) {
+function DataStore() {
   debug("DataStore created");
-  this.init(aWindow, aName, aOwner, aReadOnly);
 }
 
-this.DataStore.prototype = {
+DataStore.prototype = {
   classDescription: "DataStore XPCOM Component",
   classID: Components.ID("{db5c9602-030f-4bff-a3de-881a8de370f2}"),
   contractID: "@mozilla.org/dom/datastore-impl;1",
-  QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports,
-                                         Components.interfaces.nsIObserver]),
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStore, Ci.nsISupports,
+                                         Ci.nsIObserver]),
 
   callbacks: [],
 
   _window: null,
   _name: null,
   _owner: null,
   _readOnly: null,
   _revisionId: null,
@@ -531,8 +528,10 @@ this.DataStore.prototype = {
     let cursorImpl = this._window.DataStoreCursorImpl.
                                   _create(this._window, this._cursor);
 
     let exposedCursor = new this._window.DataStoreCursor();
     exposedCursor.setDataStoreCursorImpl(cursorImpl);
     return exposedCursor;
   }
 };
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStore]);
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreRevision.cpp
@@ -0,0 +1,102 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DataStoreRevision.h"
+
+#include "DataStoreCallbacks.h"
+#include "DataStoreService.h"
+#include "mozilla/dom/DataStoreBinding.h"
+#include "mozilla/dom/indexedDB/IDBObjectStore.h"
+#include "nsIDOMEvent.h"
+
+namespace mozilla {
+namespace dom {
+
+using namespace indexedDB;
+
+NS_IMPL_ISUPPORTS(DataStoreRevision, nsIDOMEventListener)
+
+// Note: this code in it must not assume anything about the compartment cx is
+// in.
+nsresult
+DataStoreRevision::AddRevision(JSContext* aCx,
+                               IDBObjectStore* aStore,
+                               uint32_t aObjectId,
+                               RevisionType aRevisionType,
+                               DataStoreRevisionCallback* aCallback)
+{
+  MOZ_ASSERT(aStore);
+  MOZ_ASSERT(aCallback);
+
+  nsRefPtr<DataStoreService> service = DataStoreService::Get();
+  if (!service) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsString id;
+  nsresult rv = service->GenerateUUID(mRevisionID);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  DataStoreRevisionData data;
+  data.mRevisionId = mRevisionID;
+  data.mObjectId = aObjectId;
+
+  switch (aRevisionType) {
+    case RevisionVoid:
+      data.mOperation = NS_LITERAL_STRING("void");
+      break;
+
+    default:
+      MOZ_ASSUME_UNREACHABLE("This should not happen");
+      break;
+  }
+
+  JS::Rooted<JS::Value> value(aCx);
+  if (!data.ToObject(aCx, &value)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  ErrorResult error;
+  mRequest = aStore->Put(aCx, value, JS::UndefinedHandleValue, error);
+  if (NS_WARN_IF(error.Failed())) {
+    return error.ErrorCode();
+  }
+
+  rv = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
+                                               this, false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mCallback = aCallback;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DataStoreRevision::HandleEvent(nsIDOMEvent* aEvent)
+{
+  nsString type;
+  nsresult rv = aEvent->GetType(type);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!type.EqualsASCII("success")) {
+    MOZ_ASSUME_UNREACHABLE("This should not happen");
+    return NS_ERROR_FAILURE;
+  }
+
+  mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false);
+  mRequest = nullptr;
+
+  mCallback->Run(mRevisionID);
+  return NS_OK;
+}
+
+} // dom namespace
+} // mozilla namespace
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreRevision.h
@@ -0,0 +1,52 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_DataStoreRevision_h
+#define mozilla_dom_DataStoreRevision_h
+
+#include "jsapi.h"
+#include "nsAutoPtr.h"
+#include "nsIDOMEventListener.h"
+#include "nsString.h"
+
+namespace mozilla {
+namespace dom {
+
+namespace indexedDB {
+class IDBObjectStore;
+class IDBRequest;
+}
+
+class DataStoreRevisionCallback;
+
+class DataStoreRevision MOZ_FINAL : public nsIDOMEventListener
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  enum RevisionType {
+    RevisionVoid
+  };
+
+  nsresult AddRevision(JSContext* aCx,
+                       indexedDB::IDBObjectStore* aStore,
+                       uint32_t aObjectId,
+                       RevisionType aRevisionType,
+                       DataStoreRevisionCallback* aCallback);
+
+  // nsIDOMEventListener
+  NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
+
+private:
+  nsRefPtr<DataStoreRevisionCallback> mCallback;
+  nsRefPtr<indexedDB::IDBRequest> mRequest;
+  nsString mRevisionID;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_DataStoreRevision_h
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreService.cpp
@@ -0,0 +1,1352 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "DataStoreService.h"
+
+#include "DataStoreCallbacks.h"
+#include "DataStoreDB.h"
+#include "DataStoreRevision.h"
+#include "mozilla/dom/DataStore.h"
+#include "mozilla/dom/DataStoreBinding.h"
+#include "mozilla/dom/DataStoreImplBinding.h"
+#include "nsIDataStore.h"
+
+#include "mozilla/Preferences.h"
+#include "mozilla/Services.h"
+#include "mozilla/StaticPtr.h"
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ContentParent.h"
+#include "mozilla/dom/DOMError.h"
+#include "mozilla/dom/indexedDB/IDBCursor.h"
+#include "mozilla/dom/indexedDB/IDBObjectStore.h"
+#include "mozilla/dom/PermissionMessageUtils.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/unused.h"
+
+#include "mozIApplication.h"
+#include "mozIApplicationClearPrivateDataParams.h"
+#include "nsIAppsService.h"
+#include "nsIDOMEvent.h"
+#include "nsIDocument.h"
+#include "nsIDOMGlobalPropertyInitializer.h"
+#include "nsIIOService.h"
+#include "nsIObserverService.h"
+#include "nsIPermissionManager.h"
+#include "nsIScriptSecurityManager.h"
+#include "nsIUUIDGenerator.h"
+#include "nsPIDOMWindow.h"
+#include "nsIURI.h"
+
+#include "nsContentUtils.h"
+#include "nsNetCID.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "nsXULAppAPI.h"
+
+#define ASSERT_PARENT_PROCESS()                                             \
+  AssertIsInMainProcess();                                                  \
+  if (NS_WARN_IF(!IsMainProcess())) {                                       \
+    return NS_ERROR_FAILURE;                                                \
+  }
+
+namespace mozilla {
+namespace dom {
+
+using namespace indexedDB;
+
+// This class contains all the information about a DataStore.
+class DataStoreInfo
+{
+public:
+  DataStoreInfo()
+    : mReadOnly(true)
+    , mEnabled(false)
+  {}
+
+  DataStoreInfo(const nsAString& aName,
+                const nsAString& aOriginURL,
+                const nsAString& aManifestURL,
+                bool aReadOnly,
+                bool aEnabled)
+  {
+    Init(aName, aOriginURL, aManifestURL, aReadOnly, aEnabled);
+  }
+
+  void Init(const nsAString& aName,
+            const nsAString& aOriginURL,
+            const nsAString& aManifestURL,
+            bool aReadOnly,
+            bool aEnabled)
+  {
+    mName = aName;
+    mOriginURL = aOriginURL;
+    mManifestURL = aManifestURL;
+    mReadOnly = aReadOnly;
+    mEnabled = aEnabled;
+  }
+
+  void Update(const nsAString& aName,
+              const nsAString& aOriginURL,
+              const nsAString& aManifestURL,
+              bool aReadOnly)
+  {
+    mName = aName;
+    mOriginURL = aOriginURL;
+    mManifestURL = aManifestURL;
+    mReadOnly = aReadOnly;
+  }
+
+  void Enable()
+  {
+    mEnabled = true;
+  }
+
+  nsString mName;
+  nsString mOriginURL;
+  nsString mManifestURL;
+  bool mReadOnly;
+
+  // A DataStore is enabled when it has its first revision.
+  bool mEnabled;
+};
+
+namespace {
+
+// Singleton for DataStoreService.
+StaticRefPtr<DataStoreService> gDataStoreService;
+static uint64_t gCounterID = 0;
+
+typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp;
+
+bool
+IsMainProcess()
+{
+  static const bool isMainProcess =
+    XRE_GetProcessType() == GeckoProcessType_Default;
+  return isMainProcess;
+}
+
+void
+AssertIsInMainProcess()
+{
+  MOZ_ASSERT(IsMainProcess());
+}
+
+void
+RejectPromise(nsPIDOMWindow* aWindow, Promise* aPromise, nsresult aRv)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(NS_FAILED(aRv));
+
+  nsRefPtr<DOMError> error;
+  if (aRv == NS_ERROR_DOM_SECURITY_ERR) {
+    error = new DOMError(aWindow, NS_LITERAL_STRING("SecurityError"),
+                         NS_LITERAL_STRING("Access denied"));
+  } else {
+    error = new DOMError(aWindow, NS_LITERAL_STRING("InternalError"),
+                         NS_LITERAL_STRING("An error occurred"));
+  }
+
+  aPromise->MaybeReject(error);
+}
+
+void
+DeleteDatabase(const nsAString& aName,
+               const nsAString& aManifestURL)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsRefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName);
+  db->Delete();
+}
+
+PLDHashOperator
+DeleteDataStoresAppEnumerator(
+                             const uint32_t& aAppId,
+                             nsAutoPtr<DataStoreInfo>& aInfo,
+                             void* aUserData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  auto* appId = static_cast<uint32_t*>(aUserData);
+  if (*appId != aAppId) {
+    return PL_DHASH_NEXT;
+  }
+
+  DeleteDatabase(aInfo->mName, aInfo->mManifestURL);
+  return PL_DHASH_REMOVE;
+}
+
+PLDHashOperator
+DeleteDataStoresEnumerator(const nsAString& aName,
+                           nsAutoPtr<HashApp>& aApps,
+                           void* aUserData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  aApps->Enumerate(DeleteDataStoresAppEnumerator, aUserData);
+  return aApps->Count() ? PL_DHASH_NEXT : PL_DHASH_REMOVE;
+}
+
+void
+GeneratePermissionName(nsAString& aPermission,
+                       const nsAString& aName,
+                       const nsAString& aManifestURL)
+{
+  aPermission.AssignASCII("indexedDB-chrome-");
+  aPermission.Append(aName);
+  aPermission.AppendASCII("|");
+  aPermission.Append(aManifestURL);
+}
+
+nsresult
+ResetPermission(uint32_t aAppId, const nsAString& aOriginURL,
+                const nsAString& aManifestURL,
+                const nsAString& aPermission,
+                bool aReadOnly)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsresult rv;
+  nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIURI> uri;
+  rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aOriginURL), nullptr, nullptr,
+                         getter_AddRefs(uri));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
+  if (!ssm) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIPrincipal> principal;
+  rv = ssm->GetAppCodebasePrincipal(uri, aAppId, false,
+                                    getter_AddRefs(principal));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsCOMPtr<nsIPermissionManager> pm =
+    do_GetService(NS_PERMISSIONMANAGER_CONTRACTID);
+  if (!pm) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCString basePermission;
+  basePermission.Append(NS_ConvertUTF16toUTF8(aPermission));
+
+  // Write permission
+  {
+    nsCString permission;
+    permission.Append(basePermission);
+    permission.AppendASCII("-write");
+
+    uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
+    rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(),
+                                              &perm);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (aReadOnly && perm == nsIPermissionManager::ALLOW_ACTION) {
+      rv = pm->RemoveFromPrincipal(principal, permission.get());
+    }
+    else if (!aReadOnly && perm != nsIPermissionManager::ALLOW_ACTION) {
+      rv = pm->AddFromPrincipal(principal, permission.get(),
+                                nsIPermissionManager::ALLOW_ACTION,
+                                nsIPermissionManager::EXPIRE_NEVER, 0);
+    }
+
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  // Read permission
+  {
+    nsCString permission;
+    permission.Append(basePermission);
+    permission.AppendASCII("-read");
+
+    uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
+    rv = pm->TestExactPermissionFromPrincipal(principal, permission.get(),
+                                              &perm);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (perm != nsIPermissionManager::ALLOW_ACTION) {
+      rv = pm->AddFromPrincipal(principal, permission.get(),
+                                nsIPermissionManager::ALLOW_ACTION,
+                                nsIPermissionManager::EXPIRE_NEVER, 0);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+    }
+  }
+
+  // Generic permission
+  uint32_t perm = nsIPermissionManager::UNKNOWN_ACTION;
+  rv = pm->TestExactPermissionFromPrincipal(principal, basePermission.get(),
+                                            &perm);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (perm != nsIPermissionManager::ALLOW_ACTION) {
+    rv = pm->AddFromPrincipal(principal, basePermission.get(),
+                              nsIPermissionManager::ALLOW_ACTION,
+                              nsIPermissionManager::EXPIRE_NEVER, 0);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
+}
+
+class MOZ_STACK_CLASS GetDataStoreInfosData
+{
+public:
+  GetDataStoreInfosData(nsClassHashtable<nsStringHashKey, HashApp>& aAccessStores,
+                        const nsAString& aName, uint32_t aAppId,
+                        nsTArray<DataStoreInfo>& aStores)
+    : mAccessStores(aAccessStores)
+    , mName(aName)
+    , mAppId(aAppId)
+    , mStores(aStores)
+  {}
+
+  nsClassHashtable<nsStringHashKey, HashApp>& mAccessStores;
+  nsString mName;
+  uint32_t mAppId;
+  nsTArray<DataStoreInfo>& mStores;
+};
+
+PLDHashOperator
+GetDataStoreInfosEnumerator(const uint32_t& aAppId,
+                            DataStoreInfo* aInfo,
+                            void* aUserData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  auto* data = static_cast<GetDataStoreInfosData*>(aUserData);
+  if (aAppId == data->mAppId) {
+    return PL_DHASH_NEXT;
+  }
+
+  HashApp* apps;
+  if (!data->mAccessStores.Get(data->mName, &apps)) {
+    return PL_DHASH_NEXT;
+  }
+
+  DataStoreInfo* accessInfo = nullptr;
+  if (!apps->Get(data->mAppId, &accessInfo)) {
+    return PL_DHASH_NEXT;
+  }
+
+  bool readOnly = aInfo->mReadOnly || accessInfo->mReadOnly;
+  DataStoreInfo* accessStore = data->mStores.AppendElement();
+  accessStore->Init(aInfo->mName, aInfo->mOriginURL,
+                    aInfo->mManifestURL, readOnly,
+                    aInfo->mEnabled);
+
+  return PL_DHASH_NEXT;
+}
+
+// This class is useful to enumerate the add permissions for each app.
+class MOZ_STACK_CLASS AddPermissionsData
+{
+public:
+  AddPermissionsData(const nsAString& aPermission, bool aReadOnly)
+    : mPermission(aPermission)
+    , mReadOnly(aReadOnly)
+    , mResult(NS_OK)
+  {}
+
+  nsString mPermission;
+  bool mReadOnly;
+  nsresult mResult;
+};
+
+PLDHashOperator
+AddPermissionsEnumerator(const uint32_t& aAppId,
+                         DataStoreInfo* aInfo,
+                         void* userData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  auto* data = static_cast<AddPermissionsData*>(userData);
+
+  // ReadOnly is decided by the owner first.
+  bool readOnly = data->mReadOnly || aInfo->mReadOnly;
+
+  data->mResult = ResetPermission(aAppId, aInfo->mOriginURL,
+                                  aInfo->mManifestURL,
+                                  data->mPermission,
+                                  readOnly);
+  return NS_FAILED(data->mResult) ? PL_DHASH_STOP : PL_DHASH_NEXT;
+}
+
+// This class is useful to enumerate the add permissions for each app.
+class MOZ_STACK_CLASS AddAccessPermissionsData
+{
+public:
+  AddAccessPermissionsData(uint32_t aAppId, const nsAString& aName,
+                           const nsAString& aOriginURL, bool aReadOnly)
+    : mAppId(aAppId)
+    , mName(aName)
+    , mOriginURL(aOriginURL)
+    , mReadOnly(aReadOnly)
+    , mResult(NS_OK)
+  {}
+
+  uint32_t mAppId;
+  nsString mName;
+  nsString mOriginURL;
+  bool mReadOnly;
+  nsresult mResult;
+};
+
+PLDHashOperator
+AddAccessPermissionsEnumerator(const uint32_t& aAppId,
+                               DataStoreInfo* aInfo,
+                               void* userData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  auto* data = static_cast<AddAccessPermissionsData*>(userData);
+
+  nsString permission;
+  GeneratePermissionName(permission, data->mName, aInfo->mManifestURL);
+
+  // ReadOnly is decided by the owner first.
+  bool readOnly = aInfo->mReadOnly || data->mReadOnly;
+
+  data->mResult = ResetPermission(data->mAppId, data->mOriginURL,
+                                  aInfo->mManifestURL,
+                                  permission, readOnly);
+  return NS_FAILED(data->mResult) ? PL_DHASH_STOP : PL_DHASH_NEXT;
+}
+
+} /* anonymous namespace */
+
+// A PendingRequest is created when a content code wants a list of DataStores
+// but some of them are not enabled yet.
+class PendingRequest
+{
+public:
+  void Init(nsPIDOMWindow* aWindow, Promise* aPromise,
+            const nsTArray<DataStoreInfo>& aStores,
+            const nsTArray<nsString>& aPendingDataStores)
+  {
+    mWindow = aWindow;
+    mPromise = aPromise;
+    mStores = aStores;
+    mPendingDataStores = aPendingDataStores;
+  }
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  nsRefPtr<Promise> mPromise;
+  nsTArray<DataStoreInfo> mStores;
+
+  // This array contains the list of manifestURLs of the DataStores that are
+  // not enabled yet.
+  nsTArray<nsString> mPendingDataStores;
+};
+
+// This callback is used to enable a DataStore when its first revisionID is
+// created.
+class RevisionAddedEnableStoreCallback MOZ_FINAL :
+  public DataStoreRevisionCallback
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(RevisionAddedEnableStoreCallback);
+
+  RevisionAddedEnableStoreCallback(uint32_t aAppId,
+                                   const nsAString& aName,
+                                   const nsAString& aManifestURL)
+    : mAppId(aAppId)
+    , mName(aName)
+    , mManifestURL(aManifestURL)
+  {
+    AssertIsInMainProcess();
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  void
+  Run(const nsAString& aRevisionId)
+  {
+    AssertIsInMainProcess();
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsRefPtr<DataStoreService> service = DataStoreService::Get();
+    MOZ_ASSERT(service);
+
+    service->EnableDataStore(mAppId, mName, mManifestURL);
+  }
+
+private:
+  uint32_t mAppId;
+  nsString mName;
+  nsString mManifestURL;
+};
+
+// This DataStoreDBCallback is called when DataStoreDB opens the DataStore DB.
+// Then the first revision will be created if it doesn't exist yet.
+class FirstRevisionIdCallback MOZ_FINAL : public DataStoreDBCallback
+                                        , public nsIDOMEventListener
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  FirstRevisionIdCallback(uint32_t aAppId, const nsAString& aName,
+                          const nsAString& aManifestURL)
+    : mAppId(aAppId)
+    , mName(aName)
+    , mManifestURL(aManifestURL)
+  {
+    AssertIsInMainProcess();
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  void
+  Run(DataStoreDB* aDb, bool aSuccess)
+  {
+    AssertIsInMainProcess();
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(aDb);
+
+    if (!aSuccess) {
+      NS_WARNING("Failed to create the first revision.");
+      return;
+    }
+
+    mTxn = aDb->Transaction();
+
+    ErrorResult rv;
+    nsRefPtr<IDBObjectStore> store =
+      mTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      return;
+    }
+
+    // a Null JSContext is ok because OpenCursor ignores it if the range is
+    // undefined.
+    mRequest = store->OpenCursor(nullptr, JS::UndefinedHandleValue,
+                                 IDBCursorDirection::Prev, rv);
+    if (NS_WARN_IF(rv.Failed())) {
+      return;
+    }
+
+    nsresult res;
+    res = mRequest->EventTarget::AddEventListener(NS_LITERAL_STRING("success"),
+                                                  this, false);
+    if (NS_WARN_IF(NS_FAILED(res))) {
+      return;
+    }
+  }
+
+  // nsIDOMEventListener
+  NS_IMETHOD
+  HandleEvent(nsIDOMEvent* aEvent)
+  {
+    AssertIsInMainProcess();
+    MOZ_ASSERT(NS_IsMainThread());
+
+    nsString type;
+    nsresult rv = aEvent->GetType(type);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (!type.EqualsASCII("success")) {
+      return NS_ERROR_FAILURE;
+    }
+
+    mRequest->RemoveEventListener(NS_LITERAL_STRING("success"), this, false);
+
+    // Note: this cx is only used for rooting and AddRevision, neither of which
+    // actually care which compartment we're in.
+    AutoSafeJSContext cx;
+
+    ErrorResult error;
+    JS::Rooted<JS::Value> result(cx, mRequest->GetResult(error));
+    if (NS_WARN_IF(error.Failed())) {
+      return error.ErrorCode();
+    }
+
+    // This means that the content is a IDBCursor, so the first revision already
+    // exists.
+    if (result.isObject()) {
+      nsRefPtr<DataStoreService> service = DataStoreService::Get();
+      MOZ_ASSERT(service);
+
+      return service->EnableDataStore(mAppId, mName, mManifestURL);
+    }
+
+    MOZ_ASSERT(mTxn);
+    nsRefPtr<IDBObjectStore> store =
+      mTxn->ObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), error);
+    if (NS_WARN_IF(error.Failed())) {
+      return error.ErrorCode();
+    }
+    MOZ_ASSERT(store);
+
+    nsRefPtr<RevisionAddedEnableStoreCallback> callback =
+      new RevisionAddedEnableStoreCallback(mAppId, mName, mManifestURL);
+
+    // If the revision doesn't exist, let's create it.
+    nsRefPtr<DataStoreRevision> mRevision = new DataStoreRevision();
+    return mRevision->AddRevision(cx, store, 0, DataStoreRevision::RevisionVoid,
+                                  callback);
+  }
+
+private:
+  nsRefPtr<IDBRequest> mRequest;
+
+  nsRefPtr<IDBTransaction> mTxn;
+  nsRefPtr<DataStoreRevision> mRevision;
+
+  uint32_t mAppId;
+  nsString mName;
+  nsString mManifestURL;
+};
+
+NS_IMPL_ISUPPORTS(FirstRevisionIdCallback, nsIDOMEventListener)
+
+// This class calls the 'retrieveRevisionId' method of the DataStore object for
+// any DataStore in the 'mResults' array. When all of them are called, the
+// promise is resolved with 'mResults'.
+// The reson why this has to be done is because DataStore are object that can be
+// created in any thread and in any process. The first revision has been
+// created, but they don't know its value yet.
+class RetrieveRevisionsCounter
+{
+public:
+  NS_INLINE_DECL_REFCOUNTING(RetrieveRevisionsCounter);
+
+  RetrieveRevisionsCounter(uint32_t aId, Promise* aPromise, uint32_t aCount)
+    : mPromise(aPromise)
+    , mId(aId)
+    , mCount(aCount)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+  }
+
+  void
+  AppendDataStore(JSContext* aCx, DataStore* aDataStore,
+                  nsIDataStore* aDataStoreIf)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    mResults.AppendElement(aDataStore);
+
+    // DataStore will run this callback when the revisionID is retrieved.
+    JSFunction* func = js::NewFunctionWithReserved(aCx, JSCallback,
+                                                   0 /* nargs */, 0 /* flags */,
+                                                   nullptr, nullptr);
+    if (!func) {
+      return;
+    }
+
+    JS::Rooted<JSObject*> obj(aCx, JS_GetFunctionObject(func));
+    if (!obj) {
+      return;
+    }
+
+    // We use the ID to know which counter is this. The service keeps all of
+    // these counters alive with their own IDs in an hashtable.
+    js::SetFunctionNativeReserved(obj, 0, JS::Int32Value(mId));
+
+    JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*obj));
+    nsresult rv = aDataStoreIf->RetrieveRevisionId(value);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+  }
+
+private:
+  static bool
+  JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
+  {
+    MOZ_ASSERT(NS_IsMainThread());
+
+    JS::CallArgs args = CallArgsFromVp(aArgc, aVp);
+
+    JS::Rooted<JS::Value> value(aCx,
+                                js::GetFunctionNativeReserved(&args.callee(), 0));
+    uint32_t id = value.toInt32();
+
+    nsRefPtr<DataStoreService> service = DataStoreService::Get();
+    MOZ_ASSERT(service);
+
+    nsRefPtr<RetrieveRevisionsCounter> counter = service->GetCounter(id);
+    MOZ_ASSERT(counter);
+
+    // When all the callbacks are called, we can resolve the promise and remove
+    // the counter from the service.
+    --counter->mCount;
+    if (!counter->mCount) {
+      service->RemoveCounter(id);
+      counter->mPromise->MaybeResolve(counter->mResults);
+    }
+
+    return true;
+  }
+
+  nsRefPtr<Promise> mPromise;
+  nsTArray<nsRefPtr<DataStore>> mResults;
+
+  uint32_t mId;
+  uint32_t mCount;
+};
+
+/* static */ already_AddRefed<DataStoreService>
+DataStoreService::GetOrCreate()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!gDataStoreService) {
+    nsRefPtr<DataStoreService> service = new DataStoreService();
+    if (NS_WARN_IF(NS_FAILED(service->Init()))) {
+      return nullptr;
+    }
+
+    gDataStoreService = service;
+  }
+
+  nsRefPtr<DataStoreService> service = gDataStoreService.get();
+  return service.forget();
+}
+
+/* static */ already_AddRefed<DataStoreService>
+DataStoreService::Get()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsRefPtr<DataStoreService> service = gDataStoreService.get();
+  return service.forget();
+}
+
+/* static */ void
+DataStoreService::Shutdown()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (gDataStoreService) {
+    if (IsMainProcess()) {
+      nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+      if (obs) {
+        obs->RemoveObserver(gDataStoreService, "webapps-clear-data");
+      }
+    }
+
+    gDataStoreService = nullptr;
+  }
+}
+
+NS_INTERFACE_MAP_BEGIN(DataStoreService)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDataStoreService)
+  NS_INTERFACE_MAP_ENTRY(nsIDataStoreService)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+NS_INTERFACE_MAP_END
+
+NS_IMPL_ADDREF(DataStoreService)
+NS_IMPL_RELEASE(DataStoreService)
+
+DataStoreService::DataStoreService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+DataStoreService::~DataStoreService()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+}
+
+nsresult
+DataStoreService::Init()
+{
+  if (!IsMainProcess()) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+  if (!obs) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsresult rv = obs->AddObserver(this, "webapps-clear-data", false);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+DataStoreService::InstallDataStore(uint32_t aAppId,
+                                   const nsAString& aName,
+                                   const nsAString& aOriginURL,
+                                   const nsAString& aManifestURL,
+                                   bool aReadOnly)
+{
+  ASSERT_PARENT_PROCESS()
+  MOZ_ASSERT(NS_IsMainThread());
+
+  HashApp* apps = nullptr;
+  if (!mStores.Get(aName, &apps)) {
+    apps = new HashApp();
+    mStores.Put(aName, apps);
+  }
+
+  DataStoreInfo* info = nullptr;
+  if (!apps->Get(aAppId, &info)) {
+    info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false);
+    apps->Put(aAppId, info);
+  } else {
+    info->Update(aName, aOriginURL, aManifestURL, aReadOnly);
+  }
+
+  nsresult rv = AddPermissions(aAppId, aName, aOriginURL, aManifestURL,
+                               aReadOnly);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // Immediately create the first revision.
+  return CreateFirstRevisionId(aAppId, aName, aManifestURL);
+}
+
+NS_IMETHODIMP
+DataStoreService::InstallAccessDataStore(uint32_t aAppId,
+                                         const nsAString& aName,
+                                         const nsAString& aOriginURL,
+                                         const nsAString& aManifestURL,
+                                         bool aReadOnly)
+{
+  ASSERT_PARENT_PROCESS()
+  MOZ_ASSERT(NS_IsMainThread());
+
+  HashApp* apps = nullptr;
+  if (!mAccessStores.Get(aName, &apps)) {
+    apps = new HashApp();
+    mAccessStores.Put(aName, apps);
+  }
+
+  DataStoreInfo* info = nullptr;
+  if (!apps->Get(aAppId, &info)) {
+    info = new DataStoreInfo(aName, aOriginURL, aManifestURL, aReadOnly, false);
+    apps->Put(aAppId, info);
+  } else {
+    info->Update(aName, aOriginURL, aManifestURL, aReadOnly);
+  }
+
+  return AddAccessPermissions(aAppId, aName, aOriginURL, aManifestURL,
+                              aReadOnly);
+}
+
+NS_IMETHODIMP
+DataStoreService::GetDataStores(nsIDOMWindow* aWindow,
+                                const nsAString& aName,
+                                nsISupports** aDataStores)
+{
+  // FIXME This will be a thread-safe method.
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aWindow);
+  if (!window) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window);
+  nsRefPtr<Promise> promise = new Promise(global);
+
+  nsCOMPtr<nsIDocument> document = window->GetDoc();
+  MOZ_ASSERT(document);
+
+  nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
+  MOZ_ASSERT(principal);
+
+  nsTArray<DataStoreInfo> stores;
+
+  // If this request comes from the main process, we have access to the
+  // window, so we can skip the ipc communication.
+  if (IsMainProcess()) {
+    uint32_t appId;
+    nsresult rv = principal->GetAppId(&appId);
+    if (NS_FAILED(rv)) {
+      RejectPromise(window, promise, rv);
+      promise.forget(aDataStores);
+      return NS_OK;
+    }
+
+    rv = GetDataStoreInfos(aName, appId, stores);
+    if (NS_FAILED(rv)) {
+      RejectPromise(window, promise, rv);
+      promise.forget(aDataStores);
+      return NS_OK;
+    }
+  }
+
+  else {
+    // This method can be called in the child so we need to send a request
+    // to the parent and create DataStore object here.
+    ContentChild* contentChild = ContentChild::GetSingleton();
+
+    nsTArray<DataStoreSetting> array;
+    if (!contentChild->SendDataStoreGetStores(nsAutoString(aName),
+                                              IPC::Principal(principal),
+                                              &array)) {
+      RejectPromise(window, promise, NS_ERROR_FAILURE);
+      promise.forget(aDataStores);
+      return NS_OK;
+    }
+
+    for (uint32_t i = 0; i < array.Length(); ++i) {
+      DataStoreInfo* info = stores.AppendElement();
+      info->Init(array[i].name(), array[i].originURL(),
+                 array[i].manifestURL(), array[i].readOnly(),
+                 array[i].enabled());
+    }
+  }
+
+  GetDataStoresCreate(window, promise, stores);
+  promise.forget(aDataStores);
+  return NS_OK;
+}
+
+void
+DataStoreService::GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise,
+                                      const nsTArray<DataStoreInfo>& aStores)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!aStores.Length()) {
+    GetDataStoresResolve(aWindow, aPromise, aStores);
+    return;
+  }
+
+  nsTArray<nsString> pendingDataStores;
+  for (uint32_t i = 0; i < aStores.Length(); ++i) {
+    if (!aStores[i].mEnabled) {
+      pendingDataStores.AppendElement(aStores[i].mManifestURL);
+    }
+  }
+
+  if (!pendingDataStores.Length()) {
+    GetDataStoresResolve(aWindow, aPromise, aStores);
+    return;
+  }
+
+  PendingRequests* requests;
+  if (!mPendingRequests.Get(aStores[0].mName, &requests)) {
+    requests = new PendingRequests();
+    mPendingRequests.Put(aStores[0].mName, requests);
+  }
+
+  PendingRequest* request = requests->AppendElement();
+  request->Init(aWindow, aPromise, aStores, pendingDataStores);
+}
+
+void
+DataStoreService::GetDataStoresResolve(nsPIDOMWindow* aWindow,
+                                       Promise* aPromise,
+                                       const nsTArray<DataStoreInfo>& aStores)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (!aStores.Length()) {
+    nsTArray<nsRefPtr<DataStore>> results;
+    aPromise->MaybeResolve(results);
+    return;
+  }
+
+  AutoSafeJSContext cx;
+
+  // The counter will finish this task once all the DataStores will know their
+  // first revision Ids.
+  nsRefPtr<RetrieveRevisionsCounter> counter =
+    new RetrieveRevisionsCounter(++gCounterID, aPromise, aStores.Length());
+  mPendingCounters.Put(gCounterID, counter);
+
+  for (uint32_t i = 0; i < aStores.Length(); ++i) {
+    nsCOMPtr<nsIDataStore> dataStore =
+      do_CreateInstance("@mozilla.org/dom/datastore;1");
+    if (NS_WARN_IF(!dataStore)) {
+      return;
+    }
+
+    nsresult rv = dataStore->Init(aWindow, aStores[i].mName,
+                                  aStores[i].mManifestURL,
+                                  aStores[i].mReadOnly);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return;
+    }
+
+    nsCOMPtr<nsIXPConnectWrappedJS> xpcwrappedjs = do_QueryInterface(dataStore);
+    if (NS_WARN_IF(!xpcwrappedjs)) {
+      return;
+    }
+
+    JS::Rooted<JSObject*> dataStoreJS(cx, xpcwrappedjs->GetJSObject());
+    if (NS_WARN_IF(!dataStoreJS)) {
+      return;
+    }
+
+    JSAutoCompartment ac(cx, dataStoreJS);
+    nsRefPtr<DataStoreImpl> dataStoreObj = new DataStoreImpl(dataStoreJS,
+                                                             aWindow);
+
+    nsRefPtr<DataStore> exposedStore = new DataStore(aWindow);
+
+    ErrorResult error;
+    exposedStore->SetDataStoreImpl(*dataStoreObj, error);
+    if (error.Failed()) {
+      return;
+    }
+
+    JS::Rooted<JSObject*> obj(cx, exposedStore->WrapObject(cx));
+    MOZ_ASSERT(obj);
+
+    JS::Rooted<JS::Value> exposedObject(cx, JS::ObjectValue(*obj));
+    dataStore->SetExposedObject(exposedObject);
+
+    counter->AppendDataStore(cx, exposedStore, dataStore);
+  }
+}
+
+// Thie method populates 'aStores' with the list of DataStores with 'aName' as
+// name and available for this 'aAppId'.
+nsresult
+DataStoreService::GetDataStoreInfos(const nsAString& aName,
+                                    uint32_t aAppId,
+                                    nsTArray<DataStoreInfo>& aStores)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsCOMPtr<nsIAppsService> appsService =
+    do_GetService("@mozilla.org/AppsService;1");
+  if (NS_WARN_IF(!appsService)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  nsCOMPtr<mozIApplication> app;
+  nsresult rv = appsService->GetAppByLocalId(aAppId, getter_AddRefs(app));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!app) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  uint16_t status;
+  rv = app->GetAppStatus(&status);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (status != nsIPrincipal::APP_STATUS_CERTIFIED &&
+      !Preferences::GetBool("dom.testing.datastore_enabled_for_hosted_apps",
+                            false)) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+
+  aStores.Clear();
+
+  HashApp* apps = nullptr;
+  if (!mStores.Get(aName, &apps)) {
+    return NS_OK;
+  }
+
+  DataStoreInfo* info = nullptr;
+  if (apps->Get(aAppId, &info)) {
+    DataStoreInfo* owned = aStores.AppendElement();
+    owned->Init(info->mName, info->mOriginURL, info->mManifestURL, false,
+                info->mEnabled);
+  }
+
+  GetDataStoreInfosData data(mAccessStores, aName, aAppId, aStores);
+  apps->EnumerateRead(GetDataStoreInfosEnumerator, &data);
+  return NS_OK;
+}
+
+// This method is called when an app with DataStores is deleted.
+void
+DataStoreService::DeleteDataStores(uint32_t aAppId)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  mStores.Enumerate(DeleteDataStoresEnumerator, &aAppId);
+  mAccessStores.Enumerate(DeleteDataStoresEnumerator, &aAppId);
+}
+
+NS_IMETHODIMP
+DataStoreService::Observe(nsISupports* aSubject,
+                          const char* aTopic,
+                          const char16_t* aData)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  if (strcmp(aTopic, "webapps-clear-data")) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<mozIApplicationClearPrivateDataParams> params =
+    do_QueryInterface(aSubject);
+  MOZ_ASSERT(params);
+
+  // DataStore is explosed to apps, not browser content.
+  bool browserOnly;
+  nsresult rv = params->GetBrowserOnly(&browserOnly);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (browserOnly) {
+    return NS_OK;
+  }
+
+  uint32_t appId;
+  rv = params->GetAppId(&appId);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  DeleteDataStores(appId);
+
+  return NS_OK;
+}
+
+nsresult
+DataStoreService::AddPermissions(uint32_t aAppId,
+                                 const nsAString& aName,
+                                 const nsAString& aOriginURL,
+                                 const nsAString& aManifestURL,
+                                 bool aReadOnly)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // This is the permission name.
+  nsString permission;
+  GeneratePermissionName(permission, aName, aManifestURL);
+
+  // When a new DataStore is installed, the permissions must be set for the
+  // owner app.
+  nsresult rv = ResetPermission(aAppId, aOriginURL, aManifestURL, permission,
+                                aReadOnly);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // For any app that wants to have access to this DataStore we add the
+  // permissions.
+  HashApp* apps;
+  if (!mAccessStores.Get(aName, &apps)) {
+    return NS_OK;
+  }
+
+  AddPermissionsData data(permission, aReadOnly);
+  apps->EnumerateRead(AddPermissionsEnumerator, &data);
+  return data.mResult;
+}
+
+nsresult
+DataStoreService::AddAccessPermissions(uint32_t aAppId, const nsAString& aName,
+                                       const nsAString& aOriginURL,
+                                       const nsAString& aManifestURL,
+                                       bool aReadOnly)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  // When an app wants to have access to a DataStore, the permissions must be
+  // set.
+  HashApp* apps = nullptr;
+  if (!mStores.Get(aName, &apps)) {
+    return NS_OK;
+  }
+
+  AddAccessPermissionsData data(aAppId, aName, aOriginURL, aReadOnly);
+  apps->EnumerateRead(AddAccessPermissionsEnumerator, &data);
+  return data.mResult;
+}
+
+// This method starts the operation to create the first revision for a DataStore
+// if needed.
+nsresult
+DataStoreService::CreateFirstRevisionId(uint32_t aAppId,
+                                        const nsAString& aName,
+                                        const nsAString& aManifestURL)
+{
+  AssertIsInMainProcess();
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsRefPtr<DataStoreDB> db = new DataStoreDB(aManifestURL, aName);
+
+  nsRefPtr<FirstRevisionIdCallback> callback =
+    new FirstRevisionIdCallback(aAppId, aName, aManifestURL);
+
+  Sequence<nsString> dbs;
+  dbs.AppendElement(NS_LITERAL_STRING(DATASTOREDB_REVISION));
+
+  return db->Open(IDBTransactionMode::Readwrite, dbs, callback);
+}
+
+nsresult
+DataStoreService::EnableDataStore(uint32_t aAppId, const nsAString& aName,
+                                  const nsAString& aManifestURL)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  {
+    HashApp* apps = nullptr;
+    DataStoreInfo* info = nullptr;
+    if (mStores.Get(aName, &apps) && apps->Get(aAppId, &info)) {
+      info->Enable();
+    }
+  }
+
+  // Notify the child processes.
+  if (IsMainProcess()) {
+    nsTArray<ContentParent*> children;
+    ContentParent::GetAll(children);
+    for (uint32_t i = 0; i < children.Length(); i++) {
+      if (children[i]->NeedsDataStoreInfos()) {
+        unused << children[i]->SendDataStoreNotify(aAppId, nsAutoString(aName),
+                                                   nsAutoString(aManifestURL));
+      }
+    }
+  }
+
+  // Maybe we have some pending request waiting for this DataStore.
+  PendingRequests* requests;
+  if (!mPendingRequests.Get(aName, &requests)) {
+    return NS_OK;
+  }
+
+  for (uint32_t i = 0; i < requests->Length();) {
+    PendingRequest& request = requests->ElementAt(i);
+    nsTArray<nsString>::index_type pos =
+      request.mPendingDataStores.IndexOf(aManifestURL);
+    if (pos != request.mPendingDataStores.NoIndex) {
+      request.mPendingDataStores.RemoveElementAt(pos);
+
+      // No other pending dataStores.
+      if (request.mPendingDataStores.IsEmpty()) {
+        GetDataStoresResolve(request.mWindow, request.mPromise,
+                             request.mStores);
+        requests->RemoveElementAt(i);
+        continue;
+      }
+    }
+
+    ++i;
+  }
+
+  // No other pending requests for this name.
+  if (requests->IsEmpty()) {
+    mPendingRequests.Remove(aName);
+  }
+
+  return NS_OK;
+}
+
+already_AddRefed<RetrieveRevisionsCounter>
+DataStoreService::GetCounter(uint32_t aId) const
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  nsRefPtr<RetrieveRevisionsCounter> counter;
+  return mPendingCounters.Get(aId, getter_AddRefs(counter))
+           ? counter.forget() : nullptr;
+}
+
+void
+DataStoreService::RemoveCounter(uint32_t aId)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  mPendingCounters.Remove(aId);
+}
+
+nsresult
+DataStoreService::GetDataStoresFromIPC(const nsAString& aName,
+                                       nsIPrincipal* aPrincipal,
+                                       nsTArray<DataStoreSetting>* aValue)
+{
+  MOZ_ASSERT(IsMainProcess());
+  MOZ_ASSERT(NS_IsMainThread());
+
+  uint32_t appId;
+  nsresult rv = aPrincipal->GetAppId(&appId);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsTArray<DataStoreInfo> stores;
+  rv = GetDataStoreInfos(aName, appId, stores);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  for (uint32_t i = 0; i < stores.Length(); ++i) {
+    DataStoreSetting* data = aValue->AppendElement();
+    data->name() = stores[i].mName;
+    data->originURL() = stores[i].mOriginURL;
+    data->manifestURL() = stores[i].mManifestURL;
+    data->readOnly() = stores[i].mReadOnly;
+    data->enabled() = stores[i].mEnabled;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+DataStoreService::GenerateUUID(nsAString& aID)
+{
+  nsresult rv;
+
+  if (!mUUIDGenerator) {
+    mUUIDGenerator = do_GetService("@mozilla.org/uuid-generator;1", &rv);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  nsID id;
+  rv = mUUIDGenerator->GenerateUUIDInPlace(&id);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  char chars[NSID_LENGTH];
+  id.ToProvidedString(chars);
+  CopyASCIItoUTF16(chars, aID);
+
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/datastore/DataStoreService.h
@@ -0,0 +1,110 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_DataStoreService_h
+#define mozilla_dom_DataStoreService_h
+
+#include "mozilla/dom/PContent.h"
+#include "nsClassHashtable.h"
+#include "nsIDataStoreService.h"
+#include "nsIObserver.h"
+#include "nsRefPtrHashtable.h"
+
+class nsIPrincipal;
+class nsIUUIDGenerator;
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+
+class DataStoreInfo;
+class FirstRevisionIdCallback;
+class PendingRequest;
+class Promise;
+class RetrieveRevisionsCounter;
+class RevisionAddedEnableStoreCallback;
+
+class DataStoreService MOZ_FINAL : public nsIDataStoreService
+                                 , public nsIObserver
+{
+  friend class ContentChild;
+  friend class FirstRevisionIdCallback;
+  friend class RetrieveRevisionsCounter;
+  friend class RevisionAddedEnableStoreCallback;
+
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
+  NS_DECL_NSIDATASTORESERVICE
+
+  // Returns the DataStoreService singleton. Only to be called from main
+  // thread.
+  static already_AddRefed<DataStoreService> GetOrCreate();
+
+  static already_AddRefed<DataStoreService> Get();
+
+  static void Shutdown();
+
+  nsresult GenerateUUID(nsAString& aID);
+
+  nsresult GetDataStoresFromIPC(const nsAString& aName,
+                                nsIPrincipal* aPrincipal,
+                                nsTArray<DataStoreSetting>* aValue);
+
+private:
+  DataStoreService();
+  ~DataStoreService();
+
+  nsresult Init();
+
+  typedef nsClassHashtable<nsUint32HashKey, DataStoreInfo> HashApp;
+
+  nsresult AddPermissions(uint32_t aAppId, const nsAString& aName,
+                          const nsAString& aOriginURL,
+                          const nsAString& aManifestURL,
+                          bool aReadOnly);
+
+  nsresult AddAccessPermissions(uint32_t aAppId, const nsAString& aName,
+                                const nsAString& aOriginURL,
+                                const nsAString& aManifestURL,
+                                bool aReadOnly);
+
+  nsresult CreateFirstRevisionId(uint32_t aAppId, const nsAString& aName,
+                                 const nsAString& aManifestURL);
+
+  void GetDataStoresCreate(nsPIDOMWindow* aWindow, Promise* aPromise,
+                           const nsTArray<DataStoreInfo>& aStores);
+
+  void GetDataStoresResolve(nsPIDOMWindow* aWindow, Promise* aPromise,
+                            const nsTArray<DataStoreInfo>& aStores);
+
+  nsresult GetDataStoreInfos(const nsAString& aName, uint32_t aAppId,
+                             nsTArray<DataStoreInfo>& aStores);
+
+  void DeleteDataStores(uint32_t aAppId);
+
+  nsresult EnableDataStore(uint32_t aAppId, const nsAString& aName,
+                           const nsAString& aManifestURL);
+
+  already_AddRefed<RetrieveRevisionsCounter> GetCounter(uint32_t aId) const;
+
+  void RemoveCounter(uint32_t aId);
+
+  nsClassHashtable<nsStringHashKey, HashApp> mStores;
+  nsClassHashtable<nsStringHashKey, HashApp> mAccessStores;
+
+  typedef nsTArray<PendingRequest> PendingRequests;
+  nsClassHashtable<nsStringHashKey, PendingRequests> mPendingRequests;
+
+  nsRefPtrHashtable<nsUint32HashKey, RetrieveRevisionsCounter> mPendingCounters;
+
+  nsCOMPtr<nsIUUIDGenerator> mUUIDGenerator;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_DataStoreService_h
deleted file mode 100644
--- a/dom/datastore/DataStoreService.js
+++ /dev/null
@@ -1,522 +0,0 @@
-/* -*- Mode: js2; js2-basic-offset: 2; indent-tabs-mode: nil; -*- */
-/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-'use strict'
-
-/* static functions */
-
-function debug(s) {
-  //dump('DEBUG DataStoreService: ' + s + '\n');
-}
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-Cu.import('resource://gre/modules/Services.jsm');
-Cu.import('resource://gre/modules/DataStoreImpl.jsm');
-Cu.import("resource://gre/modules/DataStoreDB.jsm");
-Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
-                                   "@mozilla.org/childprocessmessagemanager;1",
-                                   "nsIMessageSender");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "permissionManager",
-                                   "@mozilla.org/permissionmanager;1",
-                                   "nsIPermissionManager");
-
-XPCOMUtils.defineLazyServiceGetter(this, "secMan",
-                                   "@mozilla.org/scriptsecuritymanager;1",
-                                   "nsIScriptSecurityManager");
-
-/* DataStoreService */
-
-const DATASTORESERVICE_CID = Components.ID('{d193d0e2-c677-4a7b-bb0a-19155b470f2e}');
-const REVISION_VOID = "void";
-
-function DataStoreService() {
-  debug('DataStoreService Constructor');
-
-  this.inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
-                    .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-
-  if (this.inParent) {
-    let obs = Services.obs;
-    if (!obs) {
-      debug("DataStore Error: observer-service is null!");
-      return;
-    }
-
-    obs.addObserver(this, 'webapps-clear-data', false);
-  }
-
-  let self = this;
-  cpmm.addMessageListener("datastore-first-revision-created",
-                          function(aMsg) { self.receiveMessage(aMsg); });
-}
-
-DataStoreService.prototype = {
-  inParent: false,
-
-  // Hash of DataStores
-  stores: {},
-  accessStores: {},
-  pendingRequests: {},
-
-  installDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    debug('installDataStore - appId: ' + aAppId + ', aName: ' +
-          aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
-          ', aReadOnly: ' + aReadOnly);
-
-    this.checkIfInParent();
-
-    if (aName in this.stores && aAppId in this.stores[aName]) {
-      debug('This should not happen');
-      return;
-    }
-
-    if (!(aName in this.stores)) {
-      this.stores[aName] = {};
-    }
-
-    // A DataStore is enabled when it has a first valid revision.
-    this.stores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
-                                   readOnly: aReadOnly, enabled: false };
-
-    this.addPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
-
-    this.createFirstRevisionId(aAppId, aName, aOwner);
-  },
-
-  installAccessDataStore: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    debug('installAccessDataStore - appId: ' + aAppId + ', aName: ' +
-          aName + ', aOrigin: ' + aOrigin + ', aOwner:' + aOwner +
-          ', aReadOnly: ' + aReadOnly);
-
-    this.checkIfInParent();
-
-    if (aName in this.accessStores && aAppId in this.accessStores[aName]) {
-      debug('This should not happen');
-      return;
-    }
-
-    if (!(aName in this.accessStores)) {
-      this.accessStores[aName] = {};
-    }
-
-    this.accessStores[aName][aAppId] = { origin: aOrigin, owner: aOwner,
-                                         readOnly: aReadOnly };
-    this.addAccessPermissions(aAppId, aName, aOrigin, aOwner, aReadOnly);
-  },
-
-  checkIfInParent: function() {
-    if (!this.inParent) {
-      throw "DataStore can execute this operation just in the parent process";
-    }
-  },
-
-  createFirstRevisionId: function(aAppId, aName, aOwner) {
-    debug("createFirstRevisionId database: " + aName);
-
-    let self = this;
-    let db = new DataStoreDB();
-    db.init(aOwner, aName);
-    db.revisionTxn(
-      'readwrite',
-      function(aTxn, aRevisionStore) {
-        debug("createFirstRevisionId - transaction success");
-
-        let request = aRevisionStore.openCursor(null, 'prev');
-        request.onsuccess = function(aEvent) {
-          let cursor = aEvent.target.result;
-          if (cursor) {
-            debug("First revision already created.");
-            self.enableDataStore(aAppId, aName, aOwner);
-          } else {
-            // If the revision doesn't exist, let's create the first one.
-            db.addRevision(aRevisionStore, 0, REVISION_VOID, function() {
-              debug("First revision created.");
-              self.enableDataStore(aAppId, aName, aOwner);
-            });
-          }
-        };
-      }
-    );
-  },
-
-  enableDataStore: function(aAppId, aName, aOwner) {
-    if (aName in this.stores && aAppId in this.stores[aName]) {
-      this.stores[aName][aAppId].enabled = true;
-      ppmm.broadcastAsyncMessage('datastore-first-revision-created',
-                                 { name: aName, owner: aOwner });
-    }
-  },
-
-  addPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    // When a new DataStore is installed, the permissions must be set for the
-    // owner app.
-    let permission = "indexedDB-chrome-" + aName + '|' + aOwner;
-    this.resetPermissions(aAppId, aOrigin, aOwner, permission, aReadOnly);
-
-    // For any app that wants to have access to this DataStore we add the
-    // permissions.
-    if (aName in this.accessStores) {
-      for (let appId in this.accessStores[aName]) {
-        // ReadOnly is decided by the owner first.
-        let readOnly = aReadOnly || this.accessStores[aName][appId].readOnly;
-        this.resetPermissions(appId, this.accessStores[aName][appId].origin,
-                              this.accessStores[aName][appId].owner,
-                              permission, readOnly);
-      }
-    }
-  },
-
-  addAccessPermissions: function(aAppId, aName, aOrigin, aOwner, aReadOnly) {
-    // When an app wants to have access to a DataStore, the permissions must be
-    // set.
-    if (!(aName in this.stores)) {
-      return;
-    }
-
-    for (let appId in this.stores[aName]) {
-      let permission = "indexedDB-chrome-" + aName + '|' + this.stores[aName][appId].owner;
-      // The ReadOnly is decied by the owenr first.
-      let readOnly = this.stores[aName][appId].readOnly || aReadOnly;
-      this.resetPermissions(aAppId, aOrigin, aOwner, permission, readOnly);
-    }
-  },
-
-  resetPermissions: function(aAppId, aOrigin, aOwner, aPermission, aReadOnly) {
-    debug("ResetPermissions - appId: " + aAppId + " - origin: " + aOrigin +
-          " - owner: " + aOwner + " - permissions: " + aPermission +
-          " - readOnly: " + aReadOnly);
-
-    let uri = Services.io.newURI(aOrigin, null, null);
-    let principal = secMan.getAppCodebasePrincipal(uri, aAppId, false);
-
-    let result = permissionManager.testExactPermissionFromPrincipal(principal,
-                                                                    aPermission + '-write');
-
-    if (aReadOnly && result == Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Write permission removed");
-      permissionManager.removeFromPrincipal(principal, aPermission + '-write');
-    } else if (!aReadOnly && result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Write permission added");
-      permissionManager.addFromPrincipal(principal, aPermission + '-write',
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
-
-    result = permissionManager.testExactPermissionFromPrincipal(principal,
-                                                                aPermission + '-read');
-    if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Read permission added");
-      permissionManager.addFromPrincipal(principal, aPermission + '-read',
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
-
-    result = permissionManager.testExactPermissionFromPrincipal(principal, aPermission);
-    if (result != Ci.nsIPermissionManager.ALLOW_ACTION) {
-      debug("Generic permission added");
-      permissionManager.addFromPrincipal(principal, aPermission,
-                                         Ci.nsIPermissionManager.ALLOW_ACTION);
-    }
-  },
-
-  getDataStores: function(aWindow, aName) {
-    debug('getDataStores - aName: ' + aName);
-
-    let self = this;
-    return new aWindow.Promise(function(resolve, reject) {
-      // If this request comes from the main process, we have access to the
-      // window, so we can skip the ipc communication.
-      if (self.inParent) {
-        let stores = self.getDataStoresInfo(aName, aWindow.document.nodePrincipal.appId);
-        if (stores === null) {
-          reject(new aWindow.DOMError("SecurityError", "Access denied"));
-          return;
-        }
-        self.getDataStoreCreate(aWindow, resolve, stores);
-      } else {
-        // This method can be called in the child so we need to send a request
-        // to the parent and create DataStore object here.
-        new DataStoreServiceChild(aWindow, aName, function(aStores) {
-          debug("DataStoreServiceChild success callback!");
-          self.getDataStoreCreate(aWindow, resolve, aStores);
-        }, function() {
-          debug("DataStoreServiceChild error callback!");
-          reject(new aWindow.DOMError("SecurityError", "Access denied"));
-        });
-      }
-    });
-  },
-
-  getDataStoresInfo: function(aName, aAppId) {
-    debug('GetDataStoresInfo');
-
-    let appsService = Cc["@mozilla.org/AppsService;1"]
-                        .getService(Ci.nsIAppsService);
-    let app = appsService.getAppByLocalId(aAppId);
-    if (!app) {
-      return null;
-    }
-
-    let prefName = "dom.testing.datastore_enabled_for_hosted_apps";
-    if (app.appStatus != Ci.nsIPrincipal.APP_STATUS_CERTIFIED &&
-        (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
-          !Services.prefs.getBoolPref(prefName))) {
-      return null;
-    }
-
-    let results = [];
-
-    if (aName in this.stores) {
-      if (aAppId in this.stores[aName]) {
-        results.push({ name: aName,
-                       owner: this.stores[aName][aAppId].owner,
-                       readOnly: false,
-                       enabled: this.stores[aName][aAppId].enabled });
-      }
-
-      for (var i in this.stores[aName]) {
-        if (i == aAppId) {
-          continue;
-        }
-
-        let access = this.getDataStoreAccess(aName, aAppId);
-        if (!access) {
-          continue;
-        }
-
-        let readOnly = this.stores[aName][i].readOnly || access.readOnly;
-        results.push({ name: aName,
-                       owner: this.stores[aName][i].owner,
-                       readOnly: readOnly,
-                       enabled: this.stores[aName][i].enabled });
-      }
-    }
-
-    return results;
-  },
-
-  getDataStoreCreate: function(aWindow, aResolve, aStores) {
-    debug("GetDataStoreCreate");
-
-    let results = new aWindow.Array();
-
-    if (!aStores.length) {
-      aResolve(results);
-      return;
-    }
-
-    let pendingDataStores = [];
-
-    for (let i = 0; i < aStores.length; ++i) {
-      if (!aStores[i].enabled) {
-        pendingDataStores.push(aStores[i].owner);
-      }
-    }
-
-    if (!pendingDataStores.length) {
-      this.getDataStoreResolve(aWindow, aResolve, aStores);
-      return;
-    }
-
-    if (!(aStores[0].name in this.pendingRequests)) {
-      this.pendingRequests[aStores[0].name] = [];
-    }
-
-    this.pendingRequests[aStores[0].name].push({ window: aWindow,
-                                                 resolve: aResolve,
-                                                 stores: aStores,
-                                                 pendingDataStores: pendingDataStores });
-  },
-
-  getDataStoreResolve: function(aWindow, aResolve, aStores) {
-    debug("GetDataStoreResolve");
-
-    let callbackPending = aStores.length;
-    let results = new aWindow.Array();
-
-    if (!callbackPending) {
-      aResolve(results);
-      return;
-    }
-
-    for (let i = 0; i < aStores.length; ++i) {
-      let obj = new DataStore(aWindow, aStores[i].name,
-                              aStores[i].owner, aStores[i].readOnly);
-
-      let storeImpl = aWindow.DataStoreImpl._create(aWindow, obj);
-
-      let exposedStore = new aWindow.DataStore();
-      exposedStore.setDataStoreImpl(storeImpl);
-
-      obj.exposedObject = exposedStore;
-
-      results.push(exposedStore);
-
-      obj.retrieveRevisionId(
-        function() {
-          --callbackPending;
-          if (!callbackPending) {
-            aResolve(results);
-          }
-        }
-      );
-    }
-  },
-
-  getDataStoreAccess: function(aName, aAppId) {
-    if (!(aName in this.accessStores) ||
-        !(aAppId in this.accessStores[aName])) {
-      return null;
-    }
-
-    return this.accessStores[aName][aAppId];
-  },
-
-  observe: function observe(aSubject, aTopic, aData) {
-    debug('observe - aTopic: ' + aTopic);
-    if (aTopic != 'webapps-clear-data') {
-      return;
-    }
-
-    let params =
-      aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams);
-
-    // DataStore is explosed to apps, not browser content.
-    if (params.browserOnly) {
-      return;
-    }
-
-    function isEmpty(aMap) {
-      for (var key in aMap) {
-        if (aMap.hasOwnProperty(key)) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    for (let key in this.stores) {
-      if (params.appId in this.stores[key]) {
-        this.deleteDatabase(key, this.stores[key][params.appId].owner);
-        delete this.stores[key][params.appId];
-      }
-
-      if (isEmpty(this.stores[key])) {
-        delete this.stores[key];
-      }
-    }
-
-    for (let key in this.accessStores) {
-      if (params.appId in this.accessStores[key]) {
-        delete this.accessStores[key][params.appId];
-      }
-
-      if (isEmpty(this.accessStores[key])) {
-        delete this.accessStores[key];
-      }
-    }
-  },
-
-  deleteDatabase: function(aName, aOwner) {
-    debug("delete database: " + aName);
-
-    let db = new DataStoreDB();
-    db.init(aOwner, aName);
-    db.delete();
-  },
-
-  receiveMessage: function(aMsg) {
-    debug("receiveMessage");
-    let data = aMsg.json;
-
-    if (!(data.name in this.pendingRequests)) {
-      return;
-    }
-
-    for (let i = 0; i < this.pendingRequests[data.name].length;) {
-      let pos = this.pendingRequests[data.name][i].pendingDataStores.indexOf(data.owner);
-      if (pos != -1) {
-        this.pendingRequests[data.name][i].pendingDataStores.splice(pos, 1);
-        if (!this.pendingRequests[data.name][i].pendingDataStores.length) {
-          this.getDataStoreResolve(this.pendingRequests[data.name][i].window,
-                                   this.pendingRequests[data.name][i].resolve,
-                                   this.pendingRequests[data.name][i].stores);
-          this.pendingRequests[data.name].splice(i, 1);
-          continue;
-        }
-      }
-
-      ++i;
-    }
-
-    if (!this.pendingRequests[data.name].length) {
-      delete this.pendingRequests[data.name];
-    }
-  },
-
-  classID : DATASTORESERVICE_CID,
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDataStoreService,
-                                         Ci.nsIObserver]),
-  classInfo: XPCOMUtils.generateCI({
-    classID: DATASTORESERVICE_CID,
-    contractID: '@mozilla.org/datastore-service;1',
-    interfaces: [Ci.nsIDataStoreService, Ci.nsIObserver],
-    flags: Ci.nsIClassInfo.SINGLETON
-  })
-};
-
-/* DataStoreServiceChild */
-
-function DataStoreServiceChild(aWindow, aName, aSuccessCb, aErrorCb) {
-  debug("DataStoreServiceChild created");
-  this.init(aWindow, aName, aSuccessCb, aErrorCb);
-}
-
-DataStoreServiceChild.prototype = {
-  __proto__: DOMRequestIpcHelper.prototype,
-
-  init: function(aWindow, aName, aSuccessCb, aErrorCb) {
-    debug("DataStoreServiceChild init");
-    this._successCb = aSuccessCb;
-    this._errorCb = aErrorCb;
-    this._name = aName;
-
-    this.initDOMRequestHelper(aWindow, [ "DataStore:Get:Return:OK",
-                                         "DataStore:Get:Return:KO" ]);
-
-    cpmm.sendAsyncMessage("DataStore:Get",
-                          { name: aName }, null, aWindow.document.nodePrincipal );
-  },
-
-  receiveMessage: function(aMessage) {
-    debug("DataStoreServiceChild receiveMessage");
-
-    if (aMessage.data.name != this._name) {
-      return;
-    }
-
-    switch (aMessage.name) {
-      case 'DataStore:Get:Return:OK':
-        this.destroyDOMRequestHelper();
-        this._successCb(aMessage.data.stores);
-        break;
-
-      case 'DataStore:Get:Return:KO':
-        this.destroyDOMRequestHelper();
-        this._errorCb();
-        break;
-    }
-  }
-}
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([DataStoreService]);
deleted file mode 100644
--- a/dom/datastore/DataStoreServiceInternal.jsm
+++ /dev/null
@@ -1,68 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict"
-
-const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
-
-this.EXPORTED_SYMBOLS = ["DataStoreServiceInternal"];
-
-function debug(s) {
-  //dump('DEBUG DataStoreServiceInternal: ' + s + '\n');
-}
-
-Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Services.jsm");
-
-XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
-                                   "@mozilla.org/parentprocessmessagemanager;1",
-                                   "nsIMessageBroadcaster");
-
-XPCOMUtils.defineLazyServiceGetter(this, "dataStoreService",
-                                   "@mozilla.org/datastore-service;1",
-                                   "nsIDataStoreService");
-
-this.DataStoreServiceInternal = {
-  init: function() {
-    debug("init");
-
-    let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
-                      .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
-    if (inParent) {
-      ppmm.addMessageListener("DataStore:Get", this);
-    }
-  },
-
-  receiveMessage: function(aMessage) {
-    debug("receiveMessage");
-
-    if (aMessage.name != 'DataStore:Get') {
-      return;
-    }
-
-    let prefName = 'dom.testing.datastore_enabled_for_hosted_apps';
-    if ((Services.prefs.getPrefType(prefName) == Services.prefs.PREF_INVALID ||
-         !Services.prefs.getBoolPref(prefName)) &&
-        !aMessage.target.assertAppHasStatus(Ci.nsIPrincipal.APP_STATUS_CERTIFIED)) {
-      return;
-    }
-
-    let msg = aMessage.data;
-
-    if (!aMessage.principal ||
-        aMessage.principal.appId == Ci.nsIScriptSecurityManager.UNKNOWN_APP_ID) {
-      aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO");
-      return;
-    }
-
-    msg.stores = dataStoreService.getDataStoresInfo(msg.name, aMessage.principal.appId);
-    if (msg.stores === null) {
-      aMessage.target.sendAsyncMessage("DataStore:Get:Return:KO");
-      return;
-    }
-    aMessage.target.sendAsyncMessage("DataStore:Get:Return:OK", msg);
-  }
-}
-
-DataStoreServiceInternal.init();
--- a/dom/datastore/moz.build
+++ b/dom/datastore/moz.build
@@ -1,42 +1,48 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
+    'nsIDataStore.idl',
     'nsIDataStoreService.idl',
 ]
 
 XPIDL_MODULE = 'dom_datastore'
 
 EXPORTS.mozilla.dom += [
     'DataStore.h',
     'DataStoreCursor.h',
+    'DataStoreService.h',
 ]
 
 SOURCES += [
     'DataStore.cpp',
     'DataStoreCursor.cpp',
+    'DataStoreDB.cpp',
+    'DataStoreRevision.cpp',
+    'DataStoreService.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/js/xpconnect/wrappers',
 ]
 
 EXTRA_COMPONENTS += [
     'DataStore.manifest',
-    'DataStoreService.js',
+    'DataStoreImpl.js',
 ]
 
 EXTRA_JS_MODULES += [
     'DataStoreChangeNotifier.jsm',
     'DataStoreCursorImpl.jsm',
     'DataStoreDB.jsm',
-    'DataStoreImpl.jsm',
-    'DataStoreServiceInternal.jsm',
 ]
 
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
+FAIL_ON_WARNINGS = True
new file mode 100644
--- /dev/null
+++ b/dom/datastore/nsIDataStore.idl
@@ -0,0 +1,23 @@
+/* -*- 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 "nsISupports.idl"
+
+interface nsIDOMWindow;
+
+// NOTE: This is a temporary interface.
+// It will be removed in the next patches for rewriting DataStore in C++.
+[scriptable, uuid(0b41fef5-14ba-48b0-923c-3d8fb64692ae)]
+interface nsIDataStore : nsISupports
+{
+  void init(in nsIDOMWindow window,
+            in DOMString name,
+            in DOMString manifestURL,
+            in boolean readOnly);
+
+  attribute jsval exposedObject;
+
+  void retrieveRevisionId(in jsval cb);
+};
--- a/dom/datastore/nsIDataStoreService.idl
+++ b/dom/datastore/nsIDataStoreService.idl
@@ -2,34 +2,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 
-[scriptable, uuid(bd02d09c-41ab-47b7-9319-57aa8e5059b0)]
+[scriptable, uuid(0a050c4f-d292-4a14-8712-09bc1019840a)]
 interface nsIDataStoreService : nsISupports
 {
   void installDataStore(in unsigned long appId,
                         in DOMString name,
                         in DOMString originURL,
                         in DOMString manifestURL,
                         in boolean readOnly);
 
   void installAccessDataStore(in unsigned long appId,
                               in DOMString name,
                               in DOMString originURL,
                               in DOMString manifestURL,
                               in boolean readOnly);
 
   nsISupports getDataStores(in nsIDOMWindow window,
                             in DOMString name);
-
-  // This is an array of objects composed by:
-  // - readOnly: boolean
-  // - name: DOMString
-  // - owner: DOMString
-  // - enabled: true/false - true if this dataStore is ready to be used.
-  jsval getDataStoresInfo(in DOMString name,
-                          in unsigned long appId);
 };
new file mode 100644
--- /dev/null
+++ b/dom/datastore/tests/file_bug957086.html
@@ -0,0 +1,34 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for DataStore - bug 1008044</title>
+</head>
+<body>
+<div id="container"></div>
+  <script type="application/javascript;version=1.7">
+
+function is(a, b, msg) {
+  alert((a == b ? 'OK' : 'KO') + ' ' + msg)
+}
+
+function cbError() {
+  alert('KO error');
+}
+
+function finish() {
+  alert('DONE');
+}
+
+navigator.getDataStores('foo').then(function(stores) {
+  is (stores.length, 1, "Correct number of Stores");
+  is (stores[0].name, 'foo', "Correct name is received!");
+  stores[0].get(42).then(function(something) {
+    is (something, null, "Correct value");
+    finish();
+  }, cbError);
+}, cbError);
+
+  </script>
+</body>
+</html>
--- a/dom/datastore/tests/mochitest.ini
+++ b/dom/datastore/tests/mochitest.ini
@@ -24,16 +24,17 @@ support-files =
   file_bug986056.html
   file_bug986056.template.webapp
   file_event_maker.html
   file_event_receiver.html
   file_transactions.html
   file_basic_common.js
   file_sync_common.js
   file_bug1008044.html
+  file_bug957086.html
 
 [test_app_install.html]
 [test_readonly.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) # b2g-debug(debug-only failure; time out) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_basic.html]
 [test_basic_worker.html]
 [test_changes.html]
 skip-if = (toolkit == 'gonk' && debug) #intermittent failures, bug 961021
@@ -49,8 +50,9 @@ skip-if = (buildapp == 'b2g' && (toolkit
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure; time out
 [test_keys.html]
 [test_duplicate.html]
 [test_bug976311.html]
 [test_bug986056.html]
 [test_oop_events.html]
 [test_transactions.html]
 [test_bug1008044.html]
+[test_bug957086.html]
copy from dom/datastore/tests/test_basic.html
copy to dom/datastore/tests/test_bug957086.html
--- a/dom/datastore/tests/test_basic.html
+++ b/dom/datastore/tests/test_bug957086.html
@@ -1,53 +1,57 @@
 <!DOCTYPE HTML>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>Test for DataStore - basic operation on a readonly db</title>
+  <title>Test for DataStore - bug 957086</title>
   <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
 </head>
 <body>
 <div id="container"></div>
   <script type="application/javascript;version=1.7">
 
-  var gHostedManifestURL = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_basic.html';
-  var gApp;
+  var gHostedManifestURL1 = 'http://test/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug957086.html&template=file_app2.template.webapp';
+  var gHostedManifestURL2 = 'http://example.com/tests/dom/datastore/tests/file_app.sjs?testToken=file_bug957086.html';
+  var gApps = [];
 
   function cbError() {
     ok(false, "Error callback invoked");
     finish();
   }
 
-  function installApp() {
-    var request = navigator.mozApps.install(gHostedManifestURL);
+  function installApp(manifest) {
+    var request = navigator.mozApps.install(manifest);
     request.onerror = cbError;
     request.onsuccess = function() {
-      gApp = request.result;
+      gApps.push(request.result);
       runTest();
     }
   }
 
   function uninstallApp() {
-    // Uninstall the app.
-    var request = navigator.mozApps.mgmt.uninstall(gApp);
-    request.onerror = cbError;
-    request.onsuccess = function() {
+    if (!gApps.length) {
       // All done.
       info("All done");
       runTest();
+      return;
     }
+
+    // Uninstall the app.
+    var request = navigator.mozApps.mgmt.uninstall(gApps.pop());
+    request.onerror = cbError;
+    request.onsuccess = uninstallApp;
   }
 
   function testApp() {
     var ifr = document.createElement('iframe');
     ifr.setAttribute('mozbrowser', 'true');
-    ifr.setAttribute('mozapp', gApp.manifestURL);
-    ifr.setAttribute('src', gApp.manifest.launch_path);
+    ifr.setAttribute('mozapp', gApps[0].manifestURL);
+    ifr.setAttribute('src', gApps[0].manifest.launch_path);
     var domParent = document.getElementById('container');
 
     // Set us up to listen for messages from the app.
     var listener = function(e) {
       var message = e.detail.message;
       if (/^OK/.exec(message)) {
         ok(true, "Message from app: " + message);
       } else if (/KO/.exec(message)) {
@@ -72,33 +76,37 @@
         [{ "type": "browser", "allow": 1, "context": document },
          { "type": "embed-apps", "allow": 1, "context": document },
          { "type": "webapps-manage", "allow": 1, "context": document }], runTest);
     },
 
     // Preferences
     function() {
       SpecialPowers.pushPrefEnv({"set": [["dom.datastore.enabled", true],
+                                         ["dom.ipc.browser_frames.oop_by_default", true],
                                          ["dom.testing.ignore_ipc_principal", true],
                                          ["dom.testing.datastore_enabled_for_hosted_apps", true]]}, runTest);
     },
 
     function() {
       SpecialPowers.setAllAppsLaunchable(true);
       SpecialPowers.setBoolPref("dom.mozBrowserFramesEnabled", true);
       runTest();
     },
 
     // No confirmation needed when an app is installed
     function() {
       SpecialPowers.autoConfirmAppInstall(runTest);
     },
 
-    // Installing the app
-    installApp,
+    // Installing the app - access only
+    function() { installApp(gHostedManifestURL1) },
+
+    // Installing the app - owner only
+    function() { installApp(gHostedManifestURL2) },
 
     // Run tests in app
     testApp,
 
     // Uninstall the app
     uninstallApp
   ];
 
--- a/dom/identity/Identity.manifest
+++ b/dom/identity/Identity.manifest
@@ -1,8 +1,9 @@
 # nsDOMIdentity.js
 component {210853d9-2c97-4669-9761-b1ab9cbf57ef} nsDOMIdentity.js
-contract @mozilla.org/identity/manager;1 {210853d9-2c97-4669-9761-b1ab9cbf57ef}
+contract @mozilla.org/dom/identity;1 {210853d9-2c97-4669-9761-b1ab9cbf57ef}
+category JavaScript-navigator-property mozId @mozilla.org/dom/identity;1
 
 # nsIDService.js (initialization on startup)
 component {4e0a0e98-b1d3-4745-a1eb-f815199dd06b} nsIDService.js
 contract @mozilla.org/dom/identity/service;1 {4e0a0e98-b1d3-4745-a1eb-f815199dd06b}
 category app-startup IDService @mozilla.org/dom/identity/service;1
--- a/dom/identity/nsDOMIdentity.js
+++ b/dom/identity/nsDOMIdentity.js
@@ -43,20 +43,39 @@ const ERRORS = {
   "ERROR_NOT_AUTHORIZED_FOR_FIREFOX_ACCOUNTS":
     "Only privileged and certified apps may use Firefox Accounts",
   "ERROR_INVALID_ASSERTION_AUDIENCE":
     "Assertion audience may not differ from origin",
   "ERROR_REQUEST_WHILE_NOT_HANDLING_USER_INPUT":
     "The request() method may only be invoked when handling user input",
 };
 
-function nsDOMIdentity() {
+function nsDOMIdentity(aIdentityInternal) {
+  this._identityInternal = aIdentityInternal;
 }
+nsDOMIdentity.prototype = {
+  __exposedProps__: {
+    // Relying Party (RP)
+    watch: 'r',
+    request: 'r',
+    logout: 'r',
+    get: 'r',
+    getVerifiedEmail: 'r',
 
-nsDOMIdentity.prototype = {
+    // Provisioning
+    beginProvisioning: 'r',
+    genKeyPair: 'r',
+    registerCertificate: 'r',
+    raiseProvisioningFailure: 'r',
+
+    // Authentication
+    beginAuthentication: 'r',
+    completeAuthentication: 'r',
+    raiseAuthenticationFailure: 'r'
+  },
 
   // require native events unless syntheticEventsOk is set
   get nativeEventsRequired() {
     if (Services.prefs.prefHasUserValue(PREF_SYNTHETIC_EVENTS_OK) &&
         (Services.prefs.getPrefType(PREF_SYNTHETIC_EVENTS_OK) ===
          Ci.nsIPrefBranch.PREF_BOOL)) {
       return !Services.prefs.getBoolPref(PREF_SYNTHETIC_EVENTS_OK);
     }
@@ -125,17 +144,17 @@ nsDOMIdentity.prototype = {
     this._rpWatcher.audience = message.audience;
 
     if (message.errors.length) {
       this.reportErrors(message);
       // We don't delete the rpWatcher object, because we don't want the
       // broken client to be able to call watch() any more.  It's broken.
       return;
     }
-    this._mm.sendAsyncMessage("Identity:RP:Watch", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:RP:Watch", message);
   },
 
   request: function nsDOMIdentity_request(aOptions = {}) {
     this._log("request: " + JSON.stringify(aOptions));
 
     // Has the caller called watch() before this?
     if (!this._rpWatcher) {
       throw new Error("navigator.id.request called before navigator.id.watch");
@@ -195,17 +214,17 @@ nsDOMIdentity.prototype = {
         throw new Error("oncancel is not a function");
       } else {
         // Store optional cancel callback for later.
         this._onCancelRequestCallback = aOptions.oncancel;
       }
     }
 
     this._rpCalls++;
-    this._mm.sendAsyncMessage("Identity:RP:Request", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:RP:Request", message);
   },
 
   logout: function nsDOMIdentity_logout() {
     if (!this._rpWatcher) {
       throw new Error("navigator.id.logout called before navigator.id.watch");
     }
     if (this._rpCalls > MAX_RP_CALLS) {
       throw new Error("navigator.id.logout called too many times");
@@ -215,17 +234,17 @@ nsDOMIdentity.prototype = {
     let message = this.DOMIdentityMessage();
 
     // Report and fail hard on any errors.
     if (message.errors.length) {
       this.reportErrors(message);
       return;
     }
 
-    this._mm.sendAsyncMessage("Identity:RP:Logout", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:RP:Logout", message);
   },
 
   /*
    * Get an assertion.  This function is deprecated.  RPs are
    * encouraged to use the observer API instead (watch + request).
    */
   get: function nsDOMIdentity_get(aCallback, aOptions) {
     var opts = {};
@@ -298,65 +317,65 @@ nsDOMIdentity.prototype = {
     if (this._beginProvisioningCallback) {
       throw new Error("navigator.id.beginProvisioning already called.");
     }
     if (!aCallback || typeof(aCallback) !== "function") {
       throw new Error("beginProvisioning callback is required.");
     }
 
     this._beginProvisioningCallback = aCallback;
-    this._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginProvisioning",
                                                 this.DOMIdentityMessage());
   },
 
   genKeyPair: function nsDOMIdentity_genKeyPair(aCallback) {
     this._log("genKeyPair");
     if (!this._beginProvisioningCallback) {
       throw new Error("navigator.id.genKeyPair called outside of provisioning");
     }
     if (this._genKeyPairCallback) {
       throw new Error("navigator.id.genKeyPair already called.");
     }
     if (!aCallback || typeof(aCallback) !== "function") {
       throw new Error("genKeyPair callback is required.");
     }
 
     this._genKeyPairCallback = aCallback;
-    this._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:GenKeyPair",
                                                 this.DOMIdentityMessage());
   },
 
   registerCertificate: function nsDOMIdentity_registerCertificate(aCertificate) {
     this._log("registerCertificate");
     if (!this._genKeyPairCallback) {
       throw new Error("navigator.id.registerCertificate called outside of provisioning");
     }
     if (this._provisioningEnded) {
       throw new Error("Provisioning already ended");
     }
     this._provisioningEnded = true;
 
     let message = this.DOMIdentityMessage();
     message.cert = aCertificate;
-    this._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:RegisterCertificate", message);
   },
 
   raiseProvisioningFailure: function nsDOMIdentity_raiseProvisioningFailure(aReason) {
     this._log("raiseProvisioningFailure '" + aReason + "'");
     if (this._provisioningEnded) {
       throw new Error("Provisioning already ended");
     }
     if (!aReason || typeof(aReason) != "string") {
       throw new Error("raiseProvisioningFailure reason is required");
     }
     this._provisioningEnded = true;
 
     let message = this.DOMIdentityMessage();
     message.reason = aReason;
-    this._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:ProvisioningFailure", message);
   },
 
   /**
    *  Identity Provider (IDP) Authentication APIs
    */
 
   beginAuthentication: function nsDOMIdentity_beginAuthentication(aCallback) {
     this._log("beginAuthentication");
@@ -366,44 +385,64 @@ nsDOMIdentity.prototype = {
     if (typeof(aCallback) !== "function") {
       throw new Error("beginAuthentication callback is required.");
     }
     if (!aCallback || typeof(aCallback) !== "function") {
       throw new Error("beginAuthentication callback is required.");
     }
 
     this._beginAuthenticationCallback = aCallback;
-    this._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:BeginAuthentication",
                                                 this.DOMIdentityMessage());
   },
 
   completeAuthentication: function nsDOMIdentity_completeAuthentication() {
     if (this._authenticationEnded) {
       throw new Error("Authentication already ended");
     }
     if (!this._beginAuthenticationCallback) {
       throw new Error("navigator.id.completeAuthentication called outside of authentication");
     }
     this._authenticationEnded = true;
 
-    this._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:CompleteAuthentication",
                                                 this.DOMIdentityMessage());
   },
 
   raiseAuthenticationFailure: function nsDOMIdentity_raiseAuthenticationFailure(aReason) {
     if (this._authenticationEnded) {
       throw new Error("Authentication already ended");
     }
     if (!aReason || typeof(aReason) != "string") {
       throw new Error("raiseProvisioningFailure reason is required");
     }
 
     let message = this.DOMIdentityMessage();
     message.reason = aReason;
-    this._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
+    this._identityInternal._mm.sendAsyncMessage("Identity:IDP:AuthenticationFailure", message);
+  },
+
+  // Private.
+  _init: function nsDOMIdentity__init(aWindow) {
+
+    this._initializeState();
+
+    // Store window and origin URI.
+    this._window = aWindow;
+    this._origin = aWindow.document.nodePrincipal.origin;
+    this._appStatus = aWindow.document.nodePrincipal.appStatus;
+    this._appId = aWindow.document.nodePrincipal.appId;
+
+    // Setup identifiers for current window.
+    let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
+                      .getInterface(Ci.nsIDOMWindowUtils);
+
+    // We need to inherit the id from the internalIdentity service.
+    // See comments below in that service's init.
+    this._id = this._identityInternal._id;
   },
 
   /**
    * Called during init and shutdown.
    */
   _initializeState: function nsDOMIdentity__initializeState() {
     // Some state to prevent abuse
     // Limit the number of calls to .request
@@ -413,28 +452,22 @@ nsDOMIdentity.prototype = {
 
     this._rpWatcher = null;
     this._onCancelRequestCallback = null;
     this._beginProvisioningCallback = null;
     this._genKeyPairCallback = null;
     this._beginAuthenticationCallback = null;
   },
 
-  // nsIMessageListener
-  receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
+  _receiveMessage: function nsDOMIdentity_receiveMessage(aMessage) {
     let msg = aMessage.json;
 
-    // Is this message intended for this window?
-    if (msg.id != this._id) {
-      return;
-    }
-
     switch (aMessage.name) {
       case "Identity:ResetState":
-        if (!this._debug) {
+        if (!this._identityInternal._debug) {
           return;
         }
         this._initializeState();
         Services.obs.notifyObservers(null, "identity-DOM-state-reset", this._id);
         break;
       case "Identity:RP:Watch:OnLogin":
         // Do we have a watcher?
         if (!this._rpWatcher) {
@@ -500,16 +533,20 @@ nsDOMIdentity.prototype = {
         this._callGenKeyPairCallback(msg);
         break;
       case "Identity:IDP:CallBeginAuthenticationCallback":
         this._callBeginAuthenticationCallback(msg);
         break;
     }
   },
 
+  _log: function nsDOMIdentity__log(msg) {
+    this._identityInternal._log(msg);
+  },
+
   _callGenKeyPairCallback: function nsDOMIdentity__callGenKeyPairCallback(message) {
     // create a pubkey object that works
     let chrome_pubkey = JSON.parse(message.publicKey);
 
     // bunch of stuff to create a proper object in window context
     function genPropDesc(value) {
       return {
         enumerable: true, configurable: true, writable: true, value: value
@@ -600,49 +637,71 @@ nsDOMIdentity.prototype = {
     // Replace any audience supplied by the RP with one that has been sanitised
     message.audience = _audience;
 
     this._log("DOMIdentityMessage: " + JSON.stringify(message));
 
     return message;
   },
 
-  /*
-   * Internal methods that are not exposed to content.
-   * See dom/webidl/Identity.webidl for the public interface.
-   */
+  uninit: function DOMIdentity_uninit() {
+    this._log("nsDOMIdentity uninit() " + this._id);
+    this._identityInternal._mm.sendAsyncMessage(
+      "Identity:RP:Unwatch",
+      { id: this._id }
+    );
+  }
+
+};
+
+/**
+ * Internal functions that shouldn't be exposed to content.
+ */
+function nsDOMIdentityInternal() {
+}
+nsDOMIdentityInternal.prototype = {
+
+  // nsIMessageListener
+  receiveMessage: function nsDOMIdentityInternal_receiveMessage(aMessage) {
+    let msg = aMessage.json;
+    // Is this message intended for this window?
+    if (msg.id != this._id) {
+      return;
+    }
+    this._identity._receiveMessage(aMessage);
+  },
 
   // nsIObserver
   observe: function nsDOMIdentityInternal_observe(aSubject, aTopic, aData) {
     let wId = aSubject.QueryInterface(Ci.nsISupportsPRUint64).data;
     if (wId != this._innerWindowID) {
       return;
     }
 
-    this.uninit();
+    this._identity.uninit();
 
     Services.obs.removeObserver(this, "inner-window-destroyed");
-    this._initializeState();
+    this._identity._initializeState();
+    this._identity = null;
 
     // TODO: Also send message to DOMIdentity notifiying window is no longer valid
     // ie. in the case that the user closes the auth. window and we need to know.
 
     try {
       for (let msgName of this._messages) {
         this._mm.removeMessageListener(msgName, this);
       }
     } catch (ex) {
       // Avoid errors when removing more than once.
     }
 
     this._mm = null;
   },
 
-  //  Because we implement nsIDOMGlobalPropertyInitializer, our init() method
-  //  is invoked with content window as its single argument.
+  // nsIDOMGlobalPropertyInitializer
   init: function nsDOMIdentityInternal_init(aWindow) {
     if (Services.prefs.getPrefType(PREF_ENABLED) != Ci.nsIPrefBranch.PREF_BOOL
         || !Services.prefs.getBoolPref(PREF_ENABLED)) {
       return null;
     }
 
     this._debug =
       Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL
@@ -656,27 +715,18 @@ nsDOMIdentity.prototype = {
     //
     // XXX Bug 869182 - use a combination of child process id and
     // innerwindow id to construct the unique id.
     this._id = uuidgen.generateUUID().toString();
     this._innerWindowID = util.currentInnerWindowID;
 
     // nsDOMIdentity needs to know our _id, so this goes after
     // its creation.
-    this._initializeState();
-
-    // Store window and origin URI.
-    this._window = aWindow;
-    this._origin = aWindow.document.nodePrincipal.origin;
-    this._appStatus = aWindow.document.nodePrincipal.appStatus;
-    this._appId = aWindow.document.nodePrincipal.appId;
-
-    // Setup identifiers for current window.
-    let util = aWindow.QueryInterface(Ci.nsIInterfaceRequestor)
-                      .getInterface(Ci.nsIDOMWindowUtils);
+    this._identity = new nsDOMIdentity(this);
+    this._identity._init(aWindow);
 
     this._log("init was called from " + aWindow.document.location);
 
     this._mm = cpmm;
 
     // Setup listeners for messages from parent process.
     this._messages = [
       "Identity:ResetState",
@@ -690,42 +740,34 @@ nsDOMIdentity.prototype = {
       "Identity:IDP:CallBeginAuthenticationCallback"
     ];
     this._messages.forEach(function(msgName) {
       this._mm.addMessageListener(msgName, this);
     }, this);
 
     // Setup observers so we can remove message listeners.
     Services.obs.addObserver(this, "inner-window-destroyed", false);
-  },
 
-  uninit: function DOMIdentity_uninit() {
-    this._log("nsDOMIdentity uninit() " + this._id);
-    this._mm.sendAsyncMessage(
-      "Identity:RP:Unwatch",
-      { id: this._id }
-    );
+    return this._identity;
   },
 
   // Private.
   _log: function nsDOMIdentityInternal__log(msg) {
     if (!this._debug) {
       return;
     }
     dump("nsDOMIdentity (" + this._id + "): " + msg + "\n");
   },
 
   // Component setup.
   classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
 
-  QueryInterface: XPCOMUtils.generateQI([
-      Ci.nsIMessageListener,
-      Ci.nsIObserver,
-      Ci.nsIDOMGlobalPropertyInitializer
-  ]),
+  QueryInterface: XPCOMUtils.generateQI(
+    [Ci.nsIDOMGlobalPropertyInitializer, Ci.nsIMessageListener]
+  ),
 
   classInfo: XPCOMUtils.generateCI({
     classID: Components.ID("{210853d9-2c97-4669-9761-b1ab9cbf57ef}"),
     contractID: "@mozilla.org/dom/identity;1",
     interfaces: [],
     classDescription: "Identity DOM Implementation"
   })
 };
@@ -757,9 +799,9 @@ function assertCorrectCallbacks(aOptions
 
   for (let cbName of optionalCallbacks) {
     if (aOptions[cbName] && typeof(aOptions[cbName]) != "function") {
       throw new Error(cbName + " must be a function");
     }
   }
 }
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentity]);
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([nsDOMIdentityInternal]);
--- a/dom/indexedDB/IDBFactory.cpp
+++ b/dom/indexedDB/IDBFactory.cpp
@@ -230,19 +230,16 @@ IDBFactory::Create(JSContext* aCx,
 // static
 nsresult
 IDBFactory::Create(ContentParent* aContentParent,
                    IDBFactory** aFactory)
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(IndexedDatabaseManager::IsMainProcess(), "Wrong process!");
   NS_ASSERTION(nsContentUtils::IsCallerChrome(), "Only for chrome!");
-  NS_ASSERTION(aContentParent, "Null ContentParent!");
-
-  NS_ASSERTION(!nsContentUtils::GetCurrentJSContext(), "Should be called from C++");
 
   // We need to get this information before we push a null principal to avoid
   // IsCallerChrome() assertion in quota manager.
   nsCString group;
   nsCString origin;
   StoragePrivilege privilege;
   PersistenceType defaultPersistenceType;
   QuotaManager::GetInfoForChrome(&group, &origin, &privilege,
--- a/dom/indexedDB/IDBFactory.h
+++ b/dom/indexedDB/IDBFactory.h
@@ -70,17 +70,17 @@ public:
   // Called when using IndexedDB from a JS component or a JSM in the current
   // process.
   static nsresult Create(JSContext* aCx,
                          JS::Handle<JSObject*> aOwningObject,
                          ContentParent* aContentParent,
                          IDBFactory** aFactory);
 
   // Called when using IndexedDB from a JS component or a JSM in a different
-  // process.
+  // process or from a C++ component.
   static nsresult Create(ContentParent* aContentParent,
                          IDBFactory** aFactory);
 
   static already_AddRefed<nsIFileURL>
   GetDatabaseFileURL(nsIFile* aDatabaseFile,
                      PersistenceType aPersistenceType,
                      const nsACString& aGroup,
                      const nsACString& aOrigin);
--- a/dom/indexedDB/IDBRequest.cpp
+++ b/dom/indexedDB/IDBRequest.cpp
@@ -322,17 +322,17 @@ IDBRequest::ReadyState() const
 
 JSObject*
 IDBRequest::WrapObject(JSContext* aCx)
 {
   return IDBRequestBinding::Wrap(aCx, this);
 }
 
 JS::Value
-IDBRequest::GetResult(JSContext* aCx, mozilla::ErrorResult& aRv) const
+IDBRequest::GetResult(mozilla::ErrorResult& aRv) const
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
 
   if (!mHaveResultOrErrorCode) {
     // XXX Need a real error code here.
     aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR);
   }
 
--- a/dom/indexedDB/IDBRequest.h
+++ b/dom/indexedDB/IDBRequest.h
@@ -127,17 +127,23 @@ public:
   // WebIDL
   nsPIDOMWindow*
   GetParentObject() const
   {
     return GetOwner();
   }
 
   JS::Value
-  GetResult(JSContext* aCx, ErrorResult& aRv) const;
+  GetResult(ErrorResult& aRv) const;
+
+  JS::Value
+  GetResult(JSContext* aCx, ErrorResult& aRv) const
+  {
+    return GetResult(aRv);
+  }
 
   IDBTransaction*
   GetTransaction() const
   {
     NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
     return mTransaction;
   }
 
--- a/dom/interfaces/base/nsIDOMWindow.idl
+++ b/dom/interfaces/base/nsIDOMWindow.idl
@@ -19,17 +19,17 @@ interface nsIVariant;
  * The nsIDOMWindow interface is the primary interface for a DOM
  * window object. It represents a single window object that may
  * contain child windows if the document in the window contains a
  * HTML frameset document or if the document contains iframe elements.
  *
  * @see <http://www.whatwg.org/html/#window>
  */
 
-[scriptable, uuid(fbefa573-0ba2-4d15-befb-d60277643a0b)]
+[scriptable, uuid(d4316591-d16e-405c-8093-b441cbef3230)]
 interface nsIDOMWindow : nsISupports
 {
   // the current browsing context
   readonly attribute nsIDOMWindow                       window;
 
   /* [replaceable] self */
   readonly attribute nsIDOMWindow                       self;
 
@@ -146,17 +146,21 @@ interface nsIDOMWindow : nsISupports
 
   %{C++
   inline nsresult GetParent(nsIDOMWindow **aWindow)
   {
     return GetRealParent(aWindow);
   }
   %}
 
-           attribute nsIDOMWindow                       opener;
+  [implicit_jscontext, binaryname(ScriptableOpener)]
+           attribute jsval                              opener;
+
+  [noscript, binaryname(Opener)]
+           attribute nsIDOMWindow                       openerWindow;
 
   /**
    * |frameElement| gets this window's <iframe> or <frame> element, if it has
    * one.
    *
    * When script reads this property (or when C++ calls
    * ScriptableFrameElement), we return |null| if the window is inside an
    * <iframe mozbrowser>.  In contrast, when C++ calls GetFrameElement, we
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -137,16 +137,17 @@
 #include "ProcessUtils.h"
 #include "StructuredCloneUtils.h"
 #include "URIUtils.h"
 #include "nsContentUtils.h"
 #include "nsIPrincipal.h"
 #include "nsDeviceStorage.h"
 #include "AudioChannelService.h"
 #include "JavaScriptChild.h"
+#include "mozilla/dom/DataStoreService.h"
 #include "mozilla/dom/telephony/PTelephonyChild.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 
 using namespace base;
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
@@ -764,16 +765,34 @@ ContentChild::RecvAudioChannelNotify()
         AudioChannelService::GetAudioChannelService();
     if (service) {
         service->Notify();
     }
     return true;
 }
 
 bool
+ContentChild::RecvDataStoreNotify(const uint32_t& aAppId,
+                                  const nsString& aName,
+                                  const nsString& aManifestURL)
+{
+  nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
+  if (NS_WARN_IF(!service)) {
+    return false;
+  }
+
+  nsresult rv = service->EnableDataStore(aAppId, aName, aManifestURL);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  return true;
+}
+
+bool
 ContentChild::DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor)
 {
     static_cast<MemoryReportRequestChild*>(actor)->Release();
     return true;
 }
 
 PCycleCollectWithLogsChild*
 ContentChild::AllocPCycleCollectWithLogsChild(const bool& aDumpAllTraces,
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -152,16 +152,20 @@ public:
     RecvPCycleCollectWithLogsConstructor(PCycleCollectWithLogsChild* aChild,
                                          const bool& aDumpAllTraces,
                                          const FileDescriptor& aGCLog,
                                          const FileDescriptor& aCCLog) MOZ_OVERRIDE;
 
     virtual bool
     RecvAudioChannelNotify() MOZ_OVERRIDE;
 
+    virtual bool
+    RecvDataStoreNotify(const uint32_t& aAppId, const nsString& aName,
+                        const nsString& aManifestURL) MOZ_OVERRIDE;
+
     virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE;
     virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE;
     virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE;
     jsipc::JavaScriptChild *GetCPOWManager();
 
     virtual PNeckoChild* AllocPNeckoChild() MOZ_OVERRIDE;
     virtual bool DeallocPNeckoChild(PNeckoChild*) MOZ_OVERRIDE;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -28,16 +28,17 @@
 #include "IHistory.h"
 #include "IDBFactory.h"
 #include "IndexedDBParent.h"
 #include "IndexedDatabaseManager.h"
 #include "mozIApplication.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/Element.h"
+#include "mozilla/dom/DataStoreService.h"
 #include "mozilla/dom/ExternalHelperAppParent.h"
 #include "mozilla/dom/PFileDescriptorSetParent.h"
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/DOMStorageIPC.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
@@ -1499,16 +1500,17 @@ ContentParent::InitializeMembers()
 {
     mSubprocess = nullptr;
     mChildID = gContentChildID++;
     mGeolocationWatchID = -1;
     mForceKillTask = nullptr;
     mNumDestroyingTabs = 0;
     mIsAlive = true;
     mSendPermissionUpdates = false;
+    mSendDataStoreInfos = false;
     mCalledClose = false;
     mCalledCloseWithError = false;
     mCalledKillHard = false;
 }
 
 ContentParent::ContentParent(mozIApplication* aApp,
                              bool aIsForBrowser,
                              bool aIsForPreallocated,
@@ -2081,16 +2083,36 @@ ContentParent::RecvAudioChannelChangeDef
     if (service) {
        service->SetDefaultVolumeControlChannelInternal(aChannel,
                                                        aHidden, mChildID);
     }
     return true;
 }
 
 bool
+ContentParent::RecvDataStoreGetStores(
+                                    const nsString& aName,
+                                    const IPC::Principal& aPrincipal,
+                                    InfallibleTArray<DataStoreSetting>* aValue)
+{
+  nsRefPtr<DataStoreService> service = DataStoreService::GetOrCreate();
+  if (NS_WARN_IF(!service)) {
+    return false;
+  }
+
+  nsresult rv = service->GetDataStoresFromIPC(aName, aPrincipal, aValue);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  mSendDataStoreInfos = true;
+  return true;
+}
+
+bool
 ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
 {
 #ifdef MOZ_WIDGET_GONK
     nsresult rv;
     nsCOMPtr<nsIVolumeService> vs = do_GetService(NS_VOLUMESERVICE_CONTRACTID, &rv);
     if (vs) {
         vs->BroadcastVolume(aVolumeName);
     }
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -157,20 +157,24 @@ public:
 #endif
 
     GeckoChildProcessHost* Process() {
         return mSubprocess;
     }
 
     int32_t Pid();
 
-    bool NeedsPermissionsUpdate() {
+    bool NeedsPermissionsUpdate() const {
         return mSendPermissionUpdates;
     }
 
+    bool NeedsDataStoreInfos() const {
+        return mSendDataStoreInfos;
+    }
+
     BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
     /**
      * Kill our subprocess and make sure it dies.  Should only be used
      * in emergency situations since it bypasses the normal shutdown
      * process.
      */
     void KillHard();
@@ -527,16 +531,21 @@ private:
 
     virtual bool RecvAudioChannelChangedNotification() MOZ_OVERRIDE;
 
     virtual bool RecvAudioChannelChangeDefVolChannel(const int32_t& aChannel,
                                                      const bool& aHidden) MOZ_OVERRIDE;
     virtual bool RecvGetSystemMemory(const uint64_t& getterId) MOZ_OVERRIDE;
     virtual bool RecvBroadcastVolume(const nsString& aVolumeName) MOZ_OVERRIDE;
 
+    virtual bool RecvDataStoreGetStores(
+                       const nsString& aName,
+                       const IPC::Principal& aPrincipal,
+                       InfallibleTArray<DataStoreSetting>* aValue) MOZ_OVERRIDE;
+
     virtual bool RecvSpeakerManagerGetSpeakerStatus(bool* aValue) MOZ_OVERRIDE;
 
     virtual bool RecvSpeakerManagerForceSpeaker(const bool& aEnable) MOZ_OVERRIDE;
 
     virtual bool RecvSystemMessageHandled() MOZ_OVERRIDE;
 
     virtual bool RecvNuwaReady() MOZ_OVERRIDE;
 
@@ -601,16 +610,17 @@ private:
     int32_t mNumDestroyingTabs;
     // True only while this is ready to be used to host remote tabs.
     // This must not be used for new purposes after mIsAlive goes to
     // false, but some previously scheduled IPC traffic may still pass
     // through.
     bool mIsAlive;
 
     bool mSendPermissionUpdates;
+    bool mSendDataStoreInfos;
     bool mIsForBrowser;
     bool mIsNuwaProcess;
 
     // These variables track whether we've called Close(), CloseWithError()
     // and KillHard() on our channel.
     bool mCalledClose;
     bool mCalledCloseWithError;
     bool mCalledKillHard;
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -257,16 +257,24 @@ union MaybePrefValue {
 };
 
 struct PrefSetting {
   nsCString name;
   MaybePrefValue defaultValue;
   MaybePrefValue userValue;
 };
 
+struct DataStoreSetting {
+  nsString name;
+  nsString originURL;
+  nsString manifestURL;
+  bool readOnly;
+  bool enabled;
+};
+
 intr protocol PContent
 {
     parent opens PCompositor;
     parent opens PSharedBufferManager;
     parent opens PImageBridge;
     child opens PBackground;
 
     manages PAsmJSCacheEntry;
@@ -333,16 +341,19 @@ child:
 
     /**
      * Notify the AudioChannelService in the child processes.
      */
     async AudioChannelNotify();
 
     async SpeakerManagerNotify();
 
+    async DataStoreNotify(uint32_t aAppId, nsString aName,
+                          nsString aManifestURL);
+
     /**
      * Dump this process's GC and CC logs to the provided files.
      *
      * For documentation on the other args, see dumpGCAndCCLogsToFile in
      * nsIMemoryInfoDumper.idl
      */
     PCycleCollectWithLogs(bool dumpAllTraces,
                           FileDescriptor gcLog,
@@ -545,16 +556,19 @@ parent:
     sync AudioChannelRegisterType(AudioChannel aChannel, bool aWithVideo);
     sync AudioChannelUnregisterType(AudioChannel aChannel,
                                     bool aElementHidden,
                                     bool aWithVideo);
 
     async AudioChannelChangedNotification();
     async AudioChannelChangeDefVolChannel(int32_t aChannel, bool aHidden);
 
+    sync DataStoreGetStores(nsString aName, Principal aPrincipal)
+        returns (DataStoreSetting[] dataStores);
+
     async FilePathUpdateNotify(nsString aType,
                                nsString aStorageName,
                                nsString aFilepath,
                                nsCString aReason);
     // get nsIVolumeService to broadcast volume information
     async BroadcastVolume(nsString volumeName);
 
     // Notify the parent that the child has finished handling a system message.
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2002,17 +2002,17 @@ TabChild::RecvRealTouchEvent(const Widge
     return true;
   }
 
   if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
     mActiveElementManager->SetTargetElement(localEvent.touches[0]->GetTarget());
   }
 
   nsCOMPtr<nsPIDOMWindow> outerWindow = do_GetInterface(WebNavigation());
-  nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow->GetCurrentInnerWindow();
+  nsCOMPtr<nsPIDOMWindow> innerWindow = outerWindow ? outerWindow->GetCurrentInnerWindow() : nullptr;
 
   if (!innerWindow || (!innerWindow->HasTouchEventListeners() &&
                        !innerWindow->MayHaveTouchCaret())) {
     SendContentReceivedTouch(aGuid, false);
     return true;
   }
 
   bool isTouchPrevented = nsIPresShell::gPreventMouseEvents ||
--- a/dom/power/PowerManager.cpp
+++ b/dom/power/PowerManager.cpp
@@ -149,16 +149,28 @@ PowerManager::ScreenEnabled()
 }
 
 void
 PowerManager::SetScreenEnabled(bool aEnabled)
 {
   hal::SetScreenEnabled(aEnabled);
 }
 
+bool
+PowerManager::KeyLightEnabled()
+{
+  return hal::GetKeyLightEnabled();
+}
+
+void
+PowerManager::SetKeyLightEnabled(bool aEnabled)
+{
+  hal::SetKeyLightEnabled(aEnabled);
+}
+
 double
 PowerManager::ScreenBrightness()
 {
   return hal::GetScreenBrightness();
 }
 
 void
 PowerManager::SetScreenBrightness(double aBrightness, ErrorResult& aRv)
--- a/dom/power/PowerManager.h
+++ b/dom/power/PowerManager.h
@@ -48,16 +48,18 @@ public:
   void FactoryReset();
   void PowerOff(ErrorResult& aRv);
   void AddWakeLockListener(nsIDOMMozWakeLockListener* aListener);
   void RemoveWakeLockListener(nsIDOMMozWakeLockListener* aListener);
   void GetWakeLockState(const nsAString& aTopic, nsAString& aState,
                         ErrorResult& aRv);
   bool ScreenEnabled();
   void SetScreenEnabled(bool aEnabled);
+  bool KeyLightEnabled();
+  void SetKeyLightEnabled(bool aEnabled);
   double ScreenBrightness();
   void SetScreenBrightness(double aBrightness, ErrorResult& aRv);
   bool CpuSleepAllowed();
   void SetCpuSleepAllowed(bool aAllowed);
 
 private:
   nsCOMPtr<nsIDOMWindow> mWindow;
   nsTArray<nsCOMPtr<nsIDOMMozWakeLockListener> > mListeners;
--- a/dom/power/test/mochitest.ini
+++ b/dom/power/test/mochitest.ini
@@ -7,8 +7,10 @@ skip-if = e10s
 run-if = appname != "b2g"
 [test_power_basics.html]
 [test_power_set_cpusleepallowed.html]
 skip-if = toolkit != "gonk"
 [test_power_set_screen_brightness.html]
 skip-if = toolkit != "gonk"
 [test_power_set_screen_enabled.html]
 skip-if = toolkit != "gonk"
+[test_power_set_key_light_enabled.html]
+skip-if = toolkit != "gonk"
new file mode 100644
--- /dev/null
+++ b/dom/power/test/test_power_set_key_light_enabled.html
@@ -0,0 +1,64 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test Enabling/Disabling Screen with Power Management API</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test">
+  <script type="application/javascript">
+
+  "use strict";
+
+  function testEnableKeyLight() {
+    try {
+      navigator.mozPower.keyLightEnabled = true;
+      ok(navigator.mozPower.keyLightEnabled === true, "Enabled key backlight.");
+    } catch (e) {
+      ok(false, "Unexpected exception trying to enable key backlight.");
+    }
+  }
+
+  function testDisableKeyLight() {
+    try {
+      navigator.mozPower.keyLightEnabled = false;
+      ok(navigator.mozPower.keyLightEnabled === false, "Disabled key backlight.");
+    } catch (e) {
+      ok(false, "Unexpected exception trying to disable key backlight.");
+    }
+  }
+
+  function startTests() {
+
+    // Make sure we don't suspend
+    navigator.mozPower.cpuSleepAllowed = false;
+
+    testDisableKeyLight();
+    testEnableKeyLight();
+
+    SimpleTest.finish();
+  }
+
+  SimpleTest.waitForExplicitFinish();
+  if (SpecialPowers.hasPermission("power", document)) {
+    // Currently only applicable on FxOS
+    if (navigator.userAgent.indexOf("Mobile") != -1 &&
+        navigator.appVersion.indexOf("Android") == -1) {
+      startTests();
+    } else {
+      ok(true, "mozPower on Firefox OS only.");
+      SimpleTest.finish();
+    }
+  } else {
+    // Add the permission and reload so it's propogated
+    SpecialPowers.addPermission("power", true, document);
+    window.location.reload();
+  }
+  </script>
+</pre>
+</body>
+</html>
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -206,19 +206,19 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "gTimeService",
                                    "@mozilla.org/time/timeservice;1",
                                    "nsITimeService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSystemWorkerManager",
                                    "@mozilla.org/telephony/system-worker-manager;1",
                                    "nsISystemWorkerManager");
 
-XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyProvider",
-                                   "@mozilla.org/telephony/telephonyprovider;1",
-                                   "nsIGonkTelephonyProvider");
+XPCOMUtils.defineLazyServiceGetter(this, "gTelephonyService",
+                                   "@mozilla.org/telephony/telephonyservice;1",
+                                   "nsIGonkTelephonyService");
 
 XPCOMUtils.defineLazyGetter(this, "WAP", function() {
   let wap = {};
   Cu.import("resource://gre/modules/WapPushManager.js", wap);
   return wap;
 });
 
 XPCOMUtils.defineLazyGetter(this, "PhoneNumberUtils", function() {
@@ -2058,32 +2058,32 @@ RadioInterface.prototype = {
     }
     return null;
   },
 
   handleUnsolicitedWorkerMessage: function(message) {
     let connHandler = gDataConnectionManager.getConnectionHandler(this.clientId);
     switch (message.rilMessageType) {
       case "callRing":
-        gTelephonyProvider.notifyCallRing();
+        gTelephonyService.notifyCallRing();
         break;
       case "callStateChange":
-        gTelephonyProvider.notifyCallStateChanged(this.clientId, message.call);
+        gTelephonyService.notifyCallStateChanged(this.clientId, message.call);
         break;
       case "callDisconnected":
-        gTelephonyProvider.notifyCallDisconnected(this.clientId, message.call);
+        gTelephonyService.notifyCallDisconnected(this.clientId, message.call);
         break;
       case "conferenceCallStateChanged":
-        gTelephonyProvider.notifyConferenceCallStateChanged(message.state);
+        gTelephonyService.notifyConferenceCallStateChanged(message.state);
         break;
       case "cdmaCallWaiting":
-        gTelephonyProvider.notifyCdmaCallWaiting(this.clientId, message.number);
+        gTelephonyService.notifyCdmaCallWaiting(this.clientId, message.number);
         break;
       case "suppSvcNotification":
-        gTelephonyProvider.notifySupplementaryService(this.clientId,
+        gTelephonyService.notifySupplementaryService(this.clientId,
                                                       message.callIndex,
                                                       message.notification);
         break;
       case "datacallerror":
         connHandler.handleDataCallError(message);
         break;
       case "datacallstatechange":
         let addresses = [];
--- a/dom/telephony/Telephony.cpp
+++ b/dom/telephony/Telephony.cpp
@@ -120,19 +120,19 @@ Telephony::~Telephony()
 }
 
 void
 Telephony::Shutdown()
 {
   if (mListener) {
     mListener->Disconnect();
 
-    if (mProvider) {
-      mProvider->UnregisterListener(mListener);
-      mProvider = nullptr;
+    if (mService) {
+      mService->UnregisterListener(mListener);
+      mService = nullptr;
     }
 
     mListener = nullptr;
   }
 }
 
 JSObject*
 Telephony::WrapObject(JSContext* aCx)
@@ -141,18 +141,18 @@ Telephony::WrapObject(JSContext* aCx)
 }
 
 // static
 already_AddRefed<Telephony>
 Telephony::Create(nsPIDOMWindow* aOwner, ErrorResult& aRv)
 {
   NS_ASSERTION(aOwner, "Null owner!");
 
-  nsCOMPtr<nsITelephonyProvider> ril =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
+  nsCOMPtr<nsITelephonyService> ril =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
   if (!ril) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aOwner);
   if (!sgo) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
@@ -162,17 +162,17 @@ Telephony::Create(nsPIDOMWindow* aOwner,
   nsCOMPtr<nsIScriptContext> scriptContext = sgo->GetContext();
   if (!scriptContext) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<Telephony> telephony = new Telephony(aOwner);
 
-  telephony->mProvider = ril;
+  telephony->mService = ril;
   telephony->mListener = new Listener(telephony);
   telephony->mCallsList = new CallsList(telephony);
   telephony->mGroup = TelephonyCallGroup::Create(telephony);
 
   nsresult rv = ril->EnumerateCalls(telephony->mListener);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
@@ -199,40 +199,40 @@ bool
 Telephony::IsValidServiceId(uint32_t aServiceId)
 {
   return aServiceId < GetNumServices();
 }
 
 // static
 bool
 Telephony::IsActiveState(uint16_t aCallState) {
-  return aCallState == nsITelephonyProvider::CALL_STATE_DIALING ||
-      aCallState == nsITelephonyProvider::CALL_STATE_ALERTING ||
-      aCallState == nsITelephonyProvider::CALL_STATE_CONNECTED;
+  return aCallState == nsITelephonyService::CALL_STATE_DIALING ||
+      aCallState == nsITelephonyService::CALL_STATE_ALERTING ||
+      aCallState == nsITelephonyService::CALL_STATE_CONNECTED;
 }
 
 uint32_t
 Telephony::ProvidedOrDefaultServiceId(const Optional<uint32_t>& aServiceId)
 {
   if (aServiceId.WasPassed()) {
     return aServiceId.Value();
   } else {
     uint32_t serviceId = 0;
-    mProvider->GetDefaultServiceId(&serviceId);
+    mService->GetDefaultServiceId(&serviceId);
     return serviceId;
   }
 }
 
 bool
 Telephony::HasDialingCall()
 {
   for (uint32_t i = 0; i < mCalls.Length(); i++) {
     const nsRefPtr<TelephonyCall>& call = mCalls[i];
-    if (call->CallState() > nsITelephonyProvider::CALL_STATE_UNKNOWN &&
-        call->CallState() < nsITelephonyProvider::CALL_STATE_CONNECTED) {
+    if (call->CallState() > nsITelephonyService::CALL_STATE_UNKNOWN &&
+        call->CallState() < nsITelephonyService::CALL_STATE_CONNECTED) {
       return true;
     }
   }
 
   return false;
 }
 
 bool
@@ -262,32 +262,32 @@ Telephony::DialInternal(uint32_t aServic
   // We only support one outgoing call at a time.
   if (HasDialingCall()) {
     promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
     return promise.forget();
   }
 
   nsCOMPtr<nsITelephonyCallback> callback =
     new Callback(this, promise, aServiceId, aNumber);
-  nsresult rv = mProvider->Dial(aServiceId, aNumber, aIsEmergency, callback);
+  nsresult rv = mService->Dial(aServiceId, aNumber, aIsEmergency, callback);
   if (NS_FAILED(rv)) {
     promise->MaybeReject(NS_LITERAL_STRING("InvalidStateError"));
     return promise.forget();
   }
 
   return promise.forget();
 }
 
 already_AddRefed<TelephonyCall>
 Telephony::CreateNewDialingCall(uint32_t aServiceId, const nsAString& aNumber,
                                 uint32_t aCallIndex)
 {
   nsRefPtr<TelephonyCall> call =
     TelephonyCall::Create(this, aServiceId, aNumber,
-                          nsITelephonyProvider::CALL_STATE_DIALING, aCallIndex);
+                          nsITelephonyService::CALL_STATE_DIALING, aCallIndex);
   NS_ASSERTION(call, "This should never fail!");
 
   NS_ASSERTION(mCalls.Contains(call), "Should have auto-added new call!");
 
   return call.forget();
 }
 
 nsresult
@@ -393,68 +393,68 @@ Telephony::StartTone(const nsAString& aD
     return;
   }
 
   if (aDTMFChar.Length() > 1 || !IsValidServiceId(serviceId)) {
     aRv.Throw(NS_ERROR_INVALID_ARG);
     return;
   }
 
-  aRv = mProvider->StartTone(serviceId, aDTMFChar);
+  aRv = mService->StartTone(serviceId, aDTMFChar);
 }
 
 void
 Telephony::StopTone(const Optional<uint32_t>& aServiceId, ErrorResult& aRv)
 {
   uint32_t serviceId = ProvidedOrDefaultServiceId(aServiceId);
 
   if (!IsValidServiceId(serviceId)) {
     aRv.Throw(NS_ERROR_INVALID_ARG);
     return;
   }
 
-  aRv = mProvider->StopTone(serviceId);
+  aRv = mService->StopTone(serviceId);
 }
 
 bool
 Telephony::GetMuted(ErrorResult& aRv) const
 {
   bool muted = false;
-  aRv = mProvider->GetMicrophoneMuted(&muted);
+  aRv = mService->GetMicrophoneMuted(&muted);
 
   return muted;
 }
 
 void
 Telephony::SetMuted(bool aMuted, ErrorResult& aRv)
 {
-  aRv = mProvider->SetMicrophoneMuted(aMuted);
+  aRv = mService->SetMicrophoneMuted(aMuted);
 }
 
 bool
 Telephony::GetSpeakerEnabled(ErrorResult& aRv) const
 {
   bool enabled = false;
-  aRv = mProvider->GetSpeakerEnabled(&enabled);
+  aRv = mService->GetSpeakerEnabled(&enabled);
 
   return enabled;
 }
 
 void
 Telephony::SetSpeakerEnabled(bool aEnabled, ErrorResult& aRv)
 {
-  aRv = mProvider->SetSpeakerEnabled(aEnabled);
+  aRv = mService->SetSpeakerEnabled(aEnabled);
 }
 
 void
 Telephony::GetActive(Nullable<OwningTelephonyCallOrTelephonyCallGroup>& aValue)
 {
   if (mActiveCall) {
     aValue.SetValue().SetAsTelephonyCall() = mActiveCall;
-  } else if (mGroup->CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  } else if (mGroup->CallState() == nsITelephonyService::CALL_STATE_CONNECTED) {
     aValue.SetValue().SetAsTelephonyCallGroup() = mGroup;
   } else {
     aValue.SetNull();
   }
 }
 
 already_AddRefed<CallsList>
 Telephony::Calls() const
@@ -525,32 +525,32 @@ Telephony::CallStateChanged(uint32_t aSe
       AddCall(modifiedCall);
     }
 
     return NS_OK;
   }
 
   // Do nothing since we didn't know anything about it before now and it's
   // ended already.
-  if (aCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+  if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     return NS_OK;
   }
 
   // Didn't find this call in mCalls or mGroup. Create a new call.
   nsRefPtr<TelephonyCall> call =
       TelephonyCall::Create(this, aServiceId, aNumber, aCallState, aCallIndex,
                             aIsEmergency, aIsConference, aIsSwitchable,
                             aIsMergeable);
   NS_ASSERTION(call, "This should never fail!");
 
   NS_ASSERTION(aIsConference ? mGroup->CallsArray().Contains(call) :
                                mCalls.Contains(call),
                "Should have auto-added new call!");
 
-  if (aCallState == nsITelephonyProvider::CALL_STATE_INCOMING) {
+  if (aCallState == nsITelephonyService::CALL_STATE_INCOMING) {
     nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("incoming"), call);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
@@ -566,17 +566,17 @@ Telephony::EnumerateCallStateComplete()
   MOZ_ASSERT(!mEnumerated);
 
   mEnumerated = true;
 
   if (NS_FAILED(NotifyCallsChanged(nullptr))) {
     NS_WARNING("Failed to notify calls changed!");
   }
 
-  if (NS_FAILED(mProvider->RegisterListener(mListener))) {
+  if (NS_FAILED(mService->RegisterListener(mListener))) {
     NS_WARNING("Failed to register listener!");
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Telephony::EnumerateCallState(uint32_t aServiceId, uint32_t aCallIndex,
                               uint16_t aCallState, const nsAString& aNumber,
@@ -615,20 +615,20 @@ Telephony::SupplementaryServiceNotificat
 {
   nsRefPtr<TelephonyCall> associatedCall;
   if (!mCalls.IsEmpty()) {
     associatedCall = GetCall(aServiceId, aCallIndex);
   }
 
   nsresult rv;
   switch (aNotification) {
-    case nsITelephonyProvider::NOTIFICATION_REMOTE_HELD:
+    case nsITelephonyService::NOTIFICATION_REMOTE_HELD:
       rv = DispatchCallEvent(NS_LITERAL_STRING("remoteheld"), associatedCall);
       break;
-    case nsITelephonyProvider::NOTIFICATION_REMOTE_RESUMED:
+    case nsITelephonyService::NOTIFICATION_REMOTE_RESUMED:
       rv = DispatchCallEvent(NS_LITERAL_STRING("remoteresumed"), associatedCall);
       break;
     default:
       NS_ERROR("Got a bad notification!");
       return NS_ERROR_UNEXPECTED;
   }
 
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/telephony/Telephony.h
+++ b/dom/telephony/Telephony.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_telephony_telephony_h__
 #define mozilla_dom_telephony_telephony_h__
 
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 // Need to include TelephonyCall.h because we have inline methods that
 // assume they see the definition of TelephonyCall.
 #include "TelephonyCall.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
@@ -24,29 +24,29 @@ namespace dom {
 
 class OwningTelephonyCallOrTelephonyCallGroup;
 
 class Telephony MOZ_FINAL : public DOMEventTargetHelper
 {
   /**
    * Class Telephony doesn't actually inherit nsITelephonyListener.
    * Instead, it owns an nsITelephonyListener derived instance mListener
-   * and passes it to nsITelephonyProvider. The onreceived events are first
+   * 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 Callback;
   friend class Callback;
 
   class EnumerationAck;
   friend class EnumerationAck;
 
-  nsCOMPtr<nsITelephonyProvider> mProvider;
+  nsCOMPtr<nsITelephonyService> mService;
   nsRefPtr<Listener> mListener;
 
   TelephonyCall* mActiveCall;
   nsTArray<nsRefPtr<TelephonyCall> > mCalls;
   nsRefPtr<CallsList> mCallsList;
 
   nsRefPtr<TelephonyCallGroup> mGroup;
 
@@ -125,20 +125,20 @@ public:
   RemoveCall(TelephonyCall* aCall)
   {
     NS_ASSERTION(mCalls.Contains(aCall), "Didn't know about this one!");
     mCalls.RemoveElement(aCall);
     UpdateActiveCall(aCall, false);
     NotifyCallsChanged(aCall);
   }
 
-  nsITelephonyProvider*
-  Provider() const
+  nsITelephonyService*
+  Service() const
   {
-    return mProvider;
+    return mService;
   }
 
   const nsTArray<nsRefPtr<TelephonyCall> >&
   CallsArray() const
   {
     return mCalls;
   }
 
--- a/dom/telephony/TelephonyCall.cpp
+++ b/dom/telephony/TelephonyCall.cpp
@@ -41,17 +41,17 @@ TelephonyCall::Create(Telephony* aTeleph
 
   call->ChangeStateInternal(aCallState, false);
 
   return call.forget();
 }
 
 TelephonyCall::TelephonyCall(nsPIDOMWindow* aOwner)
   : DOMEventTargetHelper(aOwner),
-    mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN),
+    mCallState(nsITelephonyService::CALL_STATE_UNKNOWN),
     mLive(false)
 {
 }
 
 TelephonyCall::~TelephonyCall()
 {
 }
 
@@ -63,54 +63,54 @@ TelephonyCall::WrapObject(JSContext* aCx
 
 void
 TelephonyCall::ChangeStateInternal(uint16_t aCallState, bool aFireEvents)
 {
   nsRefPtr<TelephonyCall> kungFuDeathGrip(this);
 
   nsString stateString;
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_DIALING:
+    case nsITelephonyService::CALL_STATE_DIALING:
       stateString.AssignLiteral("dialing");
       break;
-    case nsITelephonyProvider::CALL_STATE_ALERTING:
+    case nsITelephonyService::CALL_STATE_ALERTING:
       stateString.AssignLiteral("alerting");
       break;
-    case nsITelephonyProvider::CALL_STATE_CONNECTING:
+    case nsITelephonyService::CALL_STATE_CONNECTING:
       stateString.AssignLiteral("connecting");
       break;
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       stateString.AssignLiteral("connected");
       break;
-    case nsITelephonyProvider::CALL_STATE_HOLDING:
+    case nsITelephonyService::CALL_STATE_HOLDING:
       stateString.AssignLiteral("holding");
       break;
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       stateString.AssignLiteral("held");
       break;
-    case nsITelephonyProvider::CALL_STATE_RESUMING:
+    case nsITelephonyService::CALL_STATE_RESUMING:
       stateString.AssignLiteral("resuming");
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTING:
+    case nsITelephonyService::CALL_STATE_DISCONNECTING:
       stateString.AssignLiteral("disconnecting");
       break;
-    case nsITelephonyProvider::CALL_STATE_DISCONNECTED:
+    case nsITelephonyService::CALL_STATE_DISCONNECTED:
       stateString.AssignLiteral("disconnected");
       break;
-    case nsITelephonyProvider::CALL_STATE_INCOMING:
+    case nsITelephonyService::CALL_STATE_INCOMING:
       stateString.AssignLiteral("incoming");
       break;
     default:
       NS_NOTREACHED("Unknown state!");
   }
 
   mState = stateString;
   mCallState = aCallState;
 
-  if (aCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+  if (aCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     NS_ASSERTION(mLive, "Should be live!");
     mLive = false;
     if (mGroup) {
       mGroup->RemoveCall(this);
     } else {
       mTelephony->RemoveCall(this);
     }
   } else if (!mLive) {
@@ -154,17 +154,17 @@ void
 TelephonyCall::NotifyError(const nsAString& aError)
 {
   // Set the error string
   NS_ASSERTION(!mError, "Already have an error?");
 
   mError = new DOMError(GetOwner(), aError);
 
   // Do the state transitions
-  ChangeStateInternal(nsITelephonyProvider::CALL_STATE_DISCONNECTED, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTED, true);
 
   nsresult rv = DispatchCallEvent(NS_LITERAL_STRING("error"), this);
   if (NS_FAILED(rv)) {
     NS_WARNING("Failed to dispatch error event!");
   }
 }
 
 void
@@ -204,102 +204,102 @@ TelephonyCall::GetGroup() const
 {
   nsRefPtr<TelephonyCallGroup> group = mGroup;
   return group.forget();
 }
 
 void
 TelephonyCall::Answer(ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_INCOMING) {
+  if (mCallState != nsITelephonyService::CALL_STATE_INCOMING) {
     NS_WARNING("Answer on non-incoming call ignored!");
     return;
   }
 
-  nsresult rv = mTelephony->Provider()->AnswerCall(mServiceId, mCallIndex);
+  nsresult rv = mTelephony->Service()->AnswerCall(mServiceId, mCallIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  ChangeStateInternal(nsITelephonyProvider::CALL_STATE_CONNECTING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_CONNECTING, true);
 }
 
 void
 TelephonyCall::HangUp(ErrorResult& aRv)
 {
-  if (mCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTING ||
-      mCallState == nsITelephonyProvider::CALL_STATE_DISCONNECTED) {
+  if (mCallState == nsITelephonyService::CALL_STATE_DISCONNECTING ||
+      mCallState == nsITelephonyService::CALL_STATE_DISCONNECTED) {
     NS_WARNING("HangUp on previously disconnected call ignored!");
     return;
   }
 
-  nsresult rv = mCallState == nsITelephonyProvider::CALL_STATE_INCOMING ?
-                mTelephony->Provider()->RejectCall(mServiceId, mCallIndex) :
-                mTelephony->Provider()->HangUp(mServiceId, mCallIndex);
+  nsresult rv = mCallState == nsITelephonyService::CALL_STATE_INCOMING ?
+                mTelephony->Service()->RejectCall(mServiceId, mCallIndex) :
+                mTelephony->Service()->HangUp(mServiceId, mCallIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  ChangeStateInternal(nsITelephonyProvider::CALL_STATE_DISCONNECTING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_DISCONNECTING, true);
 }
 
 void
 TelephonyCall::Hold(ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
     NS_WARNING("Hold non-connected call ignored!");
     return;
   }
 
   if (mGroup) {
     NS_WARNING("Hold a call in conference ignored!");
     return;
   }
 
   if (!mSwitchable) {
     NS_WARNING("Hold a non-switchable call ignored!");
     return;
   }
 
-  nsresult rv = mTelephony->Provider()->HoldCall(mServiceId, mCallIndex);
+  nsresult rv = mTelephony->Service()->HoldCall(mServiceId, mCallIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
   if (!mSecondNumber.IsEmpty()) {
     // No state transition when we switch two numbers within one TelephonyCall
     // object. Otherwise, the state here will be inconsistent with the backend
     // RIL and will never be right.
     return;
   }
 
-  ChangeStateInternal(nsITelephonyProvider::CALL_STATE_HOLDING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_HOLDING, true);
 }
 
 void
 TelephonyCall::Resume(ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_HELD) {
+  if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
     NS_WARNING("Resume non-held call ignored!");
     return;
   }
 
   if (mGroup) {
     NS_WARNING("Resume a call in conference ignored!");
     return;
   }
 
   if (!mSwitchable) {
     NS_WARNING("Resume a non-switchable call ignored!");
     return;
   }
 
-  nsresult rv = mTelephony->Provider()->ResumeCall(mServiceId, mCallIndex);
+  nsresult rv = mTelephony->Service()->ResumeCall(mServiceId, mCallIndex);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  ChangeStateInternal(nsITelephonyProvider::CALL_STATE_RESUMING, true);
+  ChangeStateInternal(nsITelephonyService::CALL_STATE_RESUMING, true);
 }
--- a/dom/telephony/TelephonyCallGroup.cpp
+++ b/dom/telephony/TelephonyCallGroup.cpp
@@ -12,17 +12,17 @@
 #include "mozilla/dom/CallGroupErrorEvent.h"
 #include "Telephony.h"
 
 using namespace mozilla::dom;
 using mozilla::ErrorResult;
 
 TelephonyCallGroup::TelephonyCallGroup(nsPIDOMWindow* aOwner)
   : DOMEventTargetHelper(aOwner)
-  , mCallState(nsITelephonyProvider::CALL_STATE_UNKNOWN)
+  , mCallState(nsITelephonyService::CALL_STATE_UNKNOWN)
 {
 }
 
 TelephonyCallGroup::~TelephonyCallGroup()
 {
 }
 
 // static
@@ -83,28 +83,28 @@ void
 TelephonyCallGroup::ChangeState(uint16_t aCallState)
 {
   if (mCallState == aCallState) {
     return;
   }
 
   nsString stateString;
   switch (aCallState) {
-    case nsITelephonyProvider::CALL_STATE_UNKNOWN:
+    case nsITelephonyService::CALL_STATE_UNKNOWN:
       break;
-    case nsITelephonyProvider::CALL_STATE_CONNECTED:
+    case nsITelephonyService::CALL_STATE_CONNECTED:
       stateString.AssignLiteral("connected");
       break;
-    case nsITelephonyProvider::CALL_STATE_HOLDING:
+    case nsITelephonyService::CALL_STATE_HOLDING:
       stateString.AssignLiteral("holding");
       break;
-    case nsITelephonyProvider::CALL_STATE_HELD:
+    case nsITelephonyService::CALL_STATE_HELD:
       stateString.AssignLiteral("held");
       break;
-    case nsITelephonyProvider::CALL_STATE_RESUMING:
+    case nsITelephonyService::CALL_STATE_RESUMING:
       stateString.AssignLiteral("resuming");
       break;
     default:
       NS_NOTREACHED("Unknown state!");
   }
 
   mState = stateString;
   mCallState = aCallState;
@@ -152,36 +152,36 @@ TelephonyCallGroup::CanConference(const 
 {
   if (!aCall.Mergeable()) {
     return false;
   }
 
   if (!aSecondCall) {
     MOZ_ASSERT(!mCalls.IsEmpty());
 
-    return (mCallState == nsITelephonyProvider::CALL_STATE_CONNECTED &&
-            aCall.CallState() == nsITelephonyProvider::CALL_STATE_HELD) ||
-           (mCallState == nsITelephonyProvider::CALL_STATE_HELD &&
-            aCall.CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED);
+    return (mCallState == nsITelephonyService::CALL_STATE_CONNECTED &&
+            aCall.CallState() == nsITelephonyService::CALL_STATE_HELD) ||
+           (mCallState == nsITelephonyService::CALL_STATE_HELD &&
+            aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
   }
 
-  MOZ_ASSERT(mCallState == nsITelephonyProvider::CALL_STATE_UNKNOWN);
+  MOZ_ASSERT(mCallState == nsITelephonyService::CALL_STATE_UNKNOWN);
 
   if (aCall.ServiceId() != aSecondCall->ServiceId()) {
     return false;
   }
 
   if (!aSecondCall->Mergeable()) {
     return false;
   }
 
-  return (aCall.CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED &&
-          aSecondCall->CallState() == nsITelephonyProvider::CALL_STATE_HELD) ||
-         (aCall.CallState() == nsITelephonyProvider::CALL_STATE_HELD &&
-          aSecondCall->CallState() == nsITelephonyProvider::CALL_STATE_CONNECTED);
+  return (aCall.CallState() == nsITelephonyService::CALL_STATE_CONNECTED &&
+          aSecondCall->CallState() == nsITelephonyService::CALL_STATE_HELD) ||
+         (aCall.CallState() == nsITelephonyService::CALL_STATE_HELD &&
+          aSecondCall->CallState() == nsITelephonyService::CALL_STATE_CONNECTED);
 }
 
 already_AddRefed<TelephonyCall>
 TelephonyCallGroup::GetCall(uint32_t aServiceId, uint32_t aCallIndex)
 {
   nsRefPtr<TelephonyCall> call;
 
   for (uint32_t index = 0; index < mCalls.Length(); index++) {
@@ -230,82 +230,82 @@ void
 TelephonyCallGroup::Add(TelephonyCall& aCall,
                         ErrorResult& aRv)
 {
   if (!CanConference(aCall, nullptr)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
-  aRv = mTelephony->Provider()->ConferenceCall(aCall.ServiceId());
+  aRv = mTelephony->Service()->ConferenceCall(aCall.ServiceId());
 }
 
 void
 TelephonyCallGroup::Add(TelephonyCall& aCall,
                         TelephonyCall& aSecondCall,
                         ErrorResult& aRv)
 {
   if (!CanConference(aCall, &aSecondCall)) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
-  aRv = mTelephony->Provider()->ConferenceCall(aCall.ServiceId());
+  aRv = mTelephony->Service()->ConferenceCall(aCall.ServiceId());
 }
 
 void
 TelephonyCallGroup::Remove(TelephonyCall& aCall, ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
     NS_WARNING("Remove call from a non-connected call group. Ignore!");
     return;
   }
 
   uint32_t serviceId = aCall.ServiceId();
   uint32_t callIndex = aCall.CallIndex();
 
   nsRefPtr<TelephonyCall> call;
 
   call = GetCall(serviceId, callIndex);
   if (call) {
-    aRv = mTelephony->Provider()->SeparateCall(serviceId, callIndex);
+    aRv = mTelephony->Service()->SeparateCall(serviceId, callIndex);
   } else {
     NS_WARNING("Didn't have this call. Ignore!");
   }
 }
 
 void
 TelephonyCallGroup::Hold(ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_CONNECTED) {
+  if (mCallState != nsITelephonyService::CALL_STATE_CONNECTED) {
     NS_WARNING("Hold non-connected call ignored!");
     return;
   }
 
   MOZ_ASSERT(!mCalls.IsEmpty());
 
-  nsresult rv = mTelephony->Provider()->HoldConference(mCalls[0]->ServiceId());
+  nsresult rv = mTelephony->Service()->HoldConference(mCalls[0]->ServiceId());
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  ChangeState(nsITelephonyProvider::CALL_STATE_HOLDING);
+  ChangeState(nsITelephonyService::CALL_STATE_HOLDING);
 }
 
 void
 TelephonyCallGroup::Resume(ErrorResult& aRv)
 {
-  if (mCallState != nsITelephonyProvider::CALL_STATE_HELD) {
+  if (mCallState != nsITelephonyService::CALL_STATE_HELD) {
     NS_WARNING("Resume non-held call ignored!");
     return;
   }
 
   MOZ_ASSERT(!mCalls.IsEmpty());
 
-  nsresult rv = mTelephony->Provider()->ResumeConference(mCalls[0]->ServiceId());
+  nsresult rv = mTelephony->Service()->ResumeConference(mCalls[0]->ServiceId());
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
-  ChangeState(nsITelephonyProvider::CALL_STATE_RESUMING);
+  ChangeState(nsITelephonyService::CALL_STATE_RESUMING);
 }
--- a/dom/telephony/TelephonyFactory.cpp
+++ b/dom/telephony/TelephonyFactory.cpp
@@ -1,30 +1,30 @@
 /* -*- 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 "mozilla/dom/telephony/TelephonyFactory.h"
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
-#include "nsIGonkTelephonyProvider.h"
+#include "nsIGonkTelephonyService.h"
 #endif
 #include "nsServiceManagerUtils.h"
 #include "nsXULAppAPI.h"
-#include "ipc/TelephonyIPCProvider.h"
+#include "ipc/TelephonyIPCService.h"
 
 USING_TELEPHONY_NAMESPACE
 
-/* static */ already_AddRefed<nsITelephonyProvider>
-TelephonyFactory::CreateTelephonyProvider()
+/* static */ already_AddRefed<nsITelephonyService>
+TelephonyFactory::CreateTelephonyService()
 {
-  nsCOMPtr<nsITelephonyProvider> provider;
+  nsCOMPtr<nsITelephonyService> service;
 
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
-    provider = new TelephonyIPCProvider();
+    service = new TelephonyIPCService();
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
   } else {
-    provider = do_CreateInstance(GONK_TELEPHONY_PROVIDER_CONTRACTID);
+    service = do_CreateInstance(GONK_TELEPHONY_SERVICE_CONTRACTID);
 #endif
   }
 
-  return provider.forget();
+  return service.forget();
 }
--- a/dom/telephony/TelephonyFactory.h
+++ b/dom/telephony/TelephonyFactory.h
@@ -4,21 +4,21 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_telephony_TelephonyFactory_h
 #define mozilla_dom_telephony_TelephonyFactory_h
 
 #include "nsCOMPtr.h"
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 
-class nsITelephonyProvider;
+class nsITelephonyService;
 
 BEGIN_TELEPHONY_NAMESPACE
 
 class TelephonyFactory
 {
 public:
-  static already_AddRefed<nsITelephonyProvider> CreateTelephonyProvider();
+  static already_AddRefed<nsITelephonyService> CreateTelephonyService();
 };
 
 END_TELEPHONY_NAMESPACE
 
 #endif // mozilla_dom_telephony_TelephonyFactory_h
rename from dom/telephony/gonk/TelephonyProvider.js
rename to dom/telephony/gonk/TelephonyService.js
--- a/dom/telephony/gonk/TelephonyProvider.js
+++ b/dom/telephony/gonk/TelephonyService.js
@@ -9,43 +9,43 @@ const {classes: Cc, interfaces: Ci, util
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
 var RIL = {};
 Cu.import("resource://gre/modules/ril_consts.js", RIL);
 
-const GONK_TELEPHONYPROVIDER_CONTRACTID =
-  "@mozilla.org/telephony/gonktelephonyprovider;1";
-const GONK_TELEPHONYPROVIDER_CID =
+const GONK_TELEPHONYSERVICE_CONTRACTID =
+  "@mozilla.org/telephony/gonktelephonyservice;1";
+const GONK_TELEPHONYSERVICE_CID =
   Components.ID("{67d26434-d063-4d28-9f48-5b3189788155}");
 
 const NS_XPCOM_SHUTDOWN_OBSERVER_ID   = "xpcom-shutdown";
 
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
 
 const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
 const kPrefDefaultServiceId = "dom.telephony.defaultServiceId";
 
 const nsIAudioManager = Ci.nsIAudioManager;
-const nsITelephonyProvider = Ci.nsITelephonyProvider;
+const nsITelephonyService = Ci.nsITelephonyService;
 
 const CALL_WAKELOCK_TIMEOUT = 5000;
 
-// Index of the CDMA second call which isn't held in RIL but only in TelephoyProvider.
+// Index of the CDMA second call which isn't held in RIL but only in TelephoyService.
 const CDMA_SECOND_CALL_INDEX = 2;
 
 const DIAL_ERROR_INVALID_STATE_ERROR = "InvalidStateError";
 const DIAL_ERROR_OTHER_CONNECTION_IN_USE = "OtherConnectionInUse";
 
 let DEBUG;
 function debug(s) {
-  dump("TelephonyProvider: " + s + "\n");
+  dump("TelephonyService: " + s + "\n");
 }
 
 XPCOMUtils.defineLazyGetter(this, "gAudioManager", function getAudioManager() {
   try {
     return Cc["@mozilla.org/telephony/audiomanager;1"]
              .getService(nsIAudioManager);
   } catch (ex) {
     //TODO on the phone this should not fall back as silently.
@@ -110,42 +110,42 @@ SingleCall.prototype = {
 
 function ConferenceCall(state){
   this.state = state;
 }
 ConferenceCall.prototype = {
   state: null
 };
 
-function TelephonyProvider() {
+function TelephonyService() {
   this._numClients = gRadioInterfaceLayer.numRadioInterfaces;
   this._listeners = [];
   this._currentCalls = {};
   this._updateDebugFlag();
   this.defaultServiceId = this._getDefaultServiceId();
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
   Services.prefs.addObserver(kPrefDefaultServiceId, this, false);
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   for (let i = 0; i < this._numClients; ++i) {
     this._enumerateCallsForClient(i);
   }
 }
-TelephonyProvider.prototype = {
-  classID: GONK_TELEPHONYPROVIDER_CID,
-  classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYPROVIDER_CID,
-                                    contractID: GONK_TELEPHONYPROVIDER_CONTRACTID,
-                                    classDescription: "TelephonyProvider",
-                                    interfaces: [Ci.nsITelephonyProvider,
-                                                 Ci.nsIGonkTelephonyProvider],
+TelephonyService.prototype = {
+  classID: GONK_TELEPHONYSERVICE_CID,
+  classInfo: XPCOMUtils.generateCI({classID: GONK_TELEPHONYSERVICE_CID,
+                                    contractID: GONK_TELEPHONYSERVICE_CONTRACTID,
+                                    classDescription: "TelephonyService",
+                                    interfaces: [Ci.nsITelephonyService,
+                                                 Ci.nsIGonkTelephonyService],
                                     flags: Ci.nsIClassInfo.SINGLETON}),
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyProvider,
-                                         Ci.nsIGonkTelephonyProvider,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyService,
+                                         Ci.nsIGonkTelephonyService,
                                          Ci.nsIObserver]),
 
   // The following attributes/functions are used for acquiring/releasing the
   // CPU wake lock when the RIL handles the incoming call. Note that we need
   // a timer to bound the lock's life cycle to avoid exhausting the battery.
   _callRingWakeLock: null,
   _callRingWakeLockTimer: null,
 
@@ -206,24 +206,24 @@ TelephonyProvider.prototype = {
            this._activeCall.callIndex === aCall.callIndex;
   },
 
   /**
    * Track the active call and update the audio system as its state changes.
    */
   _activeCall: null,
   _updateActiveCall: function(aCall, aConferenceState) {
-    if (aConferenceState === nsITelephonyProvider.CALL_STATE_CONNECTED) {
+    if (aConferenceState === nsITelephonyService.CALL_STATE_CONNECTED) {
       this._activeCall = new ConferenceCall(aConferenceState);
       this._updateCallAudioState(aCall);
       return;
     }
 
-    if (aConferenceState === nsITelephonyProvider.CALL_STATE_UNKNOWN ||
-        aConferenceState === nsITelephonyProvider.CALL_STATE_HELD) {
+    if (aConferenceState === nsITelephonyService.CALL_STATE_UNKNOWN ||
+        aConferenceState === nsITelephonyService.CALL_STATE_HELD) {
       if (this._activeCall instanceof ConferenceCall) {
         this._activeCall = null;
         this._updateCallAudioState(aCall);
       }
       return;
     }
 
     if (!aCall) {
@@ -233,42 +233,42 @@ TelephonyProvider.prototype = {
     if (aCall.isConference) {
       if (this._matchActiveSingleCall(aCall)) {
         this._activeCall = null;
       }
       return;
     }
 
     switch (aCall.state) {
-      case nsITelephonyProvider.CALL_STATE_DIALING: // Fall through...
-      case nsITelephonyProvider.CALL_STATE_ALERTING:
-      case nsITelephonyProvider.CALL_STATE_CONNECTED:
+      case nsITelephonyService.CALL_STATE_DIALING: // Fall through...
+      case nsITelephonyService.CALL_STATE_ALERTING:
+      case nsITelephonyService.CALL_STATE_CONNECTED:
         this._activeCall = new SingleCall(aCall);
         this._updateCallAudioState(aCall);
         break;
 
-      case nsITelephonyProvider.CALL_STATE_INCOMING:
+      case nsITelephonyService.CALL_STATE_INCOMING:
         this._updateCallAudioState(aCall);
         break;
 
-      case nsITelephonyProvider.CALL_STATE_HELD: // Fall through...
-      case nsITelephonyProvider.CALL_STATE_DISCONNECTED:
+      case nsITelephonyService.CALL_STATE_HELD: // Fall through...
+      case nsITelephonyService.CALL_STATE_DISCONNECTED:
         if (this._matchActiveSingleCall(aCall)) {
           // Previously active call is not active now.
           this._activeCall = null;
           this._updateCallAudioState(aCall);
         }
         break;
     }
   },
 
   _updateCallAudioState: function(aCall) {
     let active = (this._activeCall !== null);
     let incoming = (aCall &&
-                    aCall.state === nsITelephonyProvider.CALL_STATE_INCOMING);
+                    aCall.state === nsITelephonyService.CALL_STATE_INCOMING);
 
     if (active) {
       gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL;
       if (this.speakerEnabled) {
         gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION,
                                      nsIAudioManager.FORCE_SPEAKER);
       }
       if (DEBUG) {
@@ -290,39 +290,39 @@ TelephonyProvider.prototype = {
               gAudioManager.phoneState);
       }
     }
   },
 
   _convertRILCallState: function(aState) {
     switch (aState) {
       case RIL.CALL_STATE_UNKNOWN:
-        return nsITelephonyProvider.CALL_STATE_UNKNOWN;
+        return nsITelephonyService.CALL_STATE_UNKNOWN;
       case RIL.CALL_STATE_ACTIVE:
-        return nsITelephonyProvider.CALL_STATE_CONNECTED;
+        return nsITelephonyService.CALL_STATE_CONNECTED;
       case RIL.CALL_STATE_HOLDING:
-        return nsITelephonyProvider.CALL_STATE_HELD;
+        return nsITelephonyService.CALL_STATE_HELD;
       case RIL.CALL_STATE_DIALING:
-        return nsITelephonyProvider.CALL_STATE_DIALING;
+        return nsITelephonyService.CALL_STATE_DIALING;
       case RIL.CALL_STATE_ALERTING:
-        return nsITelephonyProvider.CALL_STATE_ALERTING;
+        return nsITelephonyService.CALL_STATE_ALERTING;
       case RIL.CALL_STATE_INCOMING:
       case RIL.CALL_STATE_WAITING:
-        return nsITelephonyProvider.CALL_STATE_INCOMING;
+        return nsITelephonyService.CALL_STATE_INCOMING;
       default:
         throw new Error("Unknown rilCallState: " + aState);
     }
   },
 
   _convertRILSuppSvcNotification: function(aNotification) {
     switch (aNotification) {
       case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_HELD:
-        return nsITelephonyProvider.NOTIFICATION_REMOTE_HELD;
+        return nsITelephonyService.NOTIFICATION_REMOTE_HELD;
       case RIL.GECKO_SUPP_SVC_NOTIFICATION_REMOTE_RESUMED:
-        return nsITelephonyProvider.NOTIFICATION_REMOTE_RESUMED;
+        return nsITelephonyService.NOTIFICATION_REMOTE_RESUMED;
       default:
         if (DEBUG) {
           debug("Unknown rilSuppSvcNotification: " + aNotification);
         }
         return;
     }
   },
 
@@ -362,17 +362,17 @@ TelephonyProvider.prototype = {
         this._currentCalls[aClientId][call.callIndex] = call;
       }
 
       return false;
     }).bind(this));
   },
 
   /**
-   * nsITelephonyProvider interface.
+   * nsITelephonyService interface.
    */
 
   defaultServiceId: 0,
 
   registerListener: function(aListener) {
     if (this._listeners.indexOf(aListener) >= 0) {
       throw Cr.NS_ERROR_UNEXPECTED;
     }
@@ -708,26 +708,26 @@ TelephonyProvider.prototype = {
     gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
 
     if (!this._activeCall) {
       gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_NORMAL;
     }
   },
 
   /**
-   * nsIGonkTelephonyProvider interface.
+   * nsIGonkTelephonyService interface.
    */
 
   /**
    * Handle call disconnects by updating our current state and the audio system.
    */
   notifyCallDisconnected: function(aClientId, aCall) {
     if (DEBUG) debug("handleCallDisconnected: " + JSON.stringify(aCall));
 
-    aCall.state = nsITelephonyProvider.CALL_STATE_DISCONNECTED;
+    aCall.state = nsITelephonyService.CALL_STATE_DISCONNECTED;
     let duration = ("started" in aCall && typeof aCall.started == "number") ?
       new Date().getTime() - aCall.started : 0;
     let data = {
       number: aCall.number,
       serviceId: aClientId,
       emergency: aCall.isEmergency,
       duration: duration,
       direction: aCall.isOutgoing ? "outgoing" : "incoming"
@@ -805,17 +805,17 @@ TelephonyProvider.prototype = {
    */
   notifyCallStateChanged: function(aClientId, aCall, aSkipStateConversion) {
     if (DEBUG) debug("handleCallStateChange: " + JSON.stringify(aCall));
 
     if (!aSkipStateConversion) {
       aCall.state = this._convertRILCallState(aCall.state);
     }
 
-    if (aCall.state == nsITelephonyProvider.CALL_STATE_DIALING) {
+    if (aCall.state == nsITelephonyService.CALL_STATE_DIALING) {
       gSystemMessenger.broadcastMessage("telephony-new-call", {});
     }
 
     aCall.clientId = aClientId;
     this._updateActiveCall(aCall, null);
 
     let call = this._currentCalls[aClientId][aCall.callIndex];
     if (call) {
@@ -894,9 +894,9 @@ TelephonyProvider.prototype = {
         this._releaseCallRingWakeLock();
 
         Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
         break;
     }
   }
 };
 
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyProvider]);
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([TelephonyService]);
rename from dom/telephony/gonk/TelephonyProvider.manifest
rename to dom/telephony/gonk/TelephonyService.manifest
--- a/dom/telephony/gonk/TelephonyProvider.manifest
+++ b/dom/telephony/gonk/TelephonyService.manifest
@@ -1,2 +1,2 @@
-component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyProvider.js
-contract @mozilla.org/telephony/gonktelephonyprovider;1 {67d26434-d063-4d28-9f48-5b3189788155}
+component {67d26434-d063-4d28-9f48-5b3189788155} TelephonyService.js
+contract @mozilla.org/telephony/gonktelephonyservice;1 {67d26434-d063-4d28-9f48-5b3189788155}
--- a/dom/telephony/ipc/TelephonyChild.cpp
+++ b/dom/telephony/ipc/TelephonyChild.cpp
@@ -1,38 +1,38 @@
 /* -*- 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 "TelephonyIPCProvider.h"
+#include "TelephonyIPCService.h"
 
 USING_TELEPHONY_NAMESPACE
 
 /*******************************************************************************
  * TelephonyChild
  ******************************************************************************/
 
-TelephonyChild::TelephonyChild(TelephonyIPCProvider* aProvider)
-  : mProvider(aProvider)
+TelephonyChild::TelephonyChild(TelephonyIPCService* aService)
+  : mService(aService)
 {
-  MOZ_ASSERT(aProvider);
+  MOZ_ASSERT(aService);
 }
 
 TelephonyChild::~TelephonyChild()
 {
 }
 
 void
 TelephonyChild::ActorDestroy(ActorDestroyReason aWhy)
 {
-  if (mProvider) {
-    mProvider->NoteActorDestroyed();
-    mProvider = nullptr;
+  if (mService) {
+    mService->NoteActorDestroyed();
+    mService = nullptr;
   }
 }
 
 PTelephonyRequestChild*
 TelephonyChild::AllocPTelephonyRequestChild(const IPCTelephonyRequest& aRequest)
 {
   MOZ_CRASH("Caller is supposed to manually construct a request!");
 }
@@ -44,77 +44,77 @@ TelephonyChild::DeallocPTelephonyRequest
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifyCallError(const uint32_t& aClientId,
                                     const int32_t& aCallIndex,
                                     const nsString& aError)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->NotifyError(aClientId, aCallIndex, aError);
+  mService->NotifyError(aClientId, aCallIndex, aError);
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifyCallStateChanged(const uint32_t& aClientId,
                                            const IPCCallStateData& aData)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->CallStateChanged(aClientId,
+  mService->CallStateChanged(aClientId,
                               aData.callIndex(),
                               aData.callState(),
                               aData.number(),
                               aData.isOutGoing(),
                               aData.isEmergency(),
                               aData.isConference(),
                               aData.isSwitchable(),
                               aData.isMergeable());
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifyCdmaCallWaiting(const uint32_t& aClientId,
                                           const nsString& aNumber)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->NotifyCdmaCallWaiting(aClientId, aNumber);
+  mService->NotifyCdmaCallWaiting(aClientId, aNumber);
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifyConferenceCallStateChanged(const uint16_t& aCallState)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->ConferenceCallStateChanged(aCallState);
+  mService->ConferenceCallStateChanged(aCallState);
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifyConferenceError(const nsString& aName,
                                           const nsString& aMessage)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->NotifyConferenceError(aName, aMessage);
+  mService->NotifyConferenceError(aName, aMessage);
   return true;
 }
 
 bool
 TelephonyChild::RecvNotifySupplementaryService(const uint32_t& aClientId,
                                                const int32_t& aCallIndex,
                                                const uint16_t& aNotification)
 {
-  MOZ_ASSERT(mProvider);
+  MOZ_ASSERT(mService);
 
-  mProvider->SupplementaryServiceNotification(aClientId, aCallIndex,
+  mService->SupplementaryServiceNotification(aClientId, aCallIndex,
                                               aNotification);
   return true;
 }
 
 /*******************************************************************************
  * TelephonyRequestChild
  ******************************************************************************/
 
--- a/dom/telephony/ipc/TelephonyChild.h
+++ b/dom/telephony/ipc/TelephonyChild.h
@@ -4,26 +4,26 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_telephony_TelephonyChild_h
 #define mozilla_dom_telephony_TelephonyChild_h
 
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 #include "mozilla/dom/telephony/PTelephonyChild.h"
 #include "mozilla/dom/telephony/PTelephonyRequestChild.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 BEGIN_TELEPHONY_NAMESPACE
 
-class TelephonyIPCProvider;
+class TelephonyIPCService;
 
 class TelephonyChild : public PTelephonyChild
 {
 public:
-  TelephonyChild(TelephonyIPCProvider* aProvider);
+  TelephonyChild(TelephonyIPCService* aService);
 
 protected:
   virtual ~TelephonyChild();
 
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   virtual PTelephonyRequestChild*
@@ -52,17 +52,17 @@ protected:
                             const nsString& aMessage) MOZ_OVERRIDE;
 
   virtual bool
   RecvNotifySupplementaryService(const uint32_t& aClientId,
                                  const int32_t& aCallIndex,
                                  const uint16_t& aNotification) MOZ_OVERRIDE;
 
 private:
-  nsRefPtr<TelephonyIPCProvider> mProvider;
+  nsRefPtr<TelephonyIPCService> mService;
 };
 
 class TelephonyRequestChild : public PTelephonyRequestChild
 {
 public:
   TelephonyRequestChild(nsITelephonyListener* aListener,
                         nsITelephonyCallback* aCallback);
 
rename from dom/telephony/ipc/TelephonyIPCProvider.cpp
rename to dom/telephony/ipc/TelephonyIPCService.cpp
--- a/dom/telephony/ipc/TelephonyIPCProvider.cpp
+++ b/dom/telephony/ipc/TelephonyIPCService.cpp
@@ -1,14 +1,14 @@
 /* -*- 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 "TelephonyIPCProvider.h"
+#include "TelephonyIPCService.h"
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/telephony/TelephonyChild.h"
 #include "mozilla/Preferences.h"
 
 USING_TELEPHONY_NAMESPACE
 using namespace mozilla::dom;
 
@@ -31,332 +31,332 @@ getDefaultServiceId()
     id = 0;
   }
 
   return id;
 }
 
 } // Anonymous namespace
 
-NS_IMPL_ISUPPORTS(TelephonyIPCProvider,
-                  nsITelephonyProvider,
+NS_IMPL_ISUPPORTS(TelephonyIPCService,
+                  nsITelephonyService,
                   nsITelephonyListener,
                   nsIObserver)
 
-TelephonyIPCProvider::TelephonyIPCProvider()
+TelephonyIPCService::TelephonyIPCService()
 {
   // Deallocated in ContentChild::DeallocPTelephonyChild().
   mPTelephonyChild = new TelephonyChild(this);
   ContentChild::GetSingleton()->SendPTelephonyConstructor(mPTelephonyChild);
 
   Preferences::AddStrongObservers(this, kObservedPrefs);
   mDefaultServiceId = getDefaultServiceId();
 }
 
-TelephonyIPCProvider::~TelephonyIPCProvider()
+TelephonyIPCService::~TelephonyIPCService()
 {
   if (mPTelephonyChild) {
     mPTelephonyChild->Send__delete__(mPTelephonyChild);
     mPTelephonyChild = nullptr;
   }
 }
 
 void
-TelephonyIPCProvider::NoteActorDestroyed()
+TelephonyIPCService::NoteActorDestroyed()
 {
   MOZ_ASSERT(mPTelephonyChild);
 
   mPTelephonyChild = nullptr;
 }
 
 /*
  * Implementation of nsIObserver.
  */
 
 NS_IMETHODIMP
-TelephonyIPCProvider::Observe(nsISupports* aSubject,
+TelephonyIPCService::Observe(nsISupports* aSubject,
                               const char* aTopic,
                               const char16_t* aData)
 {
   if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
     nsDependentString data(aData);
     if (data.EqualsLiteral(kPrefDefaultServiceId)) {
       mDefaultServiceId = getDefaultServiceId();
     }
     return NS_OK;
   }
 
-  MOZ_ASSERT(false, "TelephonyIPCProvider got unexpected topic!");
+  MOZ_ASSERT(false, "TelephonyIPCService got unexpected topic!");
   return NS_ERROR_UNEXPECTED;
 }
 
 /*
- * Implementation of nsITelephonyProvider.
+ * Implementation of nsITelephonyService.
  */
 
 NS_IMETHODIMP
-TelephonyIPCProvider::GetDefaultServiceId(uint32_t* aServiceId)
+TelephonyIPCService::GetDefaultServiceId(uint32_t* aServiceId)
 {
   *aServiceId = mDefaultServiceId;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::RegisterListener(nsITelephonyListener *aListener)
+TelephonyIPCService::RegisterListener(nsITelephonyListener *aListener)
 {
   MOZ_ASSERT(!mListeners.Contains(aListener));
 
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   // nsTArray doesn't fail.
   mListeners.AppendElement(aListener);
 
   if (mListeners.Length() == 1) {
     mPTelephonyChild->SendRegisterListener();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::UnregisterListener(nsITelephonyListener *aListener)
+TelephonyIPCService::UnregisterListener(nsITelephonyListener *aListener)
 {
   MOZ_ASSERT(mListeners.Contains(aListener));
 
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   // We always have the element here, so it can't fail.
   mListeners.RemoveElement(aListener);
 
   if (!mListeners.Length()) {
     mPTelephonyChild->SendUnregisterListener();
   }
   return NS_OK;
 }
 
 nsresult
-TelephonyIPCProvider::SendRequest(nsITelephonyListener *aListener,
+TelephonyIPCService::SendRequest(nsITelephonyListener *aListener,
                                   nsITelephonyCallback *aCallback,
                                   const IPCTelephonyRequest& aRequest)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   // Life time of newly allocated TelephonyRequestChild instance is managed by
   // IPDL itself.
   TelephonyRequestChild* actor = new TelephonyRequestChild(aListener, aCallback);
   mPTelephonyChild->SendPTelephonyRequestConstructor(actor, aRequest);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::EnumerateCalls(nsITelephonyListener *aListener)
+TelephonyIPCService::EnumerateCalls(nsITelephonyListener *aListener)
 {
   return SendRequest(aListener, nullptr, EnumerateCallsRequest());
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::Dial(uint32_t aClientId, const nsAString& aNumber,
+TelephonyIPCService::Dial(uint32_t aClientId, const nsAString& aNumber,
                            bool aIsEmergency, nsITelephonyCallback *aCallback)
 {
   return SendRequest(nullptr, aCallback,
                      DialRequest(aClientId, nsString(aNumber), aIsEmergency));
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::HangUp(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::HangUp(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendHangUpCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::AnswerCall(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::AnswerCall(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendAnswerCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::RejectCall(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::RejectCall(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendRejectCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::HoldCall(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::HoldCall(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendHoldCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::ResumeCall(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::ResumeCall(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendResumeCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::ConferenceCall(uint32_t aClientId)
+TelephonyIPCService::ConferenceCall(uint32_t aClientId)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendConferenceCall(aClientId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::SeparateCall(uint32_t aClientId, uint32_t aCallIndex)
+TelephonyIPCService::SeparateCall(uint32_t aClientId, uint32_t aCallIndex)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendSeparateCall(aClientId, aCallIndex);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::HoldConference(uint32_t aClientId)
+TelephonyIPCService::HoldConference(uint32_t aClientId)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendHoldConference(aClientId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::ResumeConference(uint32_t aClientId)
+TelephonyIPCService::ResumeConference(uint32_t aClientId)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendResumeConference(aClientId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::StartTone(uint32_t aClientId, const nsAString& aDtmfChar)
+TelephonyIPCService::StartTone(uint32_t aClientId, const nsAString& aDtmfChar)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendStartTone(aClientId, nsString(aDtmfChar));
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::StopTone(uint32_t aClientId)
+TelephonyIPCService::StopTone(uint32_t aClientId)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendStopTone(aClientId);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::GetMicrophoneMuted(bool* aMuted)
+TelephonyIPCService::GetMicrophoneMuted(bool* aMuted)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendGetMicrophoneMuted(aMuted);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::SetMicrophoneMuted(bool aMuted)
+TelephonyIPCService::SetMicrophoneMuted(bool aMuted)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendSetMicrophoneMuted(aMuted);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::GetSpeakerEnabled(bool* aEnabled)
+TelephonyIPCService::GetSpeakerEnabled(bool* aEnabled)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendGetSpeakerEnabled(aEnabled);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::SetSpeakerEnabled(bool aEnabled)
+TelephonyIPCService::SetSpeakerEnabled(bool aEnabled)
 {
   if (!mPTelephonyChild) {
-    NS_WARNING("TelephonyProvider used after shutdown has begun!");
+    NS_WARNING("TelephonyService used after shutdown has begun!");
     return NS_ERROR_FAILURE;
   }
 
   mPTelephonyChild->SendSetSpeakerEnabled(aEnabled);
   return NS_OK;
 }
 
 // nsITelephonyListener
 
 NS_IMETHODIMP
-TelephonyIPCProvider::CallStateChanged(uint32_t aClientId,
+TelephonyIPCService::CallStateChanged(uint32_t aClientId,
                                        uint32_t aCallIndex,
                                        uint16_t aCallState,
                                        const nsAString& aNumber,
                                        bool aIsOutgoing,
                                        bool aIsEmergency,
                                        bool aIsConference,
                                        bool aIsSwitchable,
                                        bool aIsMergeable)
@@ -365,76 +365,76 @@ TelephonyIPCProvider::CallStateChanged(u
     mListeners[i]->CallStateChanged(aClientId, aCallIndex, aCallState, aNumber,
                                     aIsOutgoing, aIsEmergency, aIsConference,
                                     aIsSwitchable, aIsMergeable);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::ConferenceCallStateChanged(uint16_t aCallState)
+TelephonyIPCService::ConferenceCallStateChanged(uint16_t aCallState)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->ConferenceCallStateChanged(aCallState);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::EnumerateCallStateComplete()
+TelephonyIPCService::EnumerateCallStateComplete()
 {
   MOZ_CRASH("Not a EnumerateCalls request!");
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::EnumerateCallState(uint32_t aClientId,
+TelephonyIPCService::EnumerateCallState(uint32_t aClientId,
                                          uint32_t aCallIndex,
                                          uint16_t aCallState,
                                          const nsAString& aNumber,
                                          bool aIsOutgoing,
                                          bool aIsEmergency,
                                          bool aIsConference,
                                          bool aIsSwitchable,
                                          bool aIsMergeable)
 {
   MOZ_CRASH("Not a EnumerateCalls request!");
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::NotifyCdmaCallWaiting(uint32_t aClientId,
+TelephonyIPCService::NotifyCdmaCallWaiting(uint32_t aClientId,
                                             const nsAString& aNumber)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->NotifyCdmaCallWaiting(aClientId, aNumber);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::NotifyConferenceError(const nsAString& aName,
+TelephonyIPCService::NotifyConferenceError(const nsAString& aName,
                                             const nsAString& aMessage)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->NotifyConferenceError(aName, aMessage);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::NotifyError(uint32_t aClientId, int32_t aCallIndex,
+TelephonyIPCService::NotifyError(uint32_t aClientId, int32_t aCallIndex,
                                   const nsAString& aError)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->NotifyError(aClientId, aCallIndex, aError);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-TelephonyIPCProvider::SupplementaryServiceNotification(uint32_t aClientId,
+TelephonyIPCService::SupplementaryServiceNotification(uint32_t aClientId,
                                                        int32_t aCallIndex,
                                                        uint16_t aNotification)
 {
   for (uint32_t i = 0; i < mListeners.Length(); i++) {
     mListeners[i]->SupplementaryServiceNotification(aClientId, aCallIndex,
                                                     aNotification);
   }
   return NS_OK;
rename from dom/telephony/ipc/TelephonyIPCProvider.h
rename to dom/telephony/ipc/TelephonyIPCService.h
--- a/dom/telephony/ipc/TelephonyIPCProvider.h
+++ b/dom/telephony/ipc/TelephonyIPCService.h
@@ -1,47 +1,47 @@
 /* -*- 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/. */
 
-#ifndef mozilla_dom_telephony_TelephonyIPCProvider_h
-#define mozilla_dom_telephony_TelephonyIPCProvider_h
+#ifndef mozilla_dom_telephony_TelephonyIPCService_h
+#define mozilla_dom_telephony_TelephonyIPCService_h
 
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 #include "mozilla/Attributes.h"
 #include "nsIObserver.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 BEGIN_TELEPHONY_NAMESPACE
 
 struct IPCTelephonyRequest;
 class PTelephonyChild;
 
-class TelephonyIPCProvider MOZ_FINAL : public nsITelephonyProvider
+class TelephonyIPCService MOZ_FINAL : public nsITelephonyService
                                      , public nsITelephonyListener
                                      , public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
-  NS_DECL_NSITELEPHONYPROVIDER
+  NS_DECL_NSITELEPHONYSERVICE
   NS_DECL_NSITELEPHONYLISTENER
   NS_DECL_NSIOBSERVER
 
-  TelephonyIPCProvider();
+  TelephonyIPCService();
 
   void NoteActorDestroyed();
 
 private:
-  ~TelephonyIPCProvider();
+  ~TelephonyIPCService();
 
   nsTArray<nsCOMPtr<nsITelephonyListener> > mListeners;
   PTelephonyChild* mPTelephonyChild;
   uint32_t mDefaultServiceId;
 
   nsresult SendRequest(nsITelephonyListener *aListener,
                        nsITelephonyCallback *aCallback,
                        const IPCTelephonyRequest& aRequest);
 };
 
 END_TELEPHONY_NAMESPACE
 
-#endif // mozilla_dom_telephony_TelephonyIPCProvider_h
+#endif // mozilla_dom_telephony_TelephonyIPCService_h
--- a/dom/telephony/ipc/TelephonyParent.cpp
+++ b/dom/telephony/ipc/TelephonyParent.cpp
@@ -75,209 +75,209 @@ TelephonyParent::Recv__delete__()
   return true; // Unregister listener in TelephonyParent::ActorDestroy().
 }
 
 bool
 TelephonyParent::RecvRegisterListener()
 {
   NS_ENSURE_TRUE(!mRegistered, true);
 
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  mRegistered = NS_SUCCEEDED(provider->RegisterListener(this));
+  mRegistered = NS_SUCCEEDED(service->RegisterListener(this));
   return true;
 }
 
 bool
 TelephonyParent::RecvUnregisterListener()
 {
   NS_ENSURE_TRUE(mRegistered, true);
 
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  mRegistered = !NS_SUCCEEDED(provider->UnregisterListener(this));
+  mRegistered = !NS_SUCCEEDED(service->UnregisterListener(this));
   return true;
 }
 
 bool
 TelephonyParent::RecvHangUpCall(const uint32_t& aClientId,
                                 const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->HangUp(aClientId, aCallIndex);
+  service->HangUp(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvAnswerCall(const uint32_t& aClientId,
                                 const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->AnswerCall(aClientId, aCallIndex);
+  service->AnswerCall(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvRejectCall(const uint32_t& aClientId,
                                 const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->RejectCall(aClientId, aCallIndex);
+  service->RejectCall(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvHoldCall(const uint32_t& aClientId,
                               const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->HoldCall(aClientId, aCallIndex);
+  service->HoldCall(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvResumeCall(const uint32_t& aClientId,
                                 const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->ResumeCall(aClientId, aCallIndex);
+  service->ResumeCall(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvConferenceCall(const uint32_t& aClientId)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->ConferenceCall(aClientId);
+  service->ConferenceCall(aClientId);
   return true;
 }
 
 bool
 TelephonyParent::RecvSeparateCall(const uint32_t& aClientId,
                                   const uint32_t& aCallIndex)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->SeparateCall(aClientId, aCallIndex);
+  service->SeparateCall(aClientId, aCallIndex);
   return true;
 }
 
 bool
 TelephonyParent::RecvHoldConference(const uint32_t& aClientId)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->HoldConference(aClientId);
+  service->HoldConference(aClientId);
   return true;
 }
 
 bool
 TelephonyParent::RecvResumeConference(const uint32_t& aClientId)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->ResumeConference(aClientId);
+  service->ResumeConference(aClientId);
   return true;
 }
 
 bool
 TelephonyParent::RecvStartTone(const uint32_t& aClientId, const nsString& aTone)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->StartTone(aClientId, aTone);
+  service->StartTone(aClientId, aTone);
   return true;
 }
 
 bool
 TelephonyParent::RecvStopTone(const uint32_t& aClientId)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->StopTone(aClientId);
+  service->StopTone(aClientId);
   return true;
 }
 
 bool
 TelephonyParent::RecvGetMicrophoneMuted(bool* aMuted)
 {
   *aMuted = false;
 
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->GetMicrophoneMuted(aMuted);
+  service->GetMicrophoneMuted(aMuted);
   return true;
 }
 
 bool
 TelephonyParent::RecvSetMicrophoneMuted(const bool& aMuted)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->SetMicrophoneMuted(aMuted);
+  service->SetMicrophoneMuted(aMuted);
   return true;
 }
 
 bool
 TelephonyParent::RecvGetSpeakerEnabled(bool* aEnabled)
 {
   *aEnabled = false;
 
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->GetSpeakerEnabled(aEnabled);
+  service->GetSpeakerEnabled(aEnabled);
   return true;
 }
 
 bool
 TelephonyParent::RecvSetSpeakerEnabled(const bool& aEnabled)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, true);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, true);
 
-  provider->SetSpeakerEnabled(aEnabled);
+  service->SetSpeakerEnabled(aEnabled);
   return true;
 }
 
 // nsITelephonyListener
 
 NS_IMETHODIMP
 TelephonyParent::CallStateChanged(uint32_t aClientId,
                                   uint32_t aCallIndex,
@@ -390,36 +390,36 @@ TelephonyRequestParent::ActorDestroy(Act
   mActorDestroyed = true;
 }
 
 bool
 TelephonyRequestParent::DoRequest(const EnumerateCallsRequest& aRequest)
 {
   nsresult rv = NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  if (provider) {
-    rv = provider->EnumerateCalls(this);
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  if (service) {
+    rv = service->EnumerateCalls(this);
   }
 
   if (NS_FAILED(rv)) {
     return NS_SUCCEEDED(EnumerateCallStateComplete());
   }
 
   return true;
 }
 
 bool
 TelephonyRequestParent::DoRequest(const DialRequest& aRequest)
 {
-  nsCOMPtr<nsITelephonyProvider> provider =
-    do_GetService(TELEPHONY_PROVIDER_CONTRACTID);
-  if (provider) {
-    provider->Dial(aRequest.clientId(), aRequest.number(),
+  nsCOMPtr<nsITelephonyService> service =
+    do_GetService(TELEPHONY_SERVICE_CONTRACTID);
+  if (service) {
+    service->Dial(aRequest.clientId(), aRequest.number(),
                    aRequest.isEmergency(), this);
   } else {
     return NS_SUCCEEDED(NotifyDialError(NS_LITERAL_STRING("InvalidStateError")));
   }
 
   return true;
 }
 
--- a/dom/telephony/ipc/TelephonyParent.h
+++ b/dom/telephony/ipc/TelephonyParent.h
@@ -4,17 +4,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_telephony_TelephonyParent_h
 #define mozilla_dom_telephony_TelephonyParent_h
 
 #include "mozilla/dom/telephony/TelephonyCommon.h"
 #include "mozilla/dom/telephony/PTelephonyParent.h"
 #include "mozilla/dom/telephony/PTelephonyRequestParent.h"
-#include "nsITelephonyProvider.h"
+#include "nsITelephonyService.h"
 
 BEGIN_TELEPHONY_NAMESPACE
 
 class TelephonyParent : public PTelephonyParent
                       , public nsITelephonyListener
 {
 public:
   NS_DECL_ISUPPORTS
--- a/dom/telephony/moz.build
+++ b/dom/telephony/moz.build
@@ -1,16 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPIDL_SOURCES += [
-    'nsITelephonyProvider.idl',
+    'nsITelephonyService.idl',
 ]
 
 XPIDL_MODULE = 'dom_telephony'
 
 EXPORTS.mozilla.dom += [
     'CallEvent.h',
     'CallsList.h',
     'Telephony.h',
@@ -24,35 +24,35 @@ EXPORTS.mozilla.dom.telephony += [
     'TelephonyCommon.h',
     'TelephonyFactory.h',
 ]
 
 UNIFIED_SOURCES += [
     'CallEvent.cpp',
     'CallsList.cpp',
     'ipc/TelephonyChild.cpp',
-    'ipc/TelephonyIPCProvider.cpp',
+    'ipc/TelephonyIPCService.cpp',
     'ipc/TelephonyParent.cpp',
     'Telephony.cpp',
     'TelephonyCall.cpp',
     'TelephonyCallGroup.cpp',
     'TelephonyFactory.cpp',
 ]
 
 IPDL_SOURCES += [
     'ipc/PTelephony.ipdl',
     'ipc/PTelephonyRequest.ipdl',
     'ipc/TelephonyTypes.ipdlh'
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
-        'nsIGonkTelephonyProvider.idl',
+        'nsIGonkTelephonyService.idl',
     ]
     EXTRA_COMPONENTS += [
-        'gonk/TelephonyProvider.js',
-        'gonk/TelephonyProvider.manifest',
+        'gonk/TelephonyService.js',
+        'gonk/TelephonyService.manifest',
     ]
 
 FAIL_ON_WARNINGS = True
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
rename from dom/telephony/nsIGonkTelephonyProvider.idl
rename to dom/telephony/nsIGonkTelephonyService.idl
--- a/dom/telephony/nsIGonkTelephonyProvider.idl
+++ b/dom/telephony/nsIGonkTelephonyService.idl
@@ -1,22 +1,22 @@
 /* -*- 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/. */
 
-#include "nsITelephonyProvider.idl"
+#include "nsITelephonyService.idl"
 
 %{C++
-#define GONK_TELEPHONY_PROVIDER_CONTRACTID \
-        "@mozilla.org/telephony/gonktelephonyprovider;1"
+#define GONK_TELEPHONY_SERVICE_CONTRACTID \
+        "@mozilla.org/telephony/gonktelephonyservice;1"
 %}
 
-[scriptable, uuid(9d884482-90fc-4050-a4b1-1a370afe7a35)]
-interface nsIGonkTelephonyProvider : nsITelephonyProvider
+[scriptable, uuid(2ff3dcbb-ae63-443e-9c5d-76811f2f9b42)]
+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);
 
rename from dom/telephony/nsITelephonyProvider.idl
rename to dom/telephony/nsITelephonyService.idl
--- a/dom/telephony/nsITelephonyProvider.idl
+++ b/dom/telephony/nsITelephonyService.idl
@@ -10,29 +10,29 @@ interface nsITelephonyListener : nsISupp
   /**
    * Notified when a telephony call changes state.
    *
    * @param clientId
             Indicate the RIL client, 0 ~ (number of client - 1).
    * @param callIndex
    *        Call identifier assigned by the RIL.
    * @param callState
-   *        One of the nsITelephonyProvider::CALL_STATE_* values.
+   *        One of the nsITelephonyService::CALL_STATE_* values.
    * @param number
    *        Number of the other party.
    * @param isOutgoing
    *        Indicates whether this call is outgoing or incoming.
    * @param isEmergency
    *        Indicates whether this call is an emergency call.
    * @param isConference
    *        Indicates whether this call is a conference call.
    * @param isSwitchable
    *        Indicates whether this call can be switched between states of
-   *        nsITelephonyProvider::CALL_STATE_CONNECTED and
-   *        nsITelephonyProvider::CALL_STATE_HELD.
+   *        nsITelephonyService::CALL_STATE_CONNECTED and
+   *        nsITelephonyService::CALL_STATE_HELD.
    * @param isMergeable
    *        Indicates whether this call be be added into a conference.
    */
   void callStateChanged(in unsigned long clientId,
                         in unsigned long callIndex,
                         in unsigned short callState,
                         in AString number,
                         in boolean isOutgoing,
@@ -41,49 +41,49 @@ interface nsITelephonyListener : nsISupp
                         in boolean isSwitchable,
                         in boolean isMergeable);
 
   /**
    * Called when participants of a conference call have been updated, and the
    * conference call state changes.
    *
    * @param callState
-   *        Possible values are: nsITelephonyProvider::CALL_STATE_UNKNOWN,
-   *        nsITelephonyProvider::CALL_STATE_HELD,
-   *        nsITelephonyProvider::CALL_STATE_CONNECTED.
+   *        Possible values are: nsITelephonyService::CALL_STATE_UNKNOWN,
+   *        nsITelephonyService::CALL_STATE_HELD,
+   *        nsITelephonyService::CALL_STATE_CONNECTED.
    */
   void conferenceCallStateChanged(in unsigned short callState);
 
   /**
-   * Called when enumeration asked by nsITelephonyProvider::enumerateCalls
+   * Called when enumeration asked by nsITelephonyService::enumerateCalls
    * is completed.
    */
   void enumerateCallStateComplete();
 
   /**
-   * Called when nsITelephonyProvider is asked to enumerate the current
-   * telephony call state (nsITelephonyProvider::enumerateCalls). This is
+   * Called when nsITelephonyService is asked to enumerate the current
+   * telephony call state (nsITelephonyService::enumerateCalls). This is
    * called once per call that is currently managed by the RIL.
    *
    * @param clientId
             Indicate the RIL client, 0 ~ (number of client - 1).
    * @param callIndex
    *        Call identifier assigned by the RIL.
    * @param callState
-   *        One of the nsITelephonyProvider::CALL_STATE_* values.
+   *        One of the nsITelephonyService::CALL_STATE_* values.
    * @param number
    *        Number of the other party.
    * @param isOutgoing
    *        Indicates whether this call is outgoing or incoming.
    * @param isConference
    *        Indicates whether this call is a conference call.
    * @param isSwitchable
    *        Indicates whether this call can be switched between states of
-   *        nsITelephonyProvider::CALL_STATE_CONNECTED and
-   *        nsITelephonyProvider::CALL_STATE_HELD.
+   *        nsITelephonyService::CALL_STATE_CONNECTED and
+   *        nsITelephonyService::CALL_STATE_HELD.
    * @param isMergeable
    *        Indicates whether this call be be added into a conference.
    */
   void enumerateCallState(in unsigned long clientId,
                           in unsigned long callIndex,
                           in unsigned short callState,
                           in AString number,
                           in boolean isOutgoing,
@@ -95,17 +95,17 @@ interface nsITelephonyListener : nsISupp
   /**
    * Notify when RIL receives supplementary service notification.
    *
    * @param clientId
             Indicate the RIL client, 0 ~ (number of client - 1).
    * @param callIndex
    *        Call identifier assigned by the RIL. -1 if not specified
    * @param notification
-   *        One of the nsITelephonyProvider::NOTIFICATION_* values.
+   *        One of the nsITelephonyService::NOTIFICATION_* values.
    */
   void supplementaryServiceNotification(in unsigned long clientId,
                                         in long callIndex,
                                         in unsigned short notification);
 
   /**
    * Called when RIL error occurs.
    *
@@ -154,28 +154,28 @@ interface nsITelephonyCallback : nsISupp
 
   /**
    * Called when a dial request succeeds.
    */
   void notifyDialSuccess(in unsigned long callIndex);
 };
 
 %{C++
-#define TELEPHONY_PROVIDER_CID \
+#define TELEPHONY_SERVICE_CID \
   { 0x9cf8aa52, 0x7c1c, 0x4cde, { 0x97, 0x4e, 0xed, 0x2a, 0xa0, 0xe7, 0x35, 0xfa } }
-#define TELEPHONY_PROVIDER_CONTRACTID \
-  "@mozilla.org/telephony/telephonyprovider;1"
+#define TELEPHONY_SERVICE_CONTRACTID \
+  "@mozilla.org/telephony/telephonyservice;1"
 %}
 
 /**
  * XPCOM component (in the content process) that provides the telephony
  * information.
  */
-[scriptable, uuid(b16ca98f-994f-4ae1-8c2d-e7b18e08d1f3)]
-interface nsITelephonyProvider : nsISupports
+[scriptable, uuid(4ff3ecb7-b024-4752-9dd6-c3623c6e6b8a)]
+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;
   const unsigned short CALL_STATE_HELD = 6;
--- a/dom/telephony/test/marionette/test_dsds_default_service_id.js
+++ b/dom/telephony/test/marionette/test_dsds_default_service_id.js
@@ -1,18 +1,18 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 MARIONETTE_TIMEOUT = 60000;
 MARIONETTE_CONTEXT = "chrome";
 
 Cu.import("resource://gre/modules/Promise.jsm");
 
-const TELEPHONY_PROVIDER_CONTRACTID =
-  "@mozilla.org/telephony/telephonyprovider;1";
+const TELEPHONY_SERVICE_CONTRACTID =
+  "@mozilla.org/telephony/telephonyservice;1";
 
 const PREF_RIL_NUM_RADIO_INTERFACES = "ril.numRadioInterfaces";
 const PREF_DEFAULT_SERVICE_ID = "dom.telephony.defaultServiceId";
 
 function setPrefAndVerify(prefKey, setVal, service, attrName, expectedVal, deferred) {
   log("  Set '" + prefKey + "' to " + setVal);
   Services.prefs.setIntPref(prefKey, setVal);
   let prefVal = Services.prefs.getIntPref(prefKey);
@@ -117,11 +117,11 @@ function verify(contractId, ifaceName, a
 
       deferred.resolve(numRil);
     });
 
   return deferred.promise;
 }
 
 getNumRadioInterfaces()
-  .then(verify.bind(null, TELEPHONY_PROVIDER_CONTRACTID, "nsITelephonyProvider",
+  .then(verify.bind(null, TELEPHONY_SERVICE_CONTRACTID, "nsITelephonyService",
                     "defaultServiceId", PREF_DEFAULT_SERVICE_ID))
   .then(finish);
--- a/dom/webidl/DataStore.webidl
+++ b/dom/webidl/DataStore.webidl
@@ -103,8 +103,15 @@ dictionary DataStoreTask {
   DOMString revisionId;
 
   DataStoreOperation operation;
 
   // When |operation| is "clear" or "done", this must return null.
   DataStoreKey? id;
   any data;
 };
+
+// For internal use.
+dictionary DataStoreRevisionData {
+  DOMString revisionId = "";
+  unsigned long objectId = 0;
+  DOMString operation = "";
+};
deleted file mode 100644
--- a/dom/webidl/Identity.webidl
+++ /dev/null
@@ -1,70 +0,0 @@
-/* -*- 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/.
- */
-
-callback IdentityOnReadyCallback = void();
-callback IdentityOnLoginCallback = void(DOMString identityAssertion);
-callback IdentityOnLogoutCallback = void();
-callback IdentityOnCancelCallback = void(DOMString? error);
-callback IdentityOnErrorCallback = void(DOMString error);
-
-dictionary IdentityWatchOptions {
-  // Required callback
-  IdentityOnLoginCallback onlogin;
-
-  // Optional parameters
-  DOMString wantIssuer;
-  DOMString loggedInUser;
-
-  // Optional callbacks
-  IdentityOnReadyCallback onready;
-  IdentityOnLogoutCallback onlogout;
-  IdentityOnErrorCallback onerror;
-
-  // Certified apps can specify this
-  DOMString audience;
-};
-
-dictionary IdentityRequestOptions {
-  // Optional parameters
-  long refreshAuthentication;
-  DOMString termsOfService;
-  DOMString privacyPolicy;
-  DOMString backgroundColor;
-  DOMString siteLogo;
-  DOMString siteName;
-  DOMString returnTo;
-
-  IdentityOnCancelCallback oncancel;
-
-  // Certified apps can specify this
-  DOMString origin;
-};
-
-dictionary IdentityGetOptions {
-  DOMString privacyPolicy;
-  DOMString termsOfService;
-  DOMString privacyURL;
-  DOMString tosURL;
-  DOMString siteName;
-  DOMString siteLogo;
-};
-
-[JSImplementation="@mozilla.org/identity/manager;1",
- NoInterfaceObject,
- NavigatorProperty="mozId",
- Pref="dom.identity.enabled"]
-interface IdentityManager {
-  void watch(optional IdentityWatchOptions options);
-  void request(optional IdentityRequestOptions options);
-  void logout();
-
-  [Pref="dom.identity.exposeLegacyGetAPI"]
-  void get(IdentityOnLoginCallback callback, optional IdentityGetOptions options);
-
-  [Pref="dom.identity.exposeLegacyGetVerifiedEmailAPI"]
-  void getVerifiedEmail(IdentityOnLoginCallback callback);
-};
-
--- a/dom/webidl/MozPowerManager.webidl
+++ b/dom/webidl/MozPowerManager.webidl
@@ -45,16 +45,23 @@ interface MozPowerManager
 
     /**
      * Is the device's screen currently enabled?  This attribute controls the
      * device's screen, so setting it to false will turn off the screen.
      */
     attribute boolean screenEnabled;
 
     /**
+     * Is the device's keypad/button backlight enabled? Setting it to false will
+     * turn off the device's keypad/button backlight. And the brightness level
+     * is the same as |screenBrightness|.
+     */
+    attribute boolean keyLightEnabled;
+
+    /**
      * How bright is the screen's backlight, on a scale from 0 (very dim) to 1
      * (full brightness)?  Setting this attribute modifies the screen's
      * brightness.
      *
      * You can read and write this attribute even when the screen is disabled,
      * but the backlight is off while the screen is disabled.
      *
      * If you write a value of X into this attribute, the attribute may not have
--- a/dom/webidl/Window.webidl
+++ b/dom/webidl/Window.webidl
@@ -49,17 +49,17 @@ typedef any Transferable;
   [Throws, CrossOriginCallable] void focus();
   [Throws, CrossOriginCallable] void blur();
 
   // other browsing contexts
   [Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy frames;
   [Replaceable, CrossOriginReadable] readonly attribute unsigned long length;
   //[Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy top;
   [Unforgeable, Throws, CrossOriginReadable] readonly attribute WindowProxy? top;
-  [Throws, CrossOriginReadable] attribute WindowProxy? opener;
+  [Throws, CrossOriginReadable] attribute any opener;
   //[Throws] readonly attribute WindowProxy parent;
   [Replaceable, Throws, CrossOriginReadable] readonly attribute WindowProxy? parent;
   [Throws] readonly attribute Element? frameElement;
   //[Throws] WindowProxy open(optional DOMString url = "about:blank", optional DOMString target = "_blank", [TreatNullAs=EmptyString] optional DOMString features = "", optional boolean replace = false);
   [Throws] WindowProxy? open(optional DOMString url = "", optional DOMString target = "", [TreatNullAs=EmptyString] optional DOMString features = "");
   // We think the indexed getter is a bug in the spec, it actually needs to live
   // on the WindowProxy
   //getter WindowProxy (unsigned long index);
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -207,17 +207,16 @@ WEBIDL_FILES = [
     'IDBFileHandle.webidl',
     'IDBIndex.webidl',
     'IDBKeyRange.webidl',
     'IDBObjectStore.webidl',
     'IDBOpenDBRequest.webidl',
     'IDBRequest.webidl',
     'IDBTransaction.webidl',
     'IDBVersionChangeEvent.webidl',
-    'Identity.webidl',
     'ImageData.webidl',
     'ImageDocument.webidl',
     'InputEvent.webidl',
     'InputMethod.webidl',
     'InspectorUtils.webidl',
     'InstallEvent.webidl',
     'InstallPhaseEvent.webidl',
     'InterAppConnection.webidl',
--- a/gfx/thebes/gfxUtils.cpp
+++ b/gfx/thebes/gfxUtils.cpp
@@ -137,63 +137,20 @@ gfxUtils::UnpremultiplyDataSurface(DataS
     }
 
     aSurface->Unmap();
     dest->Unmap();
     return dest;
 }
 
 void
-gfxUtils::ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
-                            gfxImageSurface *aDestSurface) {
-    if (!aDestSurface)
-        aDestSurface = aSourceSurface;
-
-    MOZ_ASSERT(aSourceSurface->Format() == aDestSurface->Format() &&
-               aSourceSurface->Width()  == aDestSurface->Width() &&
-               aSourceSurface->Height() == aDestSurface->Height() &&
-               aSourceSurface->Stride() == aDestSurface->Stride(),
-               "Source and destination surfaces don't have identical characteristics");
-
-    MOZ_ASSERT(aSourceSurface->Stride() == aSourceSurface->Width() * 4,
-               "Source surface stride isn't tightly packed");
-
-    MOZ_ASSERT(aSourceSurface->Format() == gfxImageFormat::ARGB32 || aSourceSurface->Format() == gfxImageFormat::RGB24,
-               "Surfaces must be ARGB32 or RGB24");
-
-    uint8_t *src = aSourceSurface->Data();
-    uint8_t *dst = aDestSurface->Data();
-
-    uint32_t dim = aSourceSurface->Width() * aSourceSurface->Height();
-    uint8_t *srcEnd = src + 4*dim;
-
-    if (src == dst) {
-        uint8_t buffer[4];
-        for (; src != srcEnd; src += 4) {
-            buffer[0] = src[2];
-            buffer[1] = src[1];
-            buffer[2] = src[0];
-
-            src[0] = buffer[0];
-            src[1] = buffer[1];
-            src[2] = buffer[2];
-        }
-    } else {
-        for (; src != srcEnd; src += 4, dst += 4) {
-            dst[0] = src[2];
-            dst[1] = src[1];
-            dst[2] = src[0];
-            dst[3] = src[3];
-        }
-    }
-}
-
-void
 gfxUtils::ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength)
 {
+    MOZ_ASSERT((aLength % 4) == 0, "Loop below will pass srcEnd!");
+
     uint8_t *src = aData;
     uint8_t *srcEnd = src + aLength;
 
     uint8_t buffer[4];
     for (; src != srcEnd; src += 4) {
         buffer[0] = src[2];
         buffer[1] = src[1];
         buffer[2] = src[0];
--- a/gfx/thebes/gfxUtils.h
+++ b/gfx/thebes/gfxUtils.h
@@ -38,18 +38,16 @@ public:
      * stride as the source.
      *
      * If the source is not gfxImageFormat::ARGB32, no operation is performed.  If
      * aDestSurface is given, the data is copied over.
      */
     static void PremultiplyDataSurface(DataSourceSurface *aSurface);
     static mozilla::TemporaryRef<DataSourceSurface> UnpremultiplyDataSurface(DataSourceSurface* aSurface);
 
-    static void ConvertBGRAtoRGBA(gfxImageSurface *aSourceSurface,
-                                  gfxImageSurface *aDestSurface = nullptr);
     static void ConvertBGRAtoRGBA(uint8_t* aData, uint32_t aLength);
 
     /**
      * Draw something drawable while working around limitations like bad support
      * for EXTEND_PAD, lack of source-clipping, or cairo / pixman bugs with
      * extreme user-space-to-image-space transforms.
      *
      * The input parameters here usually come from the output of our image
--- a/hal/Hal.cpp
+++ b/hal/Hal.cpp
@@ -369,48 +369,60 @@ NotifyBatteryChange(const BatteryInforma
 }
 
 bool GetScreenEnabled()
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetScreenEnabled(), false);
 }
 
-void SetScreenEnabled(bool enabled)
+void SetScreenEnabled(bool aEnabled)
 {
   AssertMainThread();
-  PROXY_IF_SANDBOXED(SetScreenEnabled(enabled));
+  PROXY_IF_SANDBOXED(SetScreenEnabled(aEnabled));
+}
+
+bool GetKeyLightEnabled()
+{
+  AssertMainThread();
+  RETURN_PROXY_IF_SANDBOXED(GetKeyLightEnabled(), false);
+}
+
+void SetKeyLightEnabled(bool aEnabled)
+{
+  AssertMainThread();
+  PROXY_IF_SANDBOXED(SetKeyLightEnabled(aEnabled));
 }
 
 bool GetCpuSleepAllowed()
 {
   // Generally for interfaces that are accessible by normal web content
   // we should cache the result and be notified on state changes, like
   // what the battery API does. But since this is only used by
   // privileged interface, the synchronous getter is OK here.
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetCpuSleepAllowed(), true);
 }
 
-void SetCpuSleepAllowed(bool allowed)
+void SetCpuSleepAllowed(bool aAllowed)
 {
   AssertMainThread();
-  PROXY_IF_SANDBOXED(SetCpuSleepAllowed(allowed));
+  PROXY_IF_SANDBOXED(SetCpuSleepAllowed(aAllowed));
 }
 
 double GetScreenBrightness()
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(GetScreenBrightness(), 0);
 }
 
-void SetScreenBrightness(double brightness)
+void SetScreenBrightness(double aBrightness)
 {
   AssertMainThread();
-  PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(brightness, 0.0, 1.0)));
+  PROXY_IF_SANDBOXED(SetScreenBrightness(clamped(aBrightness, 0.0, 1.0)));
 }
 
 bool SetLight(LightType light, const LightConfiguration& aConfig)
 {
   AssertMainThread();
   RETURN_PROXY_IF_SANDBOXED(SetLight(light, aConfig), false);
 }
 
--- a/hal/Hal.h
+++ b/hal/Hal.h
@@ -119,17 +119,27 @@ void NotifyBatteryChange(const hal::Batt
  */
 bool GetScreenEnabled();
 
 /**
  * Enable or disable the device's screen.
  *
  * Note that it may take a few seconds for the screen to turn on or off.
  */
-void SetScreenEnabled(bool enabled);
+void SetScreenEnabled(bool aEnabled);
+
+/**
+ * Determine whether the device's keypad/button backlight is currently enabled.
+ */
+bool GetKeyLightEnabled();
+
+/**
+ * Enable or disable the device's keypad/button backlight.
+ */
+void SetKeyLightEnabled(bool aEnabled);
 
 /**
  * Get the brightness of the device's screen's backlight, on a scale from 0
  * (very dim) to 1 (full blast).
  *
  * If the display is currently disabled, this returns the brightness the
  * backlight will have when the display is re-enabled.
  */
@@ -140,28 +150,28 @@ double GetScreenBrightness();
  * (very dimm) to 1 (full blast).  Values larger than 1 are treated like 1, and
  * values smaller than 0 are treated like 0.
  *
  * Note that we may reduce the resolution of the given brightness value before
  * sending it to the screen.  Therefore if you call SetScreenBrightness(x)
  * followed by GetScreenBrightness(), the value returned by
  * GetScreenBrightness() may not be exactly x.
  */
-void SetScreenBrightness(double brightness);
+void SetScreenBrightness(double aBrightness);
 
 /**
  * Determine whether the device is allowed to sleep.
  */
 bool GetCpuSleepAllowed();
 
 /**
  * Set whether the device is allowed to suspend automatically after
  * the screen is disabled.
  */
-void SetCpuSleepAllowed(bool allowed);
+void SetCpuSleepAllowed(bool aAllowed);
 
 /**
  * Set the value of a light to a particular color, with a specific flash pattern.
  * light specifices which light.  See Hal.idl for the list of constants
  * mode specifies user set or based on ambient light sensor
  * flash specifies whether or how to flash the light
  * flashOnMS and flashOffMS specify the pattern for XXX flash mode
  * color specifies the color.  If the light doesn't support color, the given color is
--- a/hal/fallback/FallbackScreenPower.cpp
+++ b/hal/fallback/FallbackScreenPower.cpp
@@ -9,23 +9,33 @@ namespace hal_impl {
 
 bool
 GetScreenEnabled()
 {
   return true;
 }
 
 void
-SetScreenEnabled(bool enabled)
+SetScreenEnabled(bool aEnabled)
+{}
+
+bool
+GetKeyLightEnabled()
+{
+  return true;
+}
+
+void
+SetKeyLightEnabled(bool aEnabled)
 {}
 
 double
 GetScreenBrightness()
 {
   return 1;
 }
 
 void
-SetScreenBrightness(double brightness)
+SetScreenBrightness(double aBrightness)
 {}
 
 } // hal_impl
 } // namespace mozilla
--- a/hal/gonk/GonkHal.cpp
+++ b/hal/gonk/GonkHal.cpp
@@ -535,57 +535,92 @@ int32_t sInternalLockCpuCount = 0;
 
 bool
 GetScreenEnabled()
 {
   return sScreenEnabled;
 }
 
 void
-SetScreenEnabled(bool enabled)
+SetScreenEnabled(bool aEnabled)
+{
+  GetGonkDisplay()->SetEnabled(aEnabled);
+  sScreenEnabled = aEnabled;
+}
+
+bool
+GetKeyLightEnabled()
+{
+  hal::LightConfiguration config;
+  hal_impl::GetLight(hal::eHalLightID_Buttons, &config);
+  return (config.color() != 0x00000000);
+}
+
+void
+SetKeyLightEnabled(bool aEnabled)
 {
-  GetGonkDisplay()->SetEnabled(enabled);
-  sScreenEnabled = enabled;
+  hal::LightConfiguration config;
+  config.mode() = hal::eHalLightMode_User;
+  config.flash() = hal::eHalLightFlash_None;
+  config.flashOnMS() = config.flashOffMS() = 0;
+  config.color() = 0x00000000;
+
+  if (aEnabled) {
+    // Convert the value in [0, 1] to an int between 0 and 255 and then convert
+    // it to a color. Note that the high byte is FF, corresponding to the alpha
+    // channel.
+    double brightness = GetScreenBrightness();
+    uint32_t val = static_cast<int>(round(brightness * 255.0));
+    uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;
+
+    config.color() = color;
+  }
+
+  hal_impl::SetLight(hal::eHalLightID_Buttons, config);
+  hal_impl::SetLight(hal::eHalLightID_Keyboard, config);
 }
 
 double
 GetScreenBrightness()
 {
-  hal::LightConfiguration aConfig;
+  hal::LightConfiguration config;
   hal::LightType light = hal::eHalLightID_Backlight;
 
-  hal::GetLight(light, &aConfig);
+  hal_impl::GetLight(light, &config);
   // backlight is brightness only, so using one of the RGB elements as value.
-  int brightness = aConfig.color() & 0xFF;
+  int brightness = config.color() & 0xFF;
   return brightness / 255.0;
 }
 
 void
 SetScreenBrightness(double brightness)
 {
   // Don't use De Morgan's law to push the ! into this expression; we want to
   // catch NaN too.
   if (!(0 <= brightness && brightness <= 1)) {
     HAL_LOG(("SetScreenBrightness: Dropping illegal brightness %f.",
              brightness));
     return;
   }
 
   // Convert the value in [0, 1] to an int between 0 and 255 and convert to a color
   // note that the high byte is FF, corresponding to the alpha channel.
-  int val = static_cast<int>(round(brightness * 255));
+  uint32_t val = static_cast<int>(round(brightness * 255.0));
   uint32_t color = (0xff<<24) + (val<<16) + (val<<8) + val;
 
-  hal::LightConfiguration aConfig;
-  aConfig.mode() = hal::eHalLightMode_User;
-  aConfig.flash() = hal::eHalLightFlash_None;
-  aConfig.flashOnMS() = aConfig.flashOffMS() = 0;
-  aConfig.color() = color;
-  hal::SetLight(hal::eHalLightID_Backlight, aConfig);
-  hal::SetLight(hal::eHalLightID_Buttons, aConfig);
+  hal::LightConfiguration config;
+  config.mode() = hal::eHalLightMode_User;
+  config.flash() = hal::eHalLightFlash_None;
+  config.flashOnMS() = config.flashOffMS() = 0;
+  config.color() = color;
+  hal_impl::SetLight(hal::eHalLightID_Backlight, config);
+  if (GetKeyLightEnabled()) {
+    hal_impl::SetLight(hal::eHalLightID_Buttons, config);
+    hal_impl::SetLight(hal::eHalLightID_Keyboard, config);
+  }
 }
 
 static Monitor* sInternalLockCpuMonitor = nullptr;
 
 static void
 UpdateCpuSleepState()
 {
   sInternalLockCpuMonitor->AssertCurrentThreadOwns();
--- a/hal/sandbox/PHal.ipdl
+++ b/hal/sandbox/PHal.ipdl
@@ -122,23 +122,26 @@ parent:
       returns (BatteryInformation aBatteryInfo);
 
     EnableNetworkNotifications();
     DisableNetworkNotifications();
     sync GetCurrentNetworkInformation()
       returns (NetworkInformation aNetworkInfo);
 
     sync GetScreenEnabled() returns (bool enabled);
-    SetScreenEnabled(bool enabled);
+    SetScreenEnabled(bool aEnabled);
+
+    sync GetKeyLightEnabled() returns (bool enabled);
+    SetKeyLightEnabled(bool aEnabled);
 
     sync GetCpuSleepAllowed() returns (bool allowed);
-    SetCpuSleepAllowed(bool allowed);
+    SetCpuSleepAllowed(bool aAllowed);
 
     sync GetScreenBrightness() returns (double brightness);
-    SetScreenBrightness(double brightness);
+    SetScreenBrightness(double aBrightness);
 
     AdjustSystemClock(int64_t aDeltaMilliseconds);
     SetTimezone(nsCString aTimezoneSpec);
     sync GetTimezone()
       returns (nsCString aTimezoneSpec);
     sync GetTimezoneOffset()
       returns (int32_t aTimezoneOffset);
     EnableSystemClockChangeNotifications();
--- a/hal/sandbox/SandboxHal.cpp
+++ b/hal/sandbox/SandboxHal.cpp
@@ -138,47 +138,61 @@ bool
 GetScreenEnabled()
 {
   bool enabled = false;
   Hal()->SendGetScreenEnabled(&enabled);
   return enabled;
 }
 
 void
-SetScreenEnabled(bool enabled)
+SetScreenEnabled(bool aEnabled)
+{
+  Hal()->SendSetScreenEnabled(aEnabled);
+}
+
+bool
+GetKeyLightEnabled()
 {
-  Hal()->SendSetScreenEnabled(enabled);
+  bool enabled = false;
+  Hal()->SendGetKeyLightEnabled(&enabled);
+  return enabled;
+}
+
+void
+SetKeyLightEnabled(bool aEnabled)
+{
+  Hal()->SendSetKeyLightEnabled(aEnabled);
 }
 
 bool
 GetCpuSleepAllowed()
 {
   bool allowed = true;
   Hal()->SendGetCpuSleepAllowed(&allowed);
   return allowed;
 }
 
 void
-SetCpuSleepAllowed(bool allowed)
+SetCpuSleepAllowed(bool aAllowed)
 {
-  Hal()->SendSetCpuSleepAllowed(allowed);
+  Hal()->SendSetCpuSleepAllowed(aAllowed);
 }
 
 double
 GetScreenBrightness()
 {
   double brightness = 0;
   Hal()->SendGetScreenBrightness(&brightness);
   return brightness;
 }
 
 void
-SetScreenBrightness(double brightness)
+SetScreenBrightness(double aBrightness)
 {
-  Hal()->SendSetScreenBrightness(brightness);
+  Hal()->SendSetScreenBrightness(aBrightness);
 }
 
 bool
 SetLight(hal::LightType light, const hal::LightConfiguration& aConfig)
 {
   bool status;
   Hal()->SendSetLight(light, aConfig, &status);
   return status;
@@ -586,72 +600,92 @@ public:
     return true;
   }
 
   void Notify(const ScreenConfiguration& aScreenConfiguration) {
     unused << SendNotifyScreenConfigurationChange(aScreenConfiguration);
   }
 
   virtual bool
-  RecvGetScreenEnabled(bool *enabled) MOZ_OVERRIDE
+  RecvGetScreenEnabled(bool* aEnabled) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    *enabled = hal::GetScreenEnabled();
+    *aEnabled = hal::GetScreenEnabled();
     return true;
   }
 
   virtual bool
-  RecvSetScreenEnabled(const bool &enabled) MOZ_OVERRIDE
+  RecvSetScreenEnabled(const bool& aEnabled) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    hal::SetScreenEnabled(enabled);
+    hal::SetScreenEnabled(aEnabled);
     return true;
   }
 
   virtual bool
-  RecvGetCpuSleepAllowed(bool *allowed) MOZ_OVERRIDE
+  RecvGetKeyLightEnabled(bool* aEnabled) MOZ_OVERRIDE
+  {
+    if (!AssertAppProcessPermission(this, "power")) {
+      return false;
+    }
+    *aEnabled = hal::GetKeyLightEnabled();
+    return true;
+  }
+
+  virtual bool
+  RecvSetKeyLightEnabled(const bool& aEnabled) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    *allowed = hal::GetCpuSleepAllowed();
+    hal::SetKeyLightEnabled(aEnabled);
     return true;
   }
 
   virtual bool
-  RecvSetCpuSleepAllowed(const bool &allowed) MOZ_OVERRIDE
+  RecvGetCpuSleepAllowed(bool* aAllowed) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    hal::SetCpuSleepAllowed(allowed);
+    *aAllowed = hal::GetCpuSleepAllowed();
     return true;
   }
 
   virtual bool
-  RecvGetScreenBrightness(double *brightness) MOZ_OVERRIDE
+  RecvSetCpuSleepAllowed(const bool& aAllowed) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    *brightness = hal::GetScreenBrightness();
+    hal::SetCpuSleepAllowed(aAllowed);
     return true;
   }
 
   virtual bool
-  RecvSetScreenBrightness(const double &brightness) MOZ_OVERRIDE
+  RecvGetScreenBrightness(double* aBrightness) MOZ_OVERRIDE
   {
     if (!AssertAppProcessPermission(this, "power")) {
       return false;
     }
-    hal::SetScreenBrightness(brightness);
+    *aBrightness = hal::GetScreenBrightness();
+    return true;
+  }
+
+  virtual bool
+  RecvSetScreenBrightness(const double& aBrightness) MOZ_OVERRIDE
+  {
+    if (!AssertAppProcessPermission(this, "power")) {
+      return false;
+    }
+    hal::SetScreenBrightness(aBrightness);
     return true;
   }
 
   virtual bool
   RecvSetLight(const LightType& aLight,  const hal::LightConfiguration& aConfig, bool *status) MOZ_OVERRIDE
   {
     // XXX currently, the hardware key light and screen backlight are
     // controlled as a unit.  Those are set through the power API, and
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -297,16 +297,17 @@ typedef union jsval_layout
     struct {
         JSValueTag tag;
         union {
             int32_t        i32;
             uint32_t       u32;
             uint32_t       boo;     // Don't use |bool| -- it must be four bytes.
             JSString       *str;
             JSObject       *obj;
+            js::gc::Cell   *cell;
             void           *ptr;
             JSWhyMagic     why;
             size_t         word;
             uintptr_t      uintptr;
         } payload;
     } s;
     double asDouble;
     void *asPtr;
--- a/js/src/gc/GCRuntime.h
+++ b/js/src/gc/GCRuntime.h
@@ -14,16 +14,21 @@
 # include "gc/Nursery.h"
 #endif
 #include "gc/Statistics.h"
 #ifdef JSGC_GENERATIONAL
 # include "gc/StoreBuffer.h"
 #endif
 #include "gc/Tracer.h"
 
+/* Perform validation of incremental marking in debug builds but not on B2G. */
+#if defined(DEBUG) && !defined(MOZ_B2G)
+#define JS_GC_MARKING_VALIDATION
+#endif
+
 namespace js {
 
 struct ScriptAndCounts
 {
     /* This structure is stored and marked from the JSRuntime. */
     JSScript *script;
     ScriptCounts scriptCounts;
 
@@ -405,17 +410,17 @@ class GCRuntime
     int                   sweepKindIndex;
     bool                  abortSweepAfterCurrentGroup;
 
     /*
      * List head of arenas allocated during the sweep phase.
      */
     js::gc::ArenaHeader   *arenasAllocatedDuringSweep;
 
-#ifdef DEBUG
+#ifdef JS_GC_MARKING_VALIDATION
     js::gc::MarkingValidator *markingValidator;
 #endif
 
     /*
      * Indicates that a GC slice has taken place in the middle of an animation
      * frame, rather than at the beginning. In this case, the next slice will be
      * delayed so that we don't get back-to-back slices.
      */
--- a/js/src/jit-test/tests/ion/dce-with-rinstructions.js
+++ b/js/src/jit-test/tests/ion/dce-with-rinstructions.js
@@ -187,16 +187,35 @@ function rsub_object(i) {
     var o = { valueOf: function () { return t; } };
     var x = o - i; /* computed with t == i, not 1000 */
     t = 1000;
     if (uceFault_sub_object(i) || uceFault_sub_object(i))
         assertEq(x, 0);
     return i;
 }
 
+var uceFault_mod_number = eval(uneval(uceFault).replace('uceFault', 'uceFault_mod_number'));
+function rmod_number(i) {
+    var x = i % 98;
+    if (uceFault_mod_number(i) || uceFault_mod_number(i))
+        assertEq(x, 1); /* 99 % 98 = 1 */
+    return i;
+}
+
+var uceFault_mod_object = eval(uneval(uceFault).replace('uceFault', 'uceFault_mod_object'));
+function rmod_object(i) {
+    var t = i;
+    var o = { valueOf: function() { return t; } };
+    var x = o % 98; /* computed with t == i, not 1000 */
+    t = 1000;
+    if(uceFault_mod_object(i) || uceFault_mod_object(i))
+        assertEq(x, 1); /* 99 % 98 = 1 */
+    return i;
+}
+
 for (i = 0; i < 100; i++) {
     rbitnot_number(i);
     rbitnot_object(i);
     rbitor_number(i);
     rbitor_object(i);
     rbitxor_number(i);
     rbitxor_object(i);
     rlsh_number(i);
@@ -207,16 +226,18 @@ for (i = 0; i < 100; i++) {
     rursh_object(i);
     radd_number(i);
     radd_float(i);
     radd_string(i);
     radd_object(i);
     rsub_number(i);
     rsub_float(i);
     rsub_object(i);
+    rmod_number(i);
+    rmod_object(i);
 }
 
 // Test that we can refer multiple time to the same recover instruction, as well
 // as chaining recover instructions.
 
 function alignedAlloc($size, $alignment) {
     var $1 = $size + 4 | 0;
     var $2 = $alignment - 1 | 0;
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/dependent.js
@@ -0,0 +1,73 @@
+function testSubstrLatin1() {
+    var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz12345678900000a");
+
+    // Static strings.
+    assertEq(s1.substr(s1.length - 1), "a");
+    assertEq(s1.substr(s1.length - 2), "0a");
+    assertEq(s1.substr(26, 3), "123");
+
+    // (Fat) inline strings.
+    var s2 = s1.substr(3, 5);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "defgh");
+    s2 = s1.substr(0, 20);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "abcdefghijklmnopqrst");
+
+    // Dependent string.
+    s2 = s1.substr(1, s1.length - 2);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2.length, 39);
+    assertEq(s2, "bcdefghijklmnopqrstuvwxyz12345678900000");
+
+    s2 = s2.substr(2).substr(1);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "efghijklmnopqrstuvwxyz12345678900000");
+}
+testSubstrLatin1();
+
+function testSubstrTwoByte() {
+    // Two byte string.
+    var s1 = "abcdefghijklmnopqrstuvwxyz12345678900000a\u1480";
+    assertEq(isLatin1(s1), false);
+
+    // Static string.
+    var s2 = s1.substr(28, 1);
+    assertEq(s2, "3");
+
+    // Inline string.
+    s2 = s1.substr(3, 5);
+    assertEq(s2, "defgh");
+
+    // Dependent string.
+    s2 = s1.substr(2);
+    assertEq(isLatin1(s2), false);
+    assertEq(s2, "cdefghijklmnopqrstuvwxyz12345678900000a\u1480");
+
+    s2 = s2.substr(2).substr(1);
+    assertEq(isLatin1(s2), false);
+    assertEq(s2, "fghijklmnopqrstuvwxyz12345678900000a\u1480");
+}
+testSubstrTwoByte();
+
+function testSubstring() {
+    var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz123456789000ab");
+    var s2 = s1.substring(1, 8);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "bcdefgh");
+    s2 = s1.substring(0, s1.length - 1);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000a");
+}
+testSubstring();
+
+function testSlice() {
+    var s1 = toLatin1("abcdefghijklmnopqrstuvwxyz123456789000ABC");
+    var s2 = s1.slice(1, 8);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "bcdefgh");
+    s2 = s1.slice(0, -2);
+    assertEq(isLatin1(s2), true);
+    assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000A");
+}
+testSlice();
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/other.js
@@ -0,0 +1,31 @@
+var s1 = toLatin1("abcdefg12345");
+var s2 = toLatin1('foo"bar');
+
+function test() {
+    assertEq(s1.valueOf(), s1);
+
+    assertEq(s1.bold(), "<b>abcdefg12345</b>");
+    assertEq(s1.fontsize("twoByte\u1400"), '<font size="twoByte\u1400">abcdefg12345</font>');
+    assertEq(s1.anchor(s1), '<a name="abcdefg12345">abcdefg12345</a>');
+    assertEq(s1.link(s2), '<a href="foo&quot;bar">abcdefg12345</a>');
+
+    assertEq(s1.concat("abc"), "abcdefg12345abc");
+
+    var s3 = s1.concat(s1, s1);
+    assertEq(isLatin1(s3), true);
+    assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345");
+
+    s3 = s1.concat("twoByte\u1400");
+    assertEq(isLatin1(s3), false);
+    assertEq(s3, "abcdefg12345twoByte\u1400");
+
+    assertEq(s1.codePointAt(3), 100);
+    assertEq(s1.codePointAt(10), 52);
+    assertEq(s1.codePointAt(12), undefined);
+
+    s3 = s1.repeat(5);
+    assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345abcdefg12345abcdefg12345");
+    assertEq(isLatin1(s3), true);
+}
+test();
+test();
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -5985,19 +5985,21 @@ CheckModuleReturn(ModuleCompiler &m)
 
 // All registers except the stack pointer.
 static const RegisterSet AllRegsExceptSP =
     RegisterSet(GeneralRegisterSet(Registers::AllMask &
                                    ~(uint32_t(1) << Registers::StackPointer)),
                 FloatRegisterSet(FloatRegisters::AllMask));
 #if defined(JS_CODEGEN_ARM)
 // The ARM system ABI also includes d15 in the non volatile float registers.
+// Also exclude lr (a.k.a. r14) as we preserve it manually)
 static const RegisterSet NonVolatileRegs =
-    RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
-                    FloatRegisterSet(FloatRegisters::NonVolatileMask | (1 << FloatRegisters::d15)));
+    RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask &
+                                   ~(uint32_t(1) << Registers::lr)),
+                FloatRegisterSet(FloatRegisters::NonVolatileMask | (1 << FloatRegisters::d15)));
 #else
 static const RegisterSet NonVolatileRegs =
     RegisterSet(GeneralRegisterSet(Registers::NonVolatileMask),
                 FloatRegisterSet(FloatRegisters::NonVolatileMask));
 #endif
 
 static void
 LoadAsmJSActivationIntoRegister(MacroAssembler &masm, Register reg)
@@ -6012,17 +6014,17 @@ static void
 LoadJSContextFromActivation(MacroAssembler &masm, Register activation, Register dest)
 {
     masm.loadPtr(Address(activation, AsmJSActivation::offsetOfContext()), dest);
 }
 
 static void
 AssertStackAlignment(MacroAssembler &masm)
 {
-    JS_ASSERT((AlignmentAtPrologue + masm.framePushed()) % StackAlignment == 0);
+    JS_ASSERT((AlignmentAtAsmJSPrologue + masm.framePushed()) % StackAlignment == 0);
 #ifdef DEBUG
     Label ok;
     JS_ASSERT(IsPowerOfTwo(StackAlignment));
     masm.branchTestPtr(Assembler::Zero, StackPointer, Imm32(StackAlignment - 1), &ok);
     masm.assumeUnreachable("Stack should be aligned.");
     masm.bind(&ok);
 #endif
 }
@@ -6037,17 +6039,17 @@ StackArgBytes(const VectorT &argTypes)
     return iter.stackBytesConsumedSoFar();
 }
 
 static unsigned
 StackDecrementForCall(MacroAssembler &masm, unsigned bytesToPush)
 {
     // Include extra padding so that, after pushing the bytesToPush,
     // the stack is aligned for a call instruction.
-    unsigned alreadyPushed = AlignmentAtPrologue + masm.framePushed();
+    unsigned alreadyPushed = AlignmentAtAsmJSPrologue + masm.framePushed();
     return AlignBytes(alreadyPushed + bytesToPush, StackAlignment) - alreadyPushed;
 }
 
 template <class VectorT>
 static unsigned
 StackDecrementForCall(MacroAssembler &masm, const VectorT &argTypes, unsigned extraBytes = 0)
 {
     return StackDecrementForCall(masm, StackArgBytes(argTypes) + extraBytes);
@@ -6073,16 +6075,24 @@ GenerateEntry(ModuleCompiler &m, const A
 
     // In constrast to the system ABI, the Ion convention is that all registers
     // are clobbered by calls. Thus, we must save the caller's non-volatile
     // registers.
     //
     // NB: GenerateExits assumes that masm.framePushed() == 0 before
     // PushRegsInMask(NonVolatileRegs).
     masm.setFramePushed(0);
+
+#if defined(JS_CODEGEN_ARM)
+    // Push lr without incrementing masm.framePushed since this push is
+    // accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
+    // pop.
+    masm.push(lr);
+#endif // JS_CODEGEN_ARM
+
     masm.PushRegsInMask(NonVolatileRegs);
     JS_ASSERT(masm.framePushed() == FramePushedAfterSave);
 
     // Remember the stack pointer in the current AsmJSActivation. This will be
     // used by error exit paths to set the stack pointer back to what it was
     // right after the (C++) caller's non-volatile registers were saved so that
     // they can be restored.
     Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
@@ -6169,17 +6179,17 @@ GenerateEntry(ModuleCompiler &m, const A
     }
 
     // Restore clobbered non-volatile registers of the caller.
     masm.PopRegsInMask(NonVolatileRegs);
 
     JS_ASSERT(masm.framePushed() == 0);
 
     masm.move32(Imm32(true), ReturnReg);
-    masm.abiret();
+    masm.ret();
     return true;
 }
 
 static inline bool
 TryEnablingIon(JSContext *cx, AsmJSModule &module, HandleFunction fun, uint32_t exitIndex,
                int32_t argc, Value *argv)
 {
     if (!fun->hasScript())
@@ -6323,35 +6333,39 @@ FillArgumentArray(ModuleCompiler &m, con
 static void
 GenerateFFIInterpreterExit(ModuleCompiler &m, const ModuleCompiler::ExitDescriptor &exit,
                            unsigned exitIndex, Label *throwLabel)
 {
     MacroAssembler &masm = m.masm();
     masm.align(CodeAlignment);
     m.setInterpExitOffset(exitIndex);
     masm.setFramePushed(0);
+
 #if defined(JS_CODEGEN_ARM)
-    masm.Push(lr);
+    // Push lr without incrementing masm.framePushed since this push is
+    // accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
+    // pop.
+    masm.push(lr);
 #endif
 
     MIRType typeArray[] = { MIRType_Pointer,   // cx
                             MIRType_Pointer,   // exitDatum
                             MIRType_Int32,     // argc
                             MIRType_Pointer }; // argv
     MIRTypeVector invokeArgTypes(m.cx());
     invokeArgTypes.infallibleAppend(typeArray, ArrayLength(typeArray));
 
     // The stack layout looks like:
     // | return address | stack arguments | array of values |
     unsigned arraySize = Max<size_t>(1, exit.sig().args().length()) * sizeof(Value);
     unsigned stackDec = StackDecrementForCall(masm, invokeArgTypes, arraySize + MaybeRetAddr);
     masm.reserveStack(stackDec);
 
     // Fill the argument array.
-    unsigned offsetToCallerStackArgs = AlignmentAtPrologue + masm.framePushed();
+    unsigned offsetToCallerStackArgs = AlignmentAtAsmJSPrologue + masm.framePushed();
     unsigned offsetToArgv = StackArgBytes(invokeArgTypes) + MaybeRetAddr;
     Register scratch = ABIArgGenerator::NonArgReturnVolatileReg0;
     FillArgumentArray(m, exit.sig().args(), offsetToArgv, offsetToCallerStackArgs, scratch);
 
     // Prepare the arguments for the call to InvokeFromAsmJS_*.
     ABIArgMIRTypeIter i(invokeArgTypes);
     Register activation = ABIArgGenerator::NonArgReturnVolatileReg1;
     LoadAsmJSActivationIntoRegister(masm, activation);
@@ -6494,24 +6508,26 @@ GenerateFFIIonExit(ModuleCompiler &m, co
     MacroAssembler &masm = m.masm();
     masm.align(CodeAlignment);
     m.setIonExitOffset(exitIndex);
     masm.setFramePushed(0);
 
 #if defined(JS_CODEGEN_X64)
     masm.Push(HeapReg);
 #elif defined(JS_CODEGEN_ARM)
-    // The lr register holds the return address and needs to be saved.  The GlobalReg
-    // (r10) and HeapReg (r11) also need to be restored before returning to asm.js code.
+    // Push lr without incrementing masm.framePushed since this push is
+    // accounted for by AlignmentAtAsmJSPrologue. The masm.ret at the end will
+    // pop.
+    masm.push(lr);
+
+    // The GlobalReg (r10) and HeapReg (r11) also need to be restored before
+    // returning to asm.js code.
     // The NANReg also needs to be restored, but is a constant and is reloaded before
     // returning to asm.js code.
-    masm.PushRegsInMask(RegisterSet(GeneralRegisterSet((1<<GlobalReg.code()) |
-                                                       (1<<HeapReg.code()) |
-                                                       (1<<lr.code())),
-                                    FloatRegisterSet(uint32_t(0))));
+    masm.PushRegsInMask(GeneralRegisterSet((1<<GlobalReg.code()) | (1<<HeapReg.code())));
 #endif
 
     // The stack frame is used for the call into Ion and also for calls into C for OOL
     // conversion of the result.  A frame large enough for both is allocated.
     //
     // Arguments to the Ion function are in the following order on the stack:
     // | return address | descriptor | callee | argc | this | arg1 | arg2 | ...
     unsigned argBytes = 3 * sizeof(size_t) + (1 + exit.sig().args().length()) * sizeof(Value);
@@ -6695,28 +6711,24 @@ GenerateFFIIonExit(ModuleCompiler &m, co
         break;
       case RetType::Float:
         MOZ_ASSUME_UNREACHABLE("Float shouldn't be returned from a FFI");
         break;
     }
 
     masm.bind(&done);
     masm.freeStack(stackDec);
+#if defined(JS_CODEGEN_X64)
+    masm.Pop(HeapReg);
+#endif
 #if defined(JS_CODEGEN_ARM)
     masm.ma_vimm(GenericNaN(), NANReg);
-    masm.PopRegsInMask(RegisterSet(GeneralRegisterSet((1<<GlobalReg.code()) |
-                                                      (1<<HeapReg.code()) |
-                                                      (1<<pc.code())),
-                                   FloatRegisterSet(uint32_t(0))));
-#else
-# if defined(JS_CODEGEN_X64)
-    masm.Pop(HeapReg);
-# endif
+    masm.PopRegsInMask(GeneralRegisterSet((1<<GlobalReg.code()) | (1<<HeapReg.code())));
+#endif
     masm.ret();
-#endif
     JS_ASSERT(masm.framePushed() == 0);
 
     // oolConvert
     if (oolConvert.used()) {
         masm.bind(&oolConvert);
         masm.setFramePushed(oolConvertFramePushed);
         GenerateOOLConvert(m, exit.sig().retType(), throwLabel);
         masm.setFramePushed(0);
@@ -6746,20 +6758,16 @@ GenerateFFIExit(ModuleCompiler &m, const
 // all the frames.
 static bool
 GenerateStackOverflowExit(ModuleCompiler &m, Label *throwLabel)
 {
     MacroAssembler &masm = m.masm();
     masm.align(CodeAlignment);
     masm.bind(&m.stackOverflowLabel());
 
-    // The overflow check always occurs before the initial function-specific
-    // stack-size adjustment. See CodeGenerator::generateAsmJSPrologue.
-    masm.setFramePushed(AlignmentMidPrologue - AlignmentAtPrologue);
-
     MIRTypeVector argTypes(m.cx());
     argTypes.infallibleAppend(MIRType_Pointer); // cx
 
     unsigned stackDec = StackDecrementForCall(masm, argTypes, MaybeRetAddr);
     masm.reserveStack(stackDec);
 
     Register activation = ABIArgGenerator::NonArgReturnVolatileReg0;
     LoadAsmJSActivationIntoRegister(masm, activation);
@@ -6919,17 +6927,17 @@ GenerateThrowExit(ModuleCompiler &m, Lab
 
     masm.setFramePushed(FramePushedAfterSave);
     masm.loadPtr(Address(activation, AsmJSActivation::offsetOfErrorRejoinSP()), StackPointer);
 
     masm.PopRegsInMask(NonVolatileRegs);
     JS_ASSERT(masm.framePushed() == 0);
 
     masm.mov(ImmWord(0), ReturnReg);
-    masm.abiret();
+    masm.ret();
 
     return !masm.oom();
 }
 
 static bool
 GenerateStubs(ModuleCompiler &m)
 {
     for (unsigned i = 0; i < m.module().numExportedFunctions(); i++) {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -8323,16 +8323,37 @@ CodeGenerator::visitCallInstanceOf(LCall
 bool
 CodeGenerator::visitGetDOMProperty(LGetDOMProperty *ins)
 {
     const Register JSContextReg = ToRegister(ins->getJSContextReg());
     const Register ObjectReg = ToRegister(ins->getObjectReg());
     const Register PrivateReg = ToRegister(ins->getPrivReg());
     const Register ValueReg = ToRegister(ins->getValueReg());
 
+    Label haveValue;
+    if (ins->mir()->valueMayBeInSlot()) {
+        size_t slot = ins->mir()->domMemberSlotIndex();
+        // It's a bit annoying to redo these slot calculations, which duplcate
+        // LSlots and a few other things like that, but I'm not sure there's a
+        // way to reuse those here.
+        if (slot < JSObject::MAX_FIXED_SLOTS) {
+            masm.loadValue(Address(ObjectReg, JSObject::getFixedSlotOffset(slot)),
+                           JSReturnOperand);
+        } else {
+            // It's a dynamic slot.
+            slot -= JSObject::MAX_FIXED_SLOTS;
+            // Use PrivateReg as a scratch register for the slots pointer.
+            masm.loadPtr(Address(ObjectReg, JSObject::offsetOfSlots()),
+                         PrivateReg);
+            masm.loadValue(Address(PrivateReg, slot*sizeof(js::Value)),
+                           JSReturnOperand);
+        }
+        masm.branchTestUndefined(Assembler::NotEqual, JSReturnOperand, &haveValue);
+    }
+
     DebugOnly<uint32_t> initialStack = masm.framePushed();
 
     masm.checkStackAlignment();
 
     // Make space for the outparam.  Pre-initialize it to UndefinedValue so we
     // can trace it at GC time.
     masm.Push(UndefinedValue());
     // We pass the pointer to our out param as an instance of
@@ -8372,16 +8393,18 @@ CodeGenerator::visitGetDOMProperty(LGetD
     } else {
         masm.branchIfFalseBool(ReturnReg, masm.exceptionLabel());
 
         masm.loadValue(Address(StackPointer, IonDOMExitFrameLayout::offsetOfResult()),</