Merge b2g-inbound to m-c a=merge
authorWes Kocher <wkocher@mozilla.com>
Fri, 27 Mar 2015 17:11:19 -0700
changeset 265035 ad587ca628cfc317941aa2c61b447226fbbd214a
parent 265010 5bc74f6fa5c8034bfb151efee6a622d472ea0acb (current diff)
parent 265034 bcc307ea64f495daebc40b65cb3d070ccf65205d (diff)
child 265036 41d4013c1462a3e98de46aeeca7efc39528267a6
child 265079 9511efa9a8ebab205ba24fa467179aaa3849f770
child 265162 21cfa00b88ddfd6d3247d80f01b63fad742f6e49
child 265194 21aa17588defe40c117cd4a47ad8d91008a720f6
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone39.0a1
first release with
nightly linux32
ad587ca628cf / 39.0a1 / 20150328030209 / files
nightly linux64
ad587ca628cf / 39.0a1 / 20150328030209 / files
nightly mac
ad587ca628cf / 39.0a1 / 20150328030209 / files
nightly win32
ad587ca628cf / 39.0a1 / 20150328030209 / files
nightly win64
ad587ca628cf / 39.0a1 / 20150328030209 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b2g-inbound to m-c a=merge
dom/ipc/PContent.ipdl
--- a/b2g/components/PaymentProviderStrategy.js
+++ b/b2g/components/PaymentProviderStrategy.js
@@ -6,19 +6,19 @@
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
 const PREF_DEBUG = "dom.payment.debug";
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
-                                   "@mozilla.org/ril/content-helper;1",
-                                   "nsIIccProvider");
+XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
+                                   "@mozilla.org/icc/iccservice;1",
+                                   "nsIIccService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gRil",
                                    "@mozilla.org/ril;1",
                                    "nsIRadioInterfaceLayer");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSettingsService",
                                    "@mozilla.org/settingsService;1",
                                    "nsISettingsService");
@@ -143,17 +143,18 @@ PaymentProviderStrategy.prototype = {
   set paymentServiceId(aServiceId) {
     this._settings.paymentServiceId = aServiceId;
   },
 
   get iccInfo() {
     if (!this._iccInfo) {
       this._iccInfo = [];
       for (let i = 0; i < gRil.numRadioInterfaces; i++) {
-        let info = iccProvider.getIccInfo(i);
+        let icc = gIccService.getIccByServiceId(i);
+        let info = icc && icc.iccInfo;
         if (!info) {
           LOGE("Tried to get the ICC info for an invalid service ID " + i);
           continue;
         }
 
         this._iccInfo.push({
           iccId: info.iccid,
           mcc: info.mcc,
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="527d1c939ee57deb7192166e56e2a3fffa8cb087"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="527d1c939ee57deb7192166e56e2a3fffa8cb087"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "9cc496cecc37d7a29f9279827cdf6e4891211f67", 
+        "git_revision": "0e7c8ade48129b3e03c5de8ae0452fd1f756535c", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "9e79307fd6bcade07847b92d42948a6a6a334f79", 
+    "revision": "97a01eae94361363300254b54e53e2ac0f0b9d38", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="9cc496cecc37d7a29f9279827cdf6e4891211f67"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="0e7c8ade48129b3e03c5de8ae0452fd1f756535c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="2aa4a75c63cd6e93870a8bddbba45f863cbfd9a3"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ed2cf97a6c37a4bbd0bbbbffe06ec7136d8c79ff"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <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="f5de61a5d8fdaa2db3d4e17e0c4212ec4d54a365"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -173,17 +173,16 @@
 @RESPATH@/components/dom_audiochannel.xpt
 @RESPATH@/components/dom_base.xpt
 @RESPATH@/components/dom_system.xpt
 #ifdef MOZ_WIDGET_GONK
 @RESPATH@/components/dom_wifi.xpt
 @RESPATH@/components/dom_system_gonk.xpt
 #endif
 #ifdef MOZ_B2G_RIL
-@RESPATH@/components/dom_icc.xpt
 @RESPATH@/components/dom_wappush.xpt
 @RESPATH@/components/dom_mobileconnection.xpt
 #endif
 #ifdef MOZ_B2G_BT
 @RESPATH@/components/dom_bluetooth.xpt
 #endif
 #ifdef MOZ_B2G_CAMERA
 @BINPATH@/components/dom_camera.xpt
@@ -213,16 +212,17 @@
 @RESPATH@/components/dom_power.xpt
 @RESPATH@/components/dom_quota.xpt
 @RESPATH@/components/dom_range.xpt
 @RESPATH@/components/dom_security.xpt
 @RESPATH@/components/dom_settings.xpt
 @RESPATH@/components/dom_permissionsettings.xpt
 @RESPATH@/components/dom_sidebar.xpt
 @RESPATH@/components/dom_cellbroadcast.xpt
+@RESPATH@/components/dom_icc.xpt
 @RESPATH@/components/dom_mobilemessage.xpt
 @RESPATH@/components/dom_storage.xpt
 @RESPATH@/components/dom_stylesheets.xpt
 @RESPATH@/components/dom_telephony.xpt
 @RESPATH@/components/dom_threads.xpt
 @RESPATH@/components/dom_traversal.xpt
 @RESPATH@/components/dom_tv.xpt
 @RESPATH@/components/dom_views.xpt
@@ -478,16 +478,18 @@
 @RESPATH@/components/ResourceStatsManager.js
 @RESPATH@/components/ResourceStatsManager.manifest
 #endif // MOZ_WIDGET_GONK
 
 ; RIL
 #if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
 @RESPATH@/components/CellBroadcastService.js
 @RESPATH@/components/CellBroadcastService.manifest
+@BINPATH@/components/IccService.js
+@BINPATH@/components/IccService.manifest
 @RESPATH@/components/MmsService.js
 @RESPATH@/components/MmsService.manifest
 @RESPATH@/components/MobileMessageDatabaseService.js
 @RESPATH@/components/MobileMessageDatabaseService.manifest
 #ifndef DISABLE_MOZ_RIL_GEOLOC
 @RESPATH@/components/MobileConnectionService.js
 @RESPATH@/components/MobileConnectionService.manifest
 @RESPATH@/components/RadioInterfaceLayer.js
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -210,16 +210,17 @@
 @RESPATH@/components/dom_css.xpt
 @RESPATH@/components/dom_devicestorage.xpt
 @RESPATH@/components/dom_events.xpt
 @RESPATH@/components/dom_geolocation.xpt
 @RESPATH@/components/dom_media.xpt
 @RESPATH@/components/dom_network.xpt
 @RESPATH@/components/dom_notification.xpt
 @RESPATH@/components/dom_html.xpt
+@RESPATH@/components/dom_icc.xpt
 @RESPATH@/components/dom_offline.xpt
 @RESPATH@/components/dom_json.xpt
 @RESPATH@/components/dom_power.xpt
 @RESPATH@/components/dom_quota.xpt
 @RESPATH@/components/dom_range.xpt
 @RESPATH@/components/dom_security.xpt
 @RESPATH@/components/dom_settings.xpt
 @RESPATH@/components/dom_permissionsettings.xpt
--- a/dom/apps/OperatorApps.jsm
+++ b/dom/apps/OperatorApps.jsm
@@ -16,19 +16,19 @@ Cu.import("resource://gre/modules/Webapp
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 
 let Path = OS.Path;
 
 #ifdef MOZ_B2G_RIL
-XPCOMUtils.defineLazyServiceGetter(this, "iccProvider",
-                                   "@mozilla.org/ril/content-helper;1",
-                                   "nsIIccProvider");
+XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
+                                   "@mozilla.org/icc/iccservice;1",
+                                   "nsIIccService");
 #endif
 
 function debug(aMsg) {
   //dump("-*-*- OperatorApps.jsm : " + aMsg + "\n");
 }
 
 // Single Variant source dir will be set in PREF_SINGLE_VARIANT_DIR
 // preference.
@@ -64,27 +64,28 @@ let iccListener = {
   notifyStkCommand: function() {},
 
   notifyStkSessionEnd: function() {},
 
   notifyCardStateChanged: function() {},
 
   notifyIccInfoChanged: function() {
     // TODO: Bug 927709 - OperatorApps for multi-sim
-    // In Multi-sim, there is more than one client in iccProvider. Each
-    // client represents a icc service. To maintain the backward compatibility
+    // In Multi-sim, there is more than one client in IccService. Each
+    // client represents a icc handle. To maintain the backward compatibility
     // with single sim, we always use client 0 for now. Adding support for
     // multiple sim will be addressed in bug 927709, if needed.
     let clientId = 0;
-    let iccInfo = iccProvider.getIccInfo(clientId);
+    let icc = gIccService.getIccByServiceId(clientId);
+    let iccInfo = icc && icc.iccInfo;
     if (iccInfo && iccInfo.mcc && iccInfo.mnc) {
       let mcc = iccInfo.mcc;
       let mnc = iccInfo.mnc;
       debug("******* iccListener cardIccInfo MCC-MNC: " + mcc + "-" + mnc);
-      iccProvider.unregisterIccMsg(clientId, this);
+      icc.unregisterListener(this);
       OperatorAppsRegistry._installOperatorApps(mcc, mnc);
 
       debug("Broadcast message first-run-with-sim");
       let messenger = Cc["@mozilla.org/system-message-internal;1"]
                         .getService(Ci.nsISystemMessagesInternal);
       messenger.broadcastMessage("first-run-with-sim", { mcc: mcc,
                                                          mnc: mnc });
     }
@@ -100,40 +101,41 @@ this.OperatorAppsRegistry = {
     debug("init");
 #ifdef MOZ_B2G_RIL
     if (isFirstRunWithSIM()) {
       debug("First Run with SIM");
       Task.spawn(function() {
         try {
           yield this._initializeSourceDir();
           // TODO: Bug 927709 - OperatorApps for multi-sim
-          // In Multi-sim, there is more than one client in iccProvider. Each
-          // client represents a icc service. To maintain the backward
+          // In Multi-sim, there is more than one client in IccService. Each
+          // client represents a icc handle. To maintain the backward
           // compatibility with single sim, we always use client 0 for now.
           // Adding support for multiple sim will be addressed in bug 927709, if
           // needed.
           let clientId = 0;
-          let iccInfo = iccProvider.getIccInfo(clientId);
+          let icc = gIccService.getIccByServiceId(clientId);
+          let iccInfo = icc && icc.iccInfo;
           let mcc = 0;
           let mnc = 0;
           if (iccInfo && iccInfo.mcc) {
             mcc = iccInfo.mcc;
           }
           if (iccInfo && iccInfo.mnc) {
             mnc = iccInfo.mnc;
           }
           if (mcc && mnc) {
             this._installOperatorApps(mcc, mnc);
             let messenger = Cc["@mozilla.org/system-message-internal;1"]
                               .getService(Ci.nsISystemMessagesInternal);
             messenger.broadcastMessage("first-run-with-sim", { mcc: mcc,
                                                                mnc: mnc });
 
           } else {
-            iccProvider.registerIccMsg(clientId, iccListener);
+            icc.registerListener(iccListener);
           }
         } catch (e) {
           debug("Error Initializing OperatorApps. " + e);
         }
       }.bind(this));
     } else {
       debug("No First Run with SIM");
     }
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -31,16 +31,17 @@
 #include "nsUnicharUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 #include "BatteryManager.h"
 #include "mozilla/dom/PowerManager.h"
 #include "mozilla/dom/WakeLock.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/CellBroadcast.h"
+#include "mozilla/dom/IccManager.h"
 #include "mozilla/dom/MobileMessageManager.h"
 #include "mozilla/dom/ServiceWorkerContainer.h"
 #include "mozilla/dom/Telephony.h"
 #include "mozilla/dom/Voicemail.h"
 #include "mozilla/dom/TVManager.h"
 #include "mozilla/dom/VRDevice.h"
 #include "mozilla/Hal.h"
 #include "nsISiteSpecificUserAgent.h"
@@ -48,17 +49,16 @@
 #include "mozilla/StaticPtr.h"
 #include "Connection.h"
 #include "mozilla/dom/Event.h" // for nsIDOMEvent::InternalDOMEvent()
 #include "nsGlobalWindow.h"
 #ifdef MOZ_B2G
 #include "nsIMobileIdentityService.h"
 #endif
 #ifdef MOZ_B2G_RIL
-#include "mozilla/dom/IccManager.h"
 #include "mozilla/dom/MobileConnectionArray.h"
 #endif
 #include "nsIIdleObserver.h"
 #include "nsIPermissionManager.h"
 #include "nsMimeTypes.h"
 #include "nsNetUtil.h"
 #include "nsIHttpChannel.h"
 #include "nsIHttpChannelInternal.h"
@@ -172,24 +172,24 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Navigator)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPlugins)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMimeTypes)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGeolocation)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNotification)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBatteryManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPowerManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCellBroadcast)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileMessageManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTelephony)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoicemail)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTVManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mConnection)
 #ifdef MOZ_B2G_RIL
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMobileConnections)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccManager)
 #endif
 #ifdef MOZ_B2G_BT
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBluetooth)
 #endif
 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAudioChannelManager)
 #endif
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCameraManager)
@@ -245,16 +245,21 @@ Navigator::Invalidate()
     mPowerManager->Shutdown();
     mPowerManager = nullptr;
   }
 
   if (mCellBroadcast) {
     mCellBroadcast = nullptr;
   }
 
+  if (mIccManager) {
+    mIccManager->Shutdown();
+    mIccManager = nullptr;
+  }
+
   if (mMobileMessageManager) {
     mMobileMessageManager->Shutdown();
     mMobileMessageManager = nullptr;
   }
 
   if (mTelephony) {
     mTelephony = nullptr;
   }
@@ -272,21 +277,16 @@ Navigator::Invalidate()
     mConnection->Shutdown();
     mConnection = nullptr;
   }
 
 #ifdef MOZ_B2G_RIL
   if (mMobileConnections) {
     mMobileConnections = nullptr;
   }
-
-  if (mIccManager) {
-    mIccManager->Shutdown();
-    mIccManager = nullptr;
-  }
 #endif
 
 #ifdef MOZ_B2G_BT
   if (mBluetooth) {
     mBluetooth = nullptr;
   }
 #endif
 
@@ -1702,34 +1702,31 @@ Navigator::GetMozVoicemail(ErrorResult& 
     }
 
     mVoicemail = Voicemail::Create(mWindow, aRv);
   }
 
   return mVoicemail;
 }
 
-#ifdef MOZ_B2G_RIL
-
 IccManager*
 Navigator::GetMozIccManager(ErrorResult& aRv)
 {
   if (!mIccManager) {
     if (!mWindow) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
       return nullptr;
     }
     NS_ENSURE_TRUE(mWindow->GetDocShell(), nullptr);
 
     mIccManager = new IccManager(mWindow);
   }
 
   return mIccManager;
 }
-#endif // MOZ_B2G_RIL
 
 #ifdef MOZ_GAMEPAD
 void
 Navigator::GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads,
                        ErrorResult& aRv)
 {
   if (!mWindow) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -39,20 +39,16 @@ class MediaDevices;
 struct MediaStreamConstraints;
 class WakeLock;
 class ArrayBufferViewOrBlobOrStringOrFormData;
 struct MobileIdOptions;
 class ServiceWorkerContainer;
 }
 }
 
-#ifdef MOZ_B2G_RIL
-class nsIDOMMozIccManager;
-#endif // MOZ_B2G_RIL
-
 //*****************************************************************************
 // Navigator: Script "navigator" object
 //*****************************************************************************
 
 namespace mozilla {
 namespace dom {
 
 namespace battery {
@@ -83,22 +79,22 @@ class Connection;
 
 #ifdef MOZ_B2G_BT
 namespace bluetooth {
 class BluetoothManager;
 } // namespace bluetooth
 #endif // MOZ_B2G_BT
 
 #ifdef MOZ_B2G_RIL
-class IccManager;
 class MobileConnectionArray;
 #endif
 
 class PowerManager;
 class CellBroadcast;
+class IccManager;
 class Telephony;
 class Voicemail;
 class TVManager;
 
 namespace time {
 class TimeManager;
 } // namespace time
 
@@ -219,16 +215,17 @@ public:
                                              ErrorResult& aRv);
   nsDOMDeviceStorage* GetDeviceStorage(const nsAString& aType,
                                        ErrorResult& aRv);
   void GetDeviceStorages(const nsAString& aType,
                          nsTArray<nsRefPtr<nsDOMDeviceStorage> >& aStores,
                          ErrorResult& aRv);
   DesktopNotificationCenter* GetMozNotification(ErrorResult& aRv);
   CellBroadcast* GetMozCellBroadcast(ErrorResult& aRv);
+  IccManager* GetMozIccManager(ErrorResult& aRv);
   MobileMessageManager* GetMozMobileMessage();
   Telephony* GetMozTelephony(ErrorResult& aRv);
   Voicemail* GetMozVoicemail(ErrorResult& aRv);
   TVManager* GetTv();
   network::Connection* GetConnection(ErrorResult& aRv);
   nsDOMCameraManager* GetMozCameras(ErrorResult& aRv);
   MediaDevices* GetMediaDevices(ErrorResult& aRv);
   void MozSetMessageHandler(const nsAString& aType,
@@ -238,17 +235,16 @@ public:
   void MozSetMessageHandlerPromise(Promise& aPromise, ErrorResult& aRv);
 
 #ifdef MOZ_B2G
   already_AddRefed<Promise> GetMobileIdAssertion(const MobileIdOptions& options,
                                                  ErrorResult& aRv);
 #endif
 #ifdef MOZ_B2G_RIL
   MobileConnectionArray* GetMozMobileConnections(ErrorResult& aRv);
-  IccManager* GetMozIccManager(ErrorResult& aRv);
 #endif // MOZ_B2G_RIL
 #ifdef MOZ_GAMEPAD
   void GetGamepads(nsTArray<nsRefPtr<Gamepad> >& aGamepads, ErrorResult& aRv);
 #endif // MOZ_GAMEPAD
   already_AddRefed<Promise> GetVRDevices(ErrorResult& aRv);
 #ifdef MOZ_B2G_FM
   FMRadio* GetMozFMRadio(ErrorResult& aRv);
 #endif
@@ -348,24 +344,24 @@ private:
   nsRefPtr<Geolocation> mGeolocation;
   nsRefPtr<DesktopNotificationCenter> mNotification;
   nsRefPtr<battery::BatteryManager> mBatteryManager;
 #ifdef MOZ_B2G_FM
   nsRefPtr<FMRadio> mFMRadio;
 #endif
   nsRefPtr<PowerManager> mPowerManager;
   nsRefPtr<CellBroadcast> mCellBroadcast;
+  nsRefPtr<IccManager> mIccManager;
   nsRefPtr<MobileMessageManager> mMobileMessageManager;
   nsRefPtr<Telephony> mTelephony;
   nsRefPtr<Voicemail> mVoicemail;
   nsRefPtr<TVManager> mTVManager;
   nsRefPtr<network::Connection> mConnection;
 #ifdef MOZ_B2G_RIL
   nsRefPtr<MobileConnectionArray> mMobileConnections;
-  nsRefPtr<IccManager> mIccManager;
 #endif
 #ifdef MOZ_B2G_BT
   nsRefPtr<bluetooth::BluetoothManager> mBluetooth;
 #endif
 #ifdef MOZ_AUDIO_CHANNEL_MANAGER
   nsRefPtr<system::AudioChannelManager> mAudioChannelManager;
 #endif
   nsRefPtr<nsDOMCameraManager> mCameraManager;
--- a/dom/bluetooth/BluetoothRilListener.cpp
+++ b/dom/bluetooth/BluetoothRilListener.cpp
@@ -2,22 +2,21 @@
 /* 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 "BluetoothRilListener.h"
 
 #include "BluetoothHfpManager.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsITelephonyCallInfo.h"
 #include "nsITelephonyService.h"
-#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID.
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 /**
  *  IccListener
  */
@@ -55,25 +54,29 @@ IccListener::NotifyCardStateChanged()
   return NS_OK;
 }
 
 bool
 IccListener::Listen(bool aStart)
 {
   NS_ENSURE_TRUE(mOwner, false);
 
-  nsCOMPtr<nsIIccProvider> provider =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, false);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, false);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(mOwner->mClientId, getter_AddRefs(icc));
+  NS_ENSURE_TRUE(icc, false);
 
   nsresult rv;
   if (aStart) {
-    rv = provider->RegisterIccMsg(mOwner->mClientId, this);
+    rv = icc->RegisterListener(this);
   } else {
-    rv = provider->UnregisterIccMsg(mOwner->mClientId, this);
+    rv = icc->UnregisterListener(this);
   }
 
   return NS_SUCCEEDED(rv);
 }
 
 void
 IccListener::SetOwner(BluetoothRilListener *aOwner)
 {
--- a/dom/bluetooth/BluetoothRilListener.h
+++ b/dom/bluetooth/BluetoothRilListener.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_bluetooth_bluetoothrillistener_h__
 #define mozilla_dom_bluetooth_bluetoothrillistener_h__
 
 #include "BluetoothCommon.h"
 
 #include "nsAutoPtr.h"
 
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionService.h"
 #include "nsITelephonyCallInfo.h"
 #include "nsITelephonyService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothRilListener;
 
--- a/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothA2dpManager.cpp
@@ -21,16 +21,18 @@
 
 using namespace mozilla;
 USING_BLUETOOTH_NAMESPACE
 // AVRC_ID op code follows bluedroid avrc_defs.h
 #define AVRC_ID_REWIND  0x48
 #define AVRC_ID_FAST_FOR 0x49
 #define AVRC_KEY_PRESS_STATE  1
 #define AVRC_KEY_RELEASE_STATE  0
+// bluedroid bt_rc.h
+#define AVRC_MAX_ATTR_STR_LEN 255
 
 namespace {
   StaticRefPtr<BluetoothA2dpManager> sBluetoothA2dpManager;
   bool sInShutdown = false;
   static BluetoothA2dpInterface* sBtA2dpInterface;
   static BluetoothAvrcpInterface* sBtAvrcpInterface;
 } // anonymous namespace
 
@@ -42,22 +44,37 @@ ConvertAttributeString(BluetoothAvrcpMed
                        nsAString& aAttrStr)
 {
   BluetoothA2dpManager* a2dp = BluetoothA2dpManager::Get();
   NS_ENSURE_TRUE_VOID(a2dp);
 
   switch (aAttrId) {
     case AVRCP_MEDIA_ATTRIBUTE_TITLE:
       a2dp->GetTitle(aAttrStr);
+      /*
+       * bluedroid can only send string length AVRC_MAX_ATTR_STR_LEN - 1
+       */
+      if (aAttrStr.Length() >= AVRC_MAX_ATTR_STR_LEN) {
+        aAttrStr.Truncate(AVRC_MAX_ATTR_STR_LEN - 1);
+        BT_WARNING("Truncate media item attribute title, length is over 255");
+      }
       break;
     case AVRCP_MEDIA_ATTRIBUTE_ARTIST:
       a2dp->GetArtist(aAttrStr);
+      if (aAttrStr.Length() >= AVRC_MAX_ATTR_STR_LEN) {
+        aAttrStr.Truncate(AVRC_MAX_ATTR_STR_LEN - 1);
+        BT_WARNING("Truncate media item attribute artist, length is over 255");
+      }
       break;
     case AVRCP_MEDIA_ATTRIBUTE_ALBUM:
       a2dp->GetAlbum(aAttrStr);
+      if (aAttrStr.Length() >= AVRC_MAX_ATTR_STR_LEN) {
+        aAttrStr.Truncate(AVRC_MAX_ATTR_STR_LEN - 1);
+        BT_WARNING("Truncate media item attribute album, length is over 255");
+      }
       break;
     case AVRCP_MEDIA_ATTRIBUTE_TRACK_NUM:
       aAttrStr.AppendInt(a2dp->GetMediaNumber());
       break;
     case AVRCP_MEDIA_ATTRIBUTE_NUM_TRACKS:
       aAttrStr.AppendInt(a2dp->GetTotalMediaNumber());
       break;
     case AVRCP_MEDIA_ATTRIBUTE_GENRE:
--- a/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -12,24 +12,23 @@
 
 #include "jsapi.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsContentUtils.h"
 #include "nsIAudioManager.h"
 #include "nsIIccInfo.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsIMobileNetworkInfo.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsITelephonyService.h"
-#include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/SettingChangeNotificationBinding.h"
 
 #define MOZSETTINGS_CHANGED_ID               "mozsettings-changed"
 #define AUDIO_VOLUME_BT_SCO_ID               "audio.volume.bt_sco"
 
@@ -721,22 +720,26 @@ BluetoothHfpManager::HandleVoiceConnecti
     BT_WARNING("The operator name was longer than 16 characters. We cut it.");
     mOperatorName.Left(mOperatorName, 16);
   }
 }
 
 void
 BluetoothHfpManager::HandleIccInfoChanged(uint32_t aClientId)
 {
-  nsCOMPtr<nsIIccProvider> icc =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(aClientId, getter_AddRefs(icc));
   NS_ENSURE_TRUE_VOID(icc);
 
   nsCOMPtr<nsIIccInfo> iccInfo;
-  icc->GetIccInfo(aClientId, getter_AddRefs(iccInfo));
+  icc->GetIccInfo(getter_AddRefs(iccInfo));
   NS_ENSURE_TRUE_VOID(iccInfo);
 
   nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
   NS_ENSURE_TRUE_VOID(gsmIccInfo);
   gsmIccInfo->GetMsisdn(mMsisdn);
 }
 
 void
--- a/dom/bluetooth/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth/bluez/BluetoothHfpManager.cpp
@@ -23,22 +23,21 @@
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/SettingChangeNotificationBinding.h"
 
 #ifdef MOZ_B2G_RIL
 #include "nsIIccInfo.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsIMobileNetworkInfo.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
 #define BSRF_BIT_EC_NR_FUNCTION            (1 << 1)
@@ -659,22 +658,26 @@ BluetoothHfpManager::HandleVoiceConnecti
     BT_WARNING("The operator name was longer than 16 characters. We cut it.");
     mOperatorName.Left(mOperatorName, 16);
   }
 }
 
 void
 BluetoothHfpManager::HandleIccInfoChanged(uint32_t aClientId)
 {
-  nsCOMPtr<nsIIccProvider> icc =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(aClientId, getter_AddRefs(icc));
   NS_ENSURE_TRUE_VOID(icc);
 
   nsCOMPtr<nsIIccInfo> iccInfo;
-  icc->GetIccInfo(aClientId, getter_AddRefs(iccInfo));
+  icc->GetIccInfo(getter_AddRefs(iccInfo));
   NS_ENSURE_TRUE_VOID(iccInfo);
 
   nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
   NS_ENSURE_TRUE_VOID(gsmIccInfo);
   gsmIccInfo->GetMsisdn(mMsisdn);
 }
 #endif // MOZ_B2G_RIL
 
--- a/dom/bluetooth2/BluetoothRilListener.cpp
+++ b/dom/bluetooth2/BluetoothRilListener.cpp
@@ -2,21 +2,20 @@
 /* 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 "BluetoothRilListener.h"
 
 #include "BluetoothHfpManager.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsITelephonyService.h"
-#include "nsRadioInterfaceLayer.h" // For NS_RILCONTENTHELPER_CONTRACTID.
 #include "nsServiceManagerUtils.h"
 #include "nsString.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 /**
  *  IccListener
  */
@@ -54,25 +53,29 @@ IccListener::NotifyCardStateChanged()
   return NS_OK;
 }
 
 bool
 IccListener::Listen(bool aStart)
 {
   NS_ENSURE_TRUE(mOwner, false);
 
-  nsCOMPtr<nsIIccProvider> provider =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
-  NS_ENSURE_TRUE(provider, false);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(service, false);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(mOwner->mClientId, getter_AddRefs(icc));
+  NS_ENSURE_TRUE(icc, false);
 
   nsresult rv;
   if (aStart) {
-    rv = provider->RegisterIccMsg(mOwner->mClientId, this);
+    rv = icc->RegisterListener(this);
   } else {
-    rv = provider->UnregisterIccMsg(mOwner->mClientId, this);
+    rv = icc->UnregisterListener(this);
   }
 
   return NS_SUCCEEDED(rv);
 }
 
 void
 IccListener::SetOwner(BluetoothRilListener *aOwner)
 {
--- a/dom/bluetooth2/BluetoothRilListener.h
+++ b/dom/bluetooth2/BluetoothRilListener.h
@@ -6,17 +6,17 @@
 
 #ifndef mozilla_dom_bluetooth_bluetoothrillistener_h__
 #define mozilla_dom_bluetooth_bluetoothrillistener_h__
 
 #include "BluetoothCommon.h"
 
 #include "nsAutoPtr.h"
 
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionService.h"
 #include "nsITelephonyCallInfo.h"
 #include "nsITelephonyService.h"
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothRilListener;
 
--- a/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluedroid/hfp/BluetoothHfpManager.cpp
@@ -12,24 +12,23 @@
 
 #include "jsapi.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "nsContentUtils.h"
 #include "nsIAudioManager.h"
 #include "nsIIccInfo.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsIMobileNetworkInfo.h"
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsITelephonyService.h"
-#include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/SettingChangeNotificationBinding.h"
 
 #define MOZSETTINGS_CHANGED_ID               "mozsettings-changed"
 #define AUDIO_VOLUME_BT_SCO_ID               "audio.volume.bt_sco"
 
@@ -705,22 +704,26 @@ BluetoothHfpManager::HandleVoiceConnecti
     BT_WARNING("The operator name was longer than 16 characters. We cut it.");
     mOperatorName.Left(mOperatorName, 16);
   }
 }
 
 void
 BluetoothHfpManager::HandleIccInfoChanged(uint32_t aClientId)
 {
-  nsCOMPtr<nsIIccProvider> icc =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(aClientId, getter_AddRefs(icc));
   NS_ENSURE_TRUE_VOID(icc);
 
   nsCOMPtr<nsIIccInfo> iccInfo;
-  icc->GetIccInfo(aClientId, getter_AddRefs(iccInfo));
+  icc->GetIccInfo(getter_AddRefs(iccInfo));
   NS_ENSURE_TRUE_VOID(iccInfo);
 
   nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
   NS_ENSURE_TRUE_VOID(gsmIccInfo);
   gsmIccInfo->GetMsisdn(mMsisdn);
 }
 
 void
--- a/dom/bluetooth2/bluez/BluetoothHfpManager.cpp
+++ b/dom/bluetooth2/bluez/BluetoothHfpManager.cpp
@@ -23,22 +23,21 @@
 #include "nsIObserverService.h"
 #include "nsISettingsService.h"
 #include "nsServiceManagerUtils.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/SettingChangeNotificationBinding.h"
 
 #ifdef MOZ_B2G_RIL
 #include "nsIIccInfo.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionInfo.h"
 #include "nsIMobileConnectionService.h"
 #include "nsIMobileNetworkInfo.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
 #define BSRF_BIT_EC_NR_FUNCTION            (1 << 1)
@@ -659,22 +658,26 @@ BluetoothHfpManager::HandleVoiceConnecti
     BT_WARNING("The operator name was longer than 16 characters. We cut it.");
     mOperatorName.Left(mOperatorName, 16);
   }
 }
 
 void
 BluetoothHfpManager::HandleIccInfoChanged(uint32_t aClientId)
 {
-  nsCOMPtr<nsIIccProvider> icc =
-    do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE_VOID(service);
+
+  nsCOMPtr<nsIIcc> icc;
+  service->GetIccByServiceId(aClientId, getter_AddRefs(icc));
   NS_ENSURE_TRUE_VOID(icc);
 
   nsCOMPtr<nsIIccInfo> iccInfo;
-  icc->GetIccInfo(aClientId, getter_AddRefs(iccInfo));
+  icc->GetIccInfo(getter_AddRefs(iccInfo));
   NS_ENSURE_TRUE_VOID(iccInfo);
 
   nsCOMPtr<nsIGsmIccInfo> gsmIccInfo = do_QueryInterface(iccInfo);
   NS_ENSURE_TRUE_VOID(gsmIccInfo);
   gsmIccInfo->GetMsisdn(mMsisdn);
 }
 #endif // MOZ_B2G_RIL
 
--- a/dom/icc/Assertions.cpp
+++ b/dom/icc/Assertions.cpp
@@ -1,22 +1,22 @@
 /* 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/MozIccBinding.h"
-#include "nsIIccProvider.h"
+#include "nsIIccService.h"
 
 namespace mozilla {
 namespace dom {
 namespace icc {
 
 #define ASSERT_EQUALITY(webidlType, webidlState, xpidlState) \
-  static_assert(static_cast<uint32_t>(webidlType::webidlState) == nsIIccProvider::xpidlState, \
-  #webidlType "::" #webidlState " should equal to nsIIccProvider::" #xpidlState)
+  static_assert(static_cast<uint32_t>(webidlType::webidlState) == nsIIcc::xpidlState, \
+  #webidlType "::" #webidlState " should equal to nsIIccService::" #xpidlState)
 
 /**
  * Enum IccCardState
  */
 #define ASSERT_ICC_CARD_STATE_EQUALITY(webidlState, xpidlState) \
   ASSERT_EQUALITY(IccCardState, webidlState, xpidlState)
 
 ASSERT_ICC_CARD_STATE_EQUALITY(Unknown, CARD_STATE_UNKNOWN);
--- a/dom/icc/Icc.cpp
+++ b/dom/icc/Icc.cpp
@@ -1,25 +1,29 @@
 /* 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/Icc.h"
 
+#include "IccCallback.h"
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/IccInfo.h"
 #include "mozilla/dom/MozStkCommandEvent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsIIccInfo.h"
 #include "nsIIccProvider.h"
+#include "nsIIccService.h"
 #include "nsJSON.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 
+using mozilla::dom::icc::IccCallback;
+
 namespace mozilla {
 namespace dom {
 
 namespace {
 
 bool
 IsPukCardLockType(IccLockType aLockType)
 {
@@ -45,19 +49,20 @@ IsPukCardLockType(IccLockType aLockType)
 NS_IMPL_CYCLE_COLLECTION_INHERITED(Icc, DOMEventTargetHelper, mIccInfo)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(Icc)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
 NS_IMPL_ADDREF_INHERITED(Icc, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(Icc, DOMEventTargetHelper)
 
-Icc::Icc(nsPIDOMWindow* aWindow, long aClientId, nsIIccInfo* aIccInfo)
+Icc::Icc(nsPIDOMWindow* aWindow, long aClientId, nsIIcc* aHandler, nsIIccInfo* aIccInfo)
   : mLive(true)
   , mClientId(aClientId)
+  , mHandler(aHandler)
 {
   BindToOwner(aWindow);
 
   mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
 
   if (aIccInfo) {
     aIccInfo->GetIccid(mIccId);
     UpdateIccInfo(aIccInfo);
@@ -74,16 +79,17 @@ Icc::~Icc()
 {
 }
 
 void
 Icc::Shutdown()
 {
   mIccInfo.SetNull();
   mProvider = nullptr;
+  mHandler = nullptr;
   mLive = false;
 }
 
 nsresult
 Icc::NotifyEvent(const nsAString& aName)
 {
   return DispatchTrustedEvent(aName);
 }
@@ -165,20 +171,20 @@ Icc::GetIccInfo(Nullable<OwningMozIccInf
   aIccInfo = mIccInfo;
 }
 
 Nullable<IccCardState>
 Icc::GetCardState() const
 {
   Nullable<IccCardState> result;
 
-  uint32_t cardState = nsIIccProvider::CARD_STATE_UNDETECTED;
-  if (mProvider &&
-      NS_SUCCEEDED(mProvider->GetCardState(mClientId, &cardState)) &&
-      cardState != nsIIccProvider::CARD_STATE_UNDETECTED) {
+  uint32_t cardState = nsIIcc::CARD_STATE_UNDETECTED;
+  if (mHandler &&
+      NS_SUCCEEDED(mHandler->GetCardState(&cardState)) &&
+      cardState != nsIIcc::CARD_STATE_UNDETECTED) {
     MOZ_ASSERT(cardState < static_cast<uint32_t>(IccCardState::EndGuard_));
     result.SetValue(static_cast<IccCardState>(cardState));
   }
 
   return result;
 }
 
 void
@@ -244,110 +250,117 @@ Icc::SendStkEventDownload(const JSContex
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
 already_AddRefed<DOMRequest>
 Icc::GetCardLock(IccLockType aLockType, ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<nsIDOMDOMRequest> request;
-  nsresult rv = mProvider->GetCardLockEnabled(mClientId, GetOwner(),
-                                              static_cast<uint32_t>(aLockType),
-                                              getter_AddRefs(request));
+  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
+  // TODO: Bug 1125018 - Simplify The Result of GetCardLock and
+  // getCardLockRetryCount in MozIcc.webidl without a wrapper object.
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), request, true);
+  nsresult rv = mHandler->GetCardLockEnabled(static_cast<uint32_t>(aLockType),
+                                             requestCallback);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  return request.forget().downcast<DOMRequest>();
+  return request.forget();
 }
 
 already_AddRefed<DOMRequest>
 Icc::UnlockCardLock(const IccUnlockCardLockOptions& aOptions, ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<nsIDOMDOMRequest> request;
+  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), request);
   const nsString& password = IsPukCardLockType(aOptions.mLockType)
                            ? aOptions.mPuk : aOptions.mPin;
-  nsresult rv = mProvider->UnlockCardLock(mClientId, GetOwner(),
-                                          static_cast<uint32_t>(aOptions.mLockType),
-                                          password, aOptions.mNewPin,
-                                          getter_AddRefs(request));
+  nsresult rv =
+    mHandler->UnlockCardLock(static_cast<uint32_t>(aOptions.mLockType),
+                             password, aOptions.mNewPin, requestCallback);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  return request.forget().downcast<DOMRequest>();
+  return request.forget();
 }
 
 already_AddRefed<DOMRequest>
 Icc::SetCardLock(const IccSetCardLockOptions& aOptions, ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
   nsresult rv;
-  nsRefPtr<nsIDOMDOMRequest> request;
+  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), request);
 
   if (aOptions.mEnabled.WasPassed()) {
     // Enable card lock.
     const nsString& password = (aOptions.mLockType == IccLockType::Fdn) ?
                                aOptions.mPin2 : aOptions.mPin;
 
-    rv = mProvider->SetCardLockEnabled(mClientId, GetOwner(),
-                                       static_cast<uint32_t>(aOptions.mLockType),
-                                       password, aOptions.mEnabled.Value(),
-                                       getter_AddRefs(request));
+    rv =
+      mHandler->SetCardLockEnabled(static_cast<uint32_t>(aOptions.mLockType),
+                                   password, aOptions.mEnabled.Value(),
+                                   requestCallback);
   } else {
     // Change card lock password.
-    rv = mProvider->ChangeCardLockPassword(mClientId, GetOwner(),
-                                           static_cast<uint32_t>(aOptions.mLockType),
-                                           aOptions.mPin, aOptions.mNewPin,
-                                           getter_AddRefs(request));
+    rv =
+      mHandler->ChangeCardLockPassword(static_cast<uint32_t>(aOptions.mLockType),
+                                       aOptions.mPin, aOptions.mNewPin,
+                                       requestCallback);
   }
 
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  return request.forget().downcast<DOMRequest>();
+  return request.forget();
 }
 
 already_AddRefed<DOMRequest>
 Icc::GetCardLockRetryCount(IccLockType aLockType, ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<nsIDOMDOMRequest> request;
-  nsresult rv = mProvider->GetCardLockRetryCount(mClientId, GetOwner(),
-                                                 static_cast<uint32_t>(aLockType),
-                                                 getter_AddRefs(request));
+  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), request);
+  nsresult rv = mHandler->GetCardLockRetryCount(static_cast<uint32_t>(aLockType),
+                                                requestCallback);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  return request.forget().downcast<DOMRequest>();
+  return request.forget();
 }
 
 already_AddRefed<DOMRequest>
 Icc::ReadContacts(IccContactType aContactType, ErrorResult& aRv)
 {
   if (!mProvider) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
@@ -387,48 +400,61 @@ Icc::UpdateContact(const JSContext* aCx,
 
   return request.forget().downcast<DOMRequest>();
 }
 
 already_AddRefed<DOMRequest>
 Icc::MatchMvno(IccMvnoType aMvnoType, const nsAString& aMvnoData,
                ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsRefPtr<nsIDOMDOMRequest> request;
-  nsresult rv = mProvider->MatchMvno(mClientId, GetOwner(),
-                                     static_cast<uint32_t>(aMvnoType),
-                                     aMvnoData, getter_AddRefs(request));
+  nsRefPtr<DOMRequest> request = new DOMRequest(GetOwner());
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), request);
+  nsresult rv = mHandler->MatchMvno(static_cast<uint32_t>(aMvnoType),
+                                    aMvnoData, requestCallback);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
-  return request.forget().downcast<DOMRequest>();
+  return request.forget();
 }
 
 already_AddRefed<Promise>
 Icc::GetServiceState(IccService aService, ErrorResult& aRv)
 {
-  if (!mProvider) {
+  if (!mHandler) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
 
-  nsCOMPtr<nsISupports> supports;
-  nsresult rv = mProvider->GetServiceState(mClientId, GetOwner(),
-                                           static_cast<uint32_t>(aService),
-                                           getter_AddRefs(supports));
-  if (NS_FAILED(rv)) {
-    aRv.Throw(rv);
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetOwner());
+  if (!global) {
+    return nullptr;
+  }
+
+  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
+  if (aRv.Failed()) {
     return nullptr;
   }
 
-  nsCOMPtr<Promise> promise = do_QueryInterface(supports);
+  nsRefPtr<IccCallback> requestCallback =
+    new IccCallback(GetOwner(), promise);
+
+  nsresult rv =
+    mHandler->GetServiceStateEnabled(static_cast<uint32_t>(aService),
+                                     requestCallback);
+
+  if (NS_FAILED(rv)) {
+    promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR);
+    // fall-through to return promise.
+  }
+
   return promise.forget();
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/icc/Icc.h
+++ b/dom/icc/Icc.h
@@ -3,16 +3,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Icc_h
 #define mozilla_dom_Icc_h
 
 #include "mozilla/dom/MozIccBinding.h"
 #include "mozilla/DOMEventTargetHelper.h"
 
+class nsIIcc;
 class nsIIccInfo;
 class nsIIccProvider;
 
 namespace mozilla {
 namespace dom {
 
 class DOMRequest;
 class OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo;
@@ -20,17 +21,18 @@ class Promise;
 
 class Icc final : public DOMEventTargetHelper
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(Icc, DOMEventTargetHelper)
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
 
-  Icc(nsPIDOMWindow* aWindow, long aClientId, nsIIccInfo* aIccInfo);
+  Icc(nsPIDOMWindow* aWindow, long aClientId,
+      nsIIcc* aHandler, nsIIccInfo* aIccInfo);
 
   void
   Shutdown();
 
   nsresult
   NotifyEvent(const nsAString& aName);
 
   nsresult
@@ -106,23 +108,29 @@ public:
   GetServiceState(IccService aService, ErrorResult& aRv);
 
   IMPL_EVENT_HANDLER(iccinfochange)
   IMPL_EVENT_HANDLER(cardstatechange)
   IMPL_EVENT_HANDLER(stkcommand)
   IMPL_EVENT_HANDLER(stksessionend)
 
 private:
+  // Put definition of the destructor in Icc.cpp to ensure forward declaration
+  // of nsIIccProvider, nsIIcc for the auto-generated .cpp file (i.e.,
+  // MozIccManagerBinding.cpp) that includes this header.
   ~Icc();
 
   bool mLive;
   uint32_t mClientId;
   nsString mIccId;
-  // mProvider is a xpcom service and will be released at shutdown, so it
+  // mProvider is a xpcom service and will be released at Shutdown(), so it
   // doesn't need to be cycle collected.
   nsCOMPtr<nsIIccProvider> mProvider;
+  // mHandler will be released at Shutdown(), so there is no need to join cycle
+  // collection.
+  nsCOMPtr<nsIIcc> mHandler;
   Nullable<OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo> mIccInfo;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_icc_Icc_h
new file mode 100644
--- /dev/null
+++ b/dom/icc/IccCallback.cpp
@@ -0,0 +1,135 @@
+/* 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 "IccCallback.h"
+
+#include "mozilla/dom/IccCardLockError.h"
+#include "mozilla/dom/MozIccBinding.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/ToJSValue.h"
+#include "nsJSUtils.h"
+#include "nsServiceManagerUtils.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+NS_IMPL_ISUPPORTS(IccCallback, nsIIccCallback)
+
+IccCallback::IccCallback(nsPIDOMWindow* aWindow, DOMRequest* aRequest,
+                         bool aIsCardLockEnabled)
+  : mWindow(aWindow)
+  , mRequest(aRequest)
+  , mIsCardLockEnabled(aIsCardLockEnabled)
+{
+}
+
+IccCallback::IccCallback(nsPIDOMWindow* aWindow, Promise* aPromise)
+  : mWindow(aWindow)
+  , mPromise(aPromise)
+{
+}
+
+nsresult
+IccCallback::NotifySuccess(JS::Handle<JS::Value> aResult)
+{
+  nsCOMPtr<nsIDOMRequestService> rs =
+    do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireSuccessAsync(mRequest, aResult);
+}
+
+nsresult
+IccCallback::NotifyGetCardLockEnabled(bool aResult)
+{
+  IccCardLockStatus result;
+  result.mEnabled.Construct(aResult);
+
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  JSContext* cx = jsapi.cx();
+  JS::Rooted<JS::Value> jsResult(cx);
+  if (!ToJSValue(cx, result, &jsResult)) {
+    JS_ClearPendingException(cx);
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  return NotifySuccess(jsResult);
+}
+
+NS_IMETHODIMP
+IccCallback::NotifySuccess()
+{
+  return NotifySuccess(JS::UndefinedHandleValue);
+}
+
+NS_IMETHODIMP
+IccCallback::NotifySuccessWithBoolean(bool aResult)
+{
+  if (mPromise) {
+    mPromise->MaybeResolve(aResult ? JS::TrueHandleValue : JS::FalseHandleValue);
+    return NS_OK;
+  }
+
+  return mIsCardLockEnabled
+    ? NotifyGetCardLockEnabled(aResult)
+    : NotifySuccess(aResult ? JS::TrueHandleValue : JS::FalseHandleValue);
+}
+
+NS_IMETHODIMP
+IccCallback::NotifyGetCardLockRetryCount(int32_t aCount)
+{
+  // TODO: Bug 1125018 - Simplify The Result of GetCardLock and
+  // getCardLockRetryCount in MozIcc.webidl without a wrapper object.
+  IccCardLockRetryCount result;
+  result.mRetryCount.Construct(aCount);
+
+  AutoJSAPI jsapi;
+  if (NS_WARN_IF(!jsapi.Init(mWindow))) {
+    return NS_ERROR_FAILURE;
+  }
+
+  JSContext* cx = jsapi.cx();
+  JS::Rooted<JS::Value> jsResult(cx);
+  if (!ToJSValue(cx, result, &jsResult)) {
+    JS_ClearPendingException(cx);
+    return NS_ERROR_TYPE_ERR;
+  }
+
+  return NotifySuccess(jsResult);
+}
+
+NS_IMETHODIMP
+IccCallback::NotifyError(const nsAString & aErrorMsg)
+{
+  if (mPromise) {
+    mPromise->MaybeRejectBrokenly(aErrorMsg);
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsIDOMRequestService> rs =
+    do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
+  NS_ENSURE_TRUE(rs, NS_ERROR_FAILURE);
+
+  return rs->FireErrorAsync(mRequest, aErrorMsg);
+}
+
+NS_IMETHODIMP
+IccCallback::NotifyCardLockError(const nsAString & aErrorMsg,
+                                 int32_t aRetryCount)
+{
+  nsRefPtr<IccCardLockError> error =
+    new IccCardLockError(mWindow, aErrorMsg, aRetryCount);
+  mRequest->FireDetailedError(error);
+
+  return NS_OK;
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/IccCallback.h
@@ -0,0 +1,64 @@
+/* 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_icc_IccCallback_h
+#define mozilla_dom_icc_IccCallback_h
+
+#include "nsCOMPtr.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+
+class DOMRequest;
+class Promise;
+
+namespace icc {
+
+/**
+ * A callback object for handling asynchronous request/response. This object is
+ * created when an asynchronous request is made and should be destroyed after
+ * Notify*Success/Error is called.
+ * The modules hold the reference of IccCallback in OOP mode and non-OOP mode
+ * are different.
+ * - OOP mode: IccRequestChild
+ * - non-OOP mode: IccService
+ * The reference should be released after Notify*Success/Error is called.
+ */
+class IccCallback final : public nsIIccCallback
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCCALLBACK
+
+  // TODO: Bug 1125018 - Simplify The Result of GetCardLock and
+  // getCardLockRetryCount in MozIcc.webidl without a wrapper object.
+  IccCallback(nsPIDOMWindow* aWindow, DOMRequest* aRequest,
+              bool aIsCardLockEnabled = false);
+  IccCallback(nsPIDOMWindow* aWindow, Promise* aPromise);
+
+private:
+  ~IccCallback() {}
+
+  nsresult
+  NotifySuccess(JS::Handle<JS::Value> aResult);
+
+  // TODO: Bug 1125018 - Simplify The Result of GetCardLock and
+  // getCardLockRetryCount in MozIcc.webidl without a wrapper object.
+  nsresult
+  NotifyGetCardLockEnabled(bool aResult);
+
+  nsCOMPtr<nsPIDOMWindow> mWindow;
+  nsRefPtr<DOMRequest> mRequest;
+  nsRefPtr<Promise> mPromise;
+  // TODO: Bug 1125018 - Simplify The Result of GetCardLock and
+  // getCardLockRetryCount in MozIcc.webidl without a wrapper object.
+  bool mIsCardLockEnabled;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccCallback_h
--- a/dom/icc/IccInfo.cpp
+++ b/dom/icc/IccInfo.cpp
@@ -1,233 +1,295 @@
 /* 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/IccInfo.h"
 
+#include "mozilla/dom/icc/PIccTypes.h"
 #include "nsPIDOMWindow.h"
 
 #define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum)      \
 {                                                                       \
   uint32_t i = 0;                                                       \
   for (const EnumEntry* entry = _enumType##Values::strings;             \
        entry->value;                                                    \
        ++entry, ++i) {                                                  \
     if (_string.EqualsASCII(entry->value)) {                            \
       _enum.SetValue(static_cast<_enumType>(i));                        \
     }                                                                   \
   }                                                                     \
 }
 
 using namespace mozilla::dom;
 
+using mozilla::dom::icc::IccInfoData;
+
 // IccInfo
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(IccInfo, mWindow, mIccInfo)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(IccInfo, mWindow)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(IccInfo)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(IccInfo)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(IccInfo)
+  NS_INTERFACE_MAP_ENTRY(nsIIccInfo)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
-  NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 IccInfo::IccInfo(nsPIDOMWindow* aWindow)
   : mWindow(aWindow)
 {
+  mIccType.SetIsVoid(true);
+  mIccid.SetIsVoid(true);
+  mMcc.SetIsVoid(true);
+  mMnc.SetIsVoid(true);
+  mSpn.SetIsVoid(true);
+}
+
+IccInfo::IccInfo(const IccInfoData& aData)
+{
+  mIccType = aData.iccType();
+  mIccid = aData.iccid();
+  mMcc = aData.mcc();
+  mMnc = aData.mnc();
+  mSpn = aData.spn();
+  mIsDisplayNetworkNameRequired = aData.isDisplayNetworkNameRequired();
+  mIsDisplaySpnRequired = aData.isDisplaySpnRequired();
+}
+
+// nsIIccInfo
+
+NS_IMETHODIMP
+IccInfo::GetIccType(nsAString & aIccType)
+{
+  aIccType = mIccType;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetIccid(nsAString & aIccid)
+{
+  aIccid = mIccid;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetMcc(nsAString & aMcc)
+{
+  aMcc = mMcc;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetMnc(nsAString & aMnc)
+{
+  aMnc = mMnc;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetSpn(nsAString & aSpn)
+{
+  aSpn = mSpn;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetIsDisplayNetworkNameRequired(bool *aIsDisplayNetworkNameRequired)
+{
+  *aIsDisplayNetworkNameRequired = mIsDisplayNetworkNameRequired;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccInfo::GetIsDisplaySpnRequired(bool *aIsDisplaySpnRequired)
+{
+  *aIsDisplaySpnRequired = mIsDisplaySpnRequired;
+  return NS_OK;
 }
 
 void
 IccInfo::Update(nsIIccInfo* aInfo)
 {
-  mIccInfo = aInfo;
+  NS_ASSERTION(aInfo, "aInfo is null");
+
+  aInfo->GetIccType(mIccType);
+  aInfo->GetIccid(mIccid);
+  aInfo->GetMcc(mMcc);
+  aInfo->GetMnc(mMnc);
+  aInfo->GetSpn(mSpn);
+  aInfo->GetIsDisplayNetworkNameRequired(
+    &mIsDisplayNetworkNameRequired);
+  aInfo->GetIsDisplaySpnRequired(
+    &mIsDisplaySpnRequired);
 }
 
+// WebIDL implementation
+
 JSObject*
 IccInfo::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MozIccInfoBinding::Wrap(aCx, this, aGivenProto);
 }
 
 Nullable<IccType>
 IccInfo::GetIccType() const
 {
-  if (!mIccInfo) {
-    return Nullable<IccType>();
-  }
-
-  nsAutoString type;
   Nullable<IccType> iccType;
 
-  mIccInfo->GetIccType(type);
-  CONVERT_STRING_TO_NULLABLE_ENUM(type, IccType, iccType);
+  CONVERT_STRING_TO_NULLABLE_ENUM(mIccType, IccType, iccType);
 
   return iccType;
 }
 
 void
 IccInfo::GetIccid(nsAString& aIccId) const
 {
-  if (!mIccInfo) {
-    aIccId.SetIsVoid(true);
-    return;
-  }
-
-  mIccInfo->GetIccid(aIccId);
+  aIccId = mIccid;
 }
 
 void
 IccInfo::GetMcc(nsAString& aMcc) const
 {
-  if (!mIccInfo) {
-    aMcc.SetIsVoid(true);
-    return;
-  }
-
-  mIccInfo->GetMcc(aMcc);
+  aMcc = mMcc;
 }
 
 void
 IccInfo::GetMnc(nsAString& aMnc) const
 {
-  if (!mIccInfo) {
-    aMnc.SetIsVoid(true);
-    return;
-  }
-
-  mIccInfo->GetMnc(aMnc);
+  aMnc = mMnc;
 }
 
 void
 IccInfo::GetSpn(nsAString& aSpn) const
 {
-  if (!mIccInfo) {
-    aSpn.SetIsVoid(true);
-    return;
-  }
-
-  mIccInfo->GetSpn(aSpn);
+  aSpn = mSpn;
 }
 
 bool
 IccInfo::IsDisplayNetworkNameRequired() const
 {
-  if (!mIccInfo) {
-    return false;
-  }
-
-  bool isDisplayNetworkNameRequired;
-  mIccInfo->GetIsDisplayNetworkNameRequired(&isDisplayNetworkNameRequired);
-
-  return isDisplayNetworkNameRequired;
+  return mIsDisplayNetworkNameRequired;
 }
 
 bool
 IccInfo::IsDisplaySpnRequired() const
 {
-  if (!mIccInfo) {
-    return false;
-  }
-
-  bool isDisplaySpnRequired;
-  mIccInfo->GetIsDisplaySpnRequired(&isDisplaySpnRequired);
-
-  return isDisplaySpnRequired;
+  return mIsDisplaySpnRequired;
 }
 
 // GsmIccInfo
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED(GsmIccInfo, IccInfo, mGsmIccInfo)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(GsmIccInfo)
-NS_INTERFACE_MAP_END_INHERITING(IccInfo)
-
-NS_IMPL_ADDREF_INHERITED(GsmIccInfo, IccInfo)
-NS_IMPL_RELEASE_INHERITED(GsmIccInfo, IccInfo)
+NS_IMPL_ISUPPORTS_INHERITED(GsmIccInfo, IccInfo, nsIGsmIccInfo)
 
 GsmIccInfo::GsmIccInfo(nsPIDOMWindow* aWindow)
   : IccInfo(aWindow)
 {
+  mPhoneNumber.SetIsVoid(true);
 }
 
+GsmIccInfo::GsmIccInfo(const IccInfoData& aData)
+  : IccInfo(aData)
+{
+  mPhoneNumber = aData.phoneNumber();
+}
+
+// nsIGsmIccInfo
+
+NS_IMETHODIMP
+GsmIccInfo::GetMsisdn(nsAString & aMsisdn)
+{
+  aMsisdn = mPhoneNumber;
+  return NS_OK;
+}
+
+// WebIDL implementation
+
 void
 GsmIccInfo::Update(nsIGsmIccInfo* aInfo)
 {
+  MOZ_ASSERT(aInfo);
   nsCOMPtr<nsIIccInfo> iccInfo = do_QueryInterface(aInfo);
   MOZ_ASSERT(iccInfo);
 
   IccInfo::Update(iccInfo);
-  mGsmIccInfo = aInfo;
+
+  aInfo->GetMsisdn(mPhoneNumber);
 }
 
 JSObject*
 GsmIccInfo::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MozGsmIccInfoBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 GsmIccInfo::GetMsisdn(nsAString& aMsisdn) const
 {
-  if (!mGsmIccInfo) {
-    aMsisdn.SetIsVoid(true);
-    return;
-  }
-
-  mGsmIccInfo->GetMsisdn(aMsisdn);
+  aMsisdn = mPhoneNumber;
 }
 
 // CdmaIccInfo
 
-NS_IMPL_CYCLE_COLLECTION_INHERITED(CdmaIccInfo, IccInfo, mCdmaIccInfo)
-
-NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CdmaIccInfo)
-NS_INTERFACE_MAP_END_INHERITING(IccInfo)
-
-NS_IMPL_ADDREF_INHERITED(CdmaIccInfo, IccInfo)
-NS_IMPL_RELEASE_INHERITED(CdmaIccInfo, IccInfo)
+NS_IMPL_ISUPPORTS_INHERITED(CdmaIccInfo, IccInfo, nsICdmaIccInfo)
 
 CdmaIccInfo::CdmaIccInfo(nsPIDOMWindow* aWindow)
   : IccInfo(aWindow)
 {
+  mPhoneNumber.SetIsVoid(true);
+}
+
+CdmaIccInfo::CdmaIccInfo(const IccInfoData& aData)
+  : IccInfo(aData)
+{
+  mPhoneNumber = aData.phoneNumber();
+  mPrlVersion = aData.prlVersion();
+}
+
+// nsICdmaIccInfo
+
+NS_IMETHODIMP
+CdmaIccInfo::GetMdn(nsAString & aMdn)
+{
+  aMdn = mPhoneNumber;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+CdmaIccInfo::GetPrlVersion(int32_t *aPrlVersion)
+{
+  *aPrlVersion = mPrlVersion;
+  return NS_OK;
 }
 
 void
 CdmaIccInfo::Update(nsICdmaIccInfo* aInfo)
 {
+  MOZ_ASSERT(aInfo);
   nsCOMPtr<nsIIccInfo> iccInfo = do_QueryInterface(aInfo);
   MOZ_ASSERT(iccInfo);
 
   IccInfo::Update(iccInfo);
-  mCdmaIccInfo = aInfo;
+
+  aInfo->GetMdn(mPhoneNumber);
+  aInfo->GetPrlVersion(&mPrlVersion);
 }
 
+// WebIDL implementation
+
 JSObject*
 CdmaIccInfo::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return MozCdmaIccInfoBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 CdmaIccInfo::GetMdn(nsAString& aMdn) const
 {
-  if (!mCdmaIccInfo) {
-    aMdn.SetIsVoid(true);
-    return;
-  }
-
-  mCdmaIccInfo->GetMdn(aMdn);
+  aMdn = mPhoneNumber;
 }
 
 int32_t
 CdmaIccInfo::PrlVersion() const
 {
-  if (!mCdmaIccInfo) {
-    return 0;
-  }
-
-  int32_t prlVersion;
-  mCdmaIccInfo->GetPrlVersion(&prlVersion);
-
-  return prlVersion;
+  return mPrlVersion;
 }
--- a/dom/icc/IccInfo.h
+++ b/dom/icc/IccInfo.h
@@ -9,24 +9,30 @@
 #include "nsIIccInfo.h"
 #include "nsWrapperCache.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
-class IccInfo : public nsISupports
+namespace icc {
+class IccInfoData;
+} // namespace icc
+
+class IccInfo : public nsIIccInfo
               , public nsWrapperCache
 {
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(IccInfo)
+  NS_DECL_NSIICCINFO
 
   explicit IccInfo(nsPIDOMWindow* aWindow);
+  explicit IccInfo(const icc::IccInfoData& aData);
 
   void
   Update(nsIIccInfo* aInfo);
 
   nsPIDOMWindow*
   GetParentObject() const
   {
     return mWindow;
@@ -56,54 +62,68 @@ public:
   IsDisplayNetworkNameRequired() const;
 
   bool
   IsDisplaySpnRequired() const;
 
 protected:
   virtual ~IccInfo() {}
 
-protected:
   nsCOMPtr<nsPIDOMWindow> mWindow;
-  nsCOMPtr<nsIIccInfo> mIccInfo;
+  // To prevent compiling error in OS_WIN in auto-generated UnifiedBindingsXX.cpp,
+  // we have all data fields expended here instead of having a data member of
+  // |IccInfoData| defined in PIccTypes.h which indirectly includes "windows.h"
+  // See 925382 for the restriction of including "windows.h" in UnifiedBindings.cpp.
+  nsString mIccType;
+  nsString mIccid;
+  nsString mMcc;
+  nsString mMnc;
+  nsString mSpn;
+  bool mIsDisplayNetworkNameRequired;
+  bool mIsDisplaySpnRequired;
 };
 
 class GsmIccInfo final : public IccInfo
+                       , public nsIGsmIccInfo
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(GsmIccInfo, IccInfo)
+  NS_FORWARD_NSIICCINFO(IccInfo::)
+  NS_DECL_NSIGSMICCINFO
 
   explicit GsmIccInfo(nsPIDOMWindow* aWindow);
+  explicit GsmIccInfo(const icc::IccInfoData& aData);
 
   void
   Update(nsIGsmIccInfo* aInfo);
 
   // WrapperCache
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // MozCdmaIccInfo WebIDL
   void
   GetMsisdn(nsAString& aMsisdn) const;
 
 private:
   ~GsmIccInfo() {}
 
-private:
-  nsCOMPtr<nsIGsmIccInfo> mGsmIccInfo;
+  nsString mPhoneNumber;
 };
 
 class CdmaIccInfo final : public IccInfo
+                        , public nsICdmaIccInfo
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CdmaIccInfo, IccInfo)
+  NS_FORWARD_NSIICCINFO(IccInfo::)
+  NS_DECL_NSICDMAICCINFO
 
   explicit CdmaIccInfo(nsPIDOMWindow* aWindow);
+  explicit CdmaIccInfo(const icc::IccInfoData& aData);
 
   void
   Update(nsICdmaIccInfo* aInfo);
 
   // WrapperCache
   virtual JSObject*
   WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
@@ -112,17 +132,17 @@ public:
   GetMdn(nsAString& aMdn) const;
 
   int32_t
   PrlVersion() const;
 
 private:
   ~CdmaIccInfo() {}
 
-private:
-  nsCOMPtr<nsICdmaIccInfo> mCdmaIccInfo;
+  nsString mPhoneNumber;
+  int32_t mPrlVersion;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_IccInfo_h
 
--- a/dom/icc/IccListener.cpp
+++ b/dom/icc/IccListener.cpp
@@ -15,51 +15,77 @@ using namespace mozilla::dom;
 NS_IMPL_ISUPPORTS(IccListener, nsIIccListener)
 
 IccListener::IccListener(IccManager* aIccManager, uint32_t aClientId)
   : mClientId(aClientId)
   , mIccManager(aIccManager)
 {
   MOZ_ASSERT(mIccManager);
 
+  // TODO: Bug 1114938, Refactor STK in MozIcc.webidl with IPDL.
+  //       Remove the registration to IccProvider.
   mProvider = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
 
   if (!mProvider) {
     NS_WARNING("Could not acquire nsIIccProvider!");
     return;
   }
 
+  nsCOMPtr<nsIIccService> iccService = do_GetService(ICC_SERVICE_CONTRACTID);
+
+  if (!iccService) {
+    NS_WARNING("Could not acquire nsIIccService!");
+    return;
+  }
+
+  iccService->GetIccByServiceId(mClientId, getter_AddRefs(mHandler));
+  if (!mHandler) {
+    NS_WARNING("Could not acquire nsIIcc!");
+    return;
+  }
+
   nsCOMPtr<nsIIccInfo> iccInfo;
-  mProvider->GetIccInfo(mClientId, getter_AddRefs(iccInfo));
+  mHandler->GetIccInfo(getter_AddRefs(iccInfo));
   if (iccInfo) {
     nsString iccId;
     iccInfo->GetIccid(iccId);
     if (!iccId.IsEmpty()) {
-      mIcc = new Icc(mIccManager->GetOwner(), mClientId, iccInfo);
+      mIcc = new Icc(mIccManager->GetOwner(), mClientId, mHandler, iccInfo);
     }
   }
 
-  DebugOnly<nsresult> rv = mProvider->RegisterIccMsg(mClientId, this);
+  DebugOnly<nsresult> rv = mHandler->RegisterListener(this);
+  NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
+                   "Failed registering icc listener with Icc Handler");
+
+  rv = mProvider->RegisterIccMsg(mClientId, this);
   NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                    "Failed registering icc messages with provider");
 }
 
 IccListener::~IccListener()
 {
   Shutdown();
 }
 
 void
 IccListener::Shutdown()
 {
+  // TODO: Bug 1114938, Refactor STK in MozIcc.webidl with IPDL.
+  //       Remove the unregistration to IccProvider.
   if (mProvider) {
     mProvider->UnregisterIccMsg(mClientId, this);
     mProvider = nullptr;
   }
 
+  if (mHandler) {
+    mHandler->UnregisterListener(this);
+    mHandler = nullptr;
+  }
+
   if (mIcc) {
     mIcc->Shutdown();
     mIcc = nullptr;
   }
 
   mIccManager = nullptr;
 }
 
@@ -93,30 +119,34 @@ IccListener::NotifyCardStateChanged()
   }
 
   return mIcc->NotifyEvent(NS_LITERAL_STRING("cardstatechange"));
 }
 
 NS_IMETHODIMP
 IccListener::NotifyIccInfoChanged()
 {
+  if (!mHandler) {
+    return NS_OK;
+  }
+
   nsCOMPtr<nsIIccInfo> iccInfo;
-  mProvider->GetIccInfo(mClientId, getter_AddRefs(iccInfo));
+  mHandler->GetIccInfo(getter_AddRefs(iccInfo));
 
   // Create/delete icc object based on current iccInfo.
   // 1. If the mIcc is nullptr and iccInfo has valid data, create icc object and
   //    notify mIccManager a new icc is added.
   // 2. If the mIcc is not nullptr and iccInfo becomes to null, delete existed
   //    icc object and notify mIccManager the icc is removed.
   if (!mIcc) {
     if (iccInfo) {
       nsString iccId;
       iccInfo->GetIccid(iccId);
       if (!iccId.IsEmpty()) {
-        mIcc = new Icc(mIccManager->GetOwner(), mClientId, iccInfo);
+        mIcc = new Icc(mIccManager->GetOwner(), mClientId, mHandler, iccInfo);
         mIccManager->NotifyIccAdd(iccId);
         mIcc->NotifyEvent(NS_LITERAL_STRING("iccinfochange"));
       }
     }
   } else {
     mIcc->UpdateIccInfo(iccInfo);
     mIcc->NotifyEvent(NS_LITERAL_STRING("iccinfochange"));
     if (!iccInfo) {
--- a/dom/icc/IccListener.h
+++ b/dom/icc/IccListener.h
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_IccListener_h
 #define mozilla_dom_IccListener_h
 
 #include "nsAutoPtr.h"
 #include "nsIIccProvider.h"
+#include "nsIIccService.h"
 
 namespace mozilla {
 namespace dom {
 
 class IccManager;
 class Icc;
 
 class IccListener final : public nsIIccListener
@@ -37,17 +38,20 @@ private:
 private:
   uint32_t mClientId;
   // We did not setup 'mIcc' and 'mIccManager' being a participant of cycle
   // collection is because in Navigator->Invalidate() it will call
   // mIccManager->Shutdown(), then IccManager will call Shutdown() of each
   // IccListener, this will release the reference and break the cycle.
   nsRefPtr<Icc> mIcc;
   nsRefPtr<IccManager> mIccManager;
-  // mProvider is a xpcom service and will be released at shutdown, so it
+  // mProvider is a xpcom service and will be released at Shutdown(), so it
   // doesn't need to be cycle collected.
   nsCOMPtr<nsIIccProvider> mProvider;
+  // mHandler will be released at Shutdown(), there is no need to join cycle
+  // collection.
+  nsCOMPtr<nsIIcc> mHandler;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_IccListener_h
--- a/dom/icc/IccManager.cpp
+++ b/dom/icc/IccManager.cpp
@@ -5,16 +5,25 @@
 #include "IccManager.h"
 #include "mozilla/dom/MozIccManagerBinding.h"
 #include "Icc.h"
 #include "IccListener.h"
 #include "mozilla/AsyncEventDispatcher.h"
 #include "mozilla/dom/IccChangeEvent.h"
 #include "mozilla/Preferences.h"
 #include "nsIIccInfo.h"
+// Service instantiation
+#include "ipc/IccIPCService.h"
+#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
+// TODO: Bug 815526, deprecate RILContentHelper.
+#include "nsIRadioInterfaceLayer.h"
+#include "nsRadioInterfaceLayer.h"
+#include "nsIGonkIccService.h"
+#endif
+#include "nsXULAppAPI.h" // For XRE_GetProcessType()
 
 using namespace mozilla::dom;
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IccManager)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IccManager,
                                                   DOMEventTargetHelper)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@@ -124,8 +133,30 @@ IccManager::GetIccById(const nsAString& 
   for (i = 0; i < mIccListeners.Length(); ++i) {
     Icc* icc = mIccListeners[i]->GetIcc();
     if (icc && aIccId == icc->GetIccId()) {
       return icc;
     }
   }
   return nullptr;
 }
+
+already_AddRefed<nsIIccService>
+NS_CreateIccService()
+{
+  nsCOMPtr<nsIIccService> service;
+
+  if (XRE_GetProcessType() == GeckoProcessType_Content) {
+    service = new mozilla::dom::icc::IccIPCService();
+#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
+  } else {
+    // TODO: Bug 815526, deprecate RILContentHelper.
+    nsCOMPtr <nsIRadioInterfaceLayer> ril =
+      do_GetService(NS_RADIOINTERFACELAYER_CONTRACTID);
+    nsCOMPtr <nsIRadioInterfaceLayer_new> ril_new(do_QueryInterface(ril));
+
+    service = (ril_new) ? do_GetService(GONK_ICC_SERVICE_CONTRACTID)
+                        : do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
+#endif
+  }
+
+  return service.forget();
+}
--- a/dom/icc/IccManager.h
+++ b/dom/icc/IccManager.h
@@ -2,17 +2,16 @@
  * 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_IccManager_h
 #define mozilla_dom_IccManager_h
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsIIccProvider.h"
 #include "nsTArrayHelpers.h"
 
 namespace mozilla {
 namespace dom {
 
 class Icc;
 class IccListener;
 
@@ -20,17 +19,17 @@ class IccManager final : public DOMEvent
 {
 public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(IccManager, DOMEventTargetHelper)
 
-  IccManager(nsPIDOMWindow* aWindow);
+  explicit IccManager(nsPIDOMWindow* aWindow);
 
   void
   Shutdown();
 
   nsresult
   NotifyIccAdd(const nsAString& aIccId);
 
   nsresult
new file mode 100644
--- /dev/null
+++ b/dom/icc/gonk/IccService.js
@@ -0,0 +1,437 @@
+/* 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;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+var RIL = {};
+Cu.import("resource://gre/modules/ril_consts.js", RIL);
+
+const GONK_ICCSERVICE_CONTRACTID = "@mozilla.org/icc/gonkiccservice;1";
+const GONK_ICCSERVICE_CID = Components.ID("{df854256-9554-11e4-a16c-c39e8d106c26}");
+
+const NS_XPCOM_SHUTDOWN_OBSERVER_ID      = "xpcom-shutdown";
+const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID  = "nsPref:changed";
+
+const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
+const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
+
+XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer",
+                                   "@mozilla.org/ril;1",
+                                   "nsIRadioInterfaceLayer");
+
+let DEBUG = RIL.DEBUG_RIL;
+function debug(s) {
+  dump("IccService: " + s);
+}
+
+function IccInfo() {}
+IccInfo.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccInfo]),
+
+  // nsIIccInfo
+
+  iccType: null,
+  iccid: null,
+  mcc: null,
+  mnc: null,
+  spn: null,
+  isDisplayNetworkNameRequired: false,
+  isDisplaySpnRequired: false
+};
+
+function GsmIccInfo() {}
+GsmIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
+                                         Ci.nsIIccInfo]),
+
+  // nsIGsmIccInfo
+
+  msisdn: null
+};
+
+function CdmaIccInfo() {}
+CdmaIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsICdmaIccInfo,
+                                         Ci.nsIIccInfo]),
+
+  // nsICdmaIccInfo
+
+  mdn: null,
+  prlVersion: 0
+};
+
+function IccService() {
+  this._iccs = [];
+
+  let numClients = gRadioInterfaceLayer.numRadioInterfaces;
+  for (let i = 0; i < numClients; i++) {
+    this._iccs.push(new Icc(gRadioInterfaceLayer.getRadioInterface(i)));
+  }
+
+  this._updateDebugFlag();
+
+  Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
+  Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+}
+IccService.prototype = {
+  classID: GONK_ICCSERVICE_CID,
+
+  classInfo: XPCOMUtils.generateCI({classID: GONK_ICCSERVICE_CID,
+                                    contractID: GONK_ICCSERVICE_CONTRACTID,
+                                    classDescription: "IccService",
+                                    interfaces: [Ci.nsIIccService,
+                                                 Ci.nsIGonkIccService],
+                                    flags: Ci.nsIClassInfo.SINGLETON}),
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccService,
+                                         Ci.nsIGonkIccService,
+                                         Ci.nsIObserver]),
+
+  // An array of Icc instances.
+  _iccs: null,
+
+  _updateDebugFlag: function() {
+    try {
+      DEBUG = DEBUG ||
+              Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
+    } catch (e) {}
+  },
+
+  /**
+   * nsIIccService interface.
+   */
+  getIccByServiceId: function(aServiceId) {
+    let icc = this._iccs[aServiceId];
+    if (!icc) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    return icc;
+  },
+
+  /**
+   * nsIGonkIccService interface.
+   */
+  notifyCardStateChanged: function(aServiceId, aCardState) {
+    if (DEBUG) {
+      debug("notifyCardStateChanged for service Id: " + aServiceId +
+            ", CardState: " + aCardState);
+    }
+
+    this.getIccByServiceId(aServiceId)._updateCardState(aCardState);
+  },
+
+  notifyIccInfoChanged: function(aServiceId, aIccInfo) {
+    if (DEBUG) {
+      debug("notifyIccInfoChanged for service Id: " + aServiceId +
+            ", IccInfo: " + JSON.stringify(aIccInfo));
+    }
+
+    this.getIccByServiceId(aServiceId)._updateIccInfo(aIccInfo);
+  },
+
+  notifyImsiChanged: function(aServiceId, aImsi) {
+    if (DEBUG) {
+      debug("notifyImsiChanged for service Id: " + aServiceId +
+            ", Imsi: " + aImsi);
+    }
+
+    let icc = this.getIccByServiceId(aServiceId);
+    icc._imsi = aImsi;
+  },
+
+  /**
+   * nsIObserver interface.
+   */
+  observe: function(aSubject, aTopic, aData) {
+    switch (aTopic) {
+      case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
+        if (aData === kPrefRilDebuggingEnabled) {
+          this._updateDebugFlag();
+        }
+        break;
+      case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
+        Services.prefs.removeObserver(kPrefRilDebuggingEnabled, this);
+        Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+        break;
+    }
+  }
+};
+
+function Icc(aRadioInterface) {
+  this._radioInterface = aRadioInterface;
+  this._listeners = [];
+}
+Icc.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
+
+  _radioInterface: null,
+  _imsi: null,
+  _listeners: null,
+
+  _updateCardState: function(aCardState) {
+    if (this.cardState != aCardState) {
+      this.cardState = aCardState;
+    }
+
+    this._deliverListenerEvent("notifyCardStateChanged");
+  },
+
+  // An utility function to copy objects.
+  _updateInfo: function(aSrcInfo, aDestInfo) {
+    for (let key in aSrcInfo) {
+      aDestInfo[key] = aSrcInfo[key];
+    }
+  },
+
+  /**
+   * We need to consider below cases when update iccInfo:
+   * 1. Should clear iccInfo to null if there is no card detected.
+   * 2. Need to create corresponding object based on iccType.
+   */
+  _updateIccInfo: function(aIccInfo) {
+    // Card is not detected, clear iccInfo to null.
+    if (!aIccInfo || !aIccInfo.iccid) {
+      if (this.iccInfo) {
+        if (DEBUG) {
+          debug("Card is not detected, clear iccInfo to null.");
+        }
+        this.iccInfo = null;
+        this._deliverListenerEvent("notifyIccInfoChanged");
+      }
+      return;
+    }
+
+    // If iccInfo is null, new corresponding object based on iccType.
+    if (!this.iccInfo ||
+        this.iccInfo.iccType != aIccInfo.iccType) {
+      if (aIccInfo.iccType === "ruim" || aIccInfo.iccType === "csim") {
+        this.iccInfo = new CdmaIccInfo();
+      } else if (aIccInfo.iccType === "sim" || aIccInfo.iccType === "usim") {
+        this.iccInfo = new GsmIccInfo();
+      } else {
+        this.iccInfo = new IccInfo();
+      }
+    }
+
+    this._updateInfo(aIccInfo, this.iccInfo);
+
+    this._deliverListenerEvent("notifyIccInfoChanged");
+
+    // Update lastKnownSimMcc.
+    if (aIccInfo.mcc) {
+      try {
+        Services.prefs.setCharPref("ril.lastKnownSimMcc",
+                                   aIccInfo.mcc.toString());
+      } catch (e) {}
+    }
+  },
+
+  _deliverListenerEvent: function(aName, aArgs) {
+    let listeners = this._listeners.slice();
+    for (let listener of listeners) {
+      if (this._listeners.indexOf(listener) === -1) {
+        continue;
+      }
+      let handler = listener[aName];
+      if (typeof handler != "function") {
+        throw new Error("No handler for " + aName);
+      }
+      try {
+        handler.apply(listener, aArgs);
+      } catch (e) {
+        if (DEBUG) {
+          debug("listener for " + aName + " threw an exception: " + e);
+        }
+      }
+    }
+  },
+
+  _modifyCardLock: function(aOperation, aOptions, aCallback) {
+    this._radioInterface.sendWorkerMessage(aOperation,
+                                           aOptions,
+                                           (aResponse) => {
+      if (aResponse.errorMsg) {
+        let retryCount =
+          (aResponse.retryCount !== undefined) ? aResponse.retryCount : -1;
+        aCallback.notifyCardLockError(aResponse.errorMsg, retryCount);
+        return;
+      }
+
+      aCallback.notifySuccess();
+    });
+  },
+
+  /**
+   * Helper to match the MVNO pattern with IMSI.
+   *
+   * Note: Characters 'x' and 'X' in MVNO are skipped and not compared.
+   *       E.g., if the aMvnoData passed is '310260x10xxxxxx', then the
+   *       function returns true only if imsi has the same first 6 digits, 8th
+   *       and 9th digit.
+   *
+   * @param aMvnoData
+   *        MVNO pattern.
+   * @param aImsi
+   *        IMSI of this ICC.
+   *
+   * @return true if matched.
+   */
+  _isImsiMatches: function(aMvnoData, aImsi) {
+    // This should not be an error, but a mismatch.
+    if (aMvnoData.length > aImsi.length) {
+      return false;
+    }
+
+    for (let i = 0; i < aMvnoData.length; i++) {
+      let c = aMvnoData[i];
+      if ((c !== 'x') && (c !== 'X') && (c !== aImsi[i])) {
+        return false;
+      }
+    }
+    return true;
+  },
+
+  /**
+   * nsIIcc interface.
+   */
+  iccInfo: null,
+  cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
+
+  registerListener: function(aListener) {
+    if (this._listeners.indexOf(aListener) >= 0) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    this._listeners.push(aListener);
+  },
+
+  unregisterListener: function(aListener) {
+    let index = this._listeners.indexOf(aListener);
+    if (index >= 0) {
+      this._listeners.splice(index, 1);
+    }
+  },
+
+  getCardLockEnabled: function(aLockType, aCallback) {
+    this._radioInterface.sendWorkerMessage("iccGetCardLockEnabled",
+                                           { lockType: aLockType },
+                                           (aResponse) => {
+      if (aResponse.errorMsg) {
+        aCallback.notifyError(aResponse.errorMsg);
+        return;
+      }
+
+      aCallback.notifySuccessWithBoolean(aResponse.enabled);
+    });
+  },
+
+  unlockCardLock: function(aLockType, aPassword, aNewPin, aCallback) {
+    this._modifyCardLock("iccUnlockCardLock",
+                         { lockType: aLockType,
+                           password: aPassword,
+                           newPin: aNewPin },
+                         aCallback);
+  },
+
+  setCardLockEnabled: function(aLockType, aPassword, aEnabled, aCallback) {
+    this._modifyCardLock("iccSetCardLockEnabled",
+                         { lockType: aLockType,
+                           password: aPassword,
+                           enabled: aEnabled },
+                         aCallback);
+  },
+
+  changeCardLockPassword: function(aLockType, aPassword, aNewPassword, aCallback) {
+    this._modifyCardLock("iccChangeCardLockPassword",
+                         { lockType: aLockType,
+                           password: aPassword,
+                           newPassword: aNewPassword, },
+                         aCallback);
+  },
+
+  getCardLockRetryCount: function(aLockType, aCallback) {
+    this._radioInterface.sendWorkerMessage("iccGetCardLockRetryCount",
+                                           { lockType: aLockType },
+                                           (aResponse) => {
+      if (aResponse.errorMsg) {
+        aCallback.notifyError(aResponse.errorMsg);
+        return;
+      }
+
+      aCallback.notifyGetCardLockRetryCount(aResponse.retryCount);
+    });
+  },
+
+  matchMvno: function(aMvnoType, aMvnoData, aCallback) {
+    if (!aMvnoData) {
+      aCallback.notifyError(RIL.GECKO_ERROR_INVALID_PARAMETER);
+      return;
+    }
+
+    switch (aMvnoType) {
+      case Ci.nsIIcc.CARD_MVNO_TYPE_IMSI:
+        let imsi = this._imsi;
+        if (!imsi) {
+          aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
+          break;
+        }
+        aCallback.notifySuccessWithBoolean(
+          this._isImsiMatches(aMvnoData, imsi));
+        break;
+      case Ci.nsIIcc.CARD_MVNO_TYPE_SPN:
+        let spn = this.iccInfo && this.iccInfo.spn;
+        if (!spn) {
+          aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
+          break;
+        }
+        aCallback.notifySuccessWithBoolean(spn == aMvnoData);
+        break;
+      case Ci.nsIIcc.CARD_MVNO_TYPE_GID:
+        this._radioInterface.sendWorkerMessage("getGID1",
+                                               null,
+                                               (aResponse) => {
+          let gid = aResponse.gid1;
+          let mvnoDataLength = aMvnoData.length;
+
+          if (!gid) {
+            aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
+          } else if (mvnoDataLength > gid.length) {
+            aCallback.notifySuccessWithBoolean(false);
+          } else {
+            let result =
+              gid.substring(0, mvnoDataLength).toLowerCase() ==
+              aMvnoData.toLowerCase();
+            aCallback.notifySuccessWithBoolean(result);
+          }
+        });
+        break;
+      default:
+        aCallback.notifyError(RIL.GECKO_ERROR_MODE_NOT_SUPPORTED);
+        break;
+    }
+  },
+
+  getServiceStateEnabled: function(aService, aCallback) {
+    this._radioInterface.sendWorkerMessage("getIccServiceState",
+                                           { service: aService },
+                                           (aResponse) => {
+      if (aResponse.errorMsg) {
+        aCallback.notifyError(aResponse.errorMsg);
+        return;
+      }
+
+      aCallback.notifySuccessWithBoolean(aResponse.result);
+    });
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([IccService]);
new file mode 100644
--- /dev/null
+++ b/dom/icc/gonk/IccService.manifest
@@ -0,0 +1,6 @@
+# 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/.
+
+component {df854256-9554-11e4-a16c-c39e8d106c26} IccService.js
+contract @mozilla.org/icc/gonkiccservice;1 {df854256-9554-11e4-a16c-c39e8d106c26}
\ No newline at end of file
--- a/dom/icc/interfaces/moz.build
+++ b/dom/icc/interfaces/moz.build
@@ -1,17 +1,19 @@
 # -*- 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 += [
     'nsIIccInfo.idl',
-    'nsIIccProvider.idl',
+    'nsIIccProvider.idl', # TODO: Bug 815526, deprecate RILContentHelper.
+    'nsIIccService.idl',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
+        'nsIGonkIccService.idl',
         'nsIIccMessenger.idl',
     ]
 
 XPIDL_MODULE = 'dom_icc'
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/nsIGonkIccService.idl
@@ -0,0 +1,21 @@
+/* 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 "nsIIccService.idl"
+
+%{C++
+#define GONK_ICC_SERVICE_CONTRACTID \
+        "@mozilla.org/icc/gonkiccservice;1"
+%}
+
+[scriptable, uuid(a037b8a2-b027-11e4-9496-c3b7af59a512)]
+interface nsIGonkIccService : nsIIccService
+{
+  // TODO: Bug 1114938 - Refactor STK in MozIcc.webidl with IPDL:
+  // void notifyStkCommand(in unsigned long aServiceId, in jsval aStkcommand);
+  // void notifyStkSessionEnd(in unsigned long aServiceId);
+  void notifyCardStateChanged(in unsigned long aServiceId, in unsigned long aCardState);
+  void notifyIccInfoChanged(in unsigned long aServiceId, in jsval aIccInfo);
+  void notifyImsiChanged(in unsigned long aServiceId, in DOMString aImsi);
+};
--- a/dom/icc/interfaces/nsIIccProvider.idl
+++ b/dom/icc/interfaces/nsIIccProvider.idl
@@ -2,25 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 interface nsIDOMDOMRequest;
 interface nsIDOMWindow;
 interface nsIIccInfo;
-
-[scriptable, uuid(7c0ada3d-d8d4-493e-9243-fa3df39855e4)]
-interface nsIIccListener : nsISupports
-{
-  void notifyStkCommand(in DOMString aMessage);
-  void notifyStkSessionEnd();
-  void notifyCardStateChanged();
-  void notifyIccInfoChanged();
-};
+interface nsIIccListener;
 
 [scriptable, uuid(6136acab-b50e-494a-a86d-df392a032897)]
 interface nsIIccChannelCallback : nsISupports
 {
   /**
    * Callback function to notify on successfully opening a logical channel.
    *
    * @param channel
@@ -53,114 +45,28 @@ interface nsIIccChannelCallback : nsISup
    *
    */
   void notifyError(in DOMString error);
 };
 
 /**
  * XPCOM component (in the content process) that provides the ICC information.
  */
-[scriptable, uuid(a203cd2e-2280-4d8e-a687-42b745d322c1)]
+[scriptable, uuid(7dd6e186-b007-11e4-9b7e-7717d7863cb8)]
 interface nsIIccProvider : nsISupports
 {
-  // MUST match enum IccCardState in MozIcc.webidl!
-  const unsigned long CARD_STATE_UNKNOWN = 0;
-  const unsigned long CARD_STATE_READY = 1;
-  const unsigned long CARD_STATE_PIN_REQUIRED = 2;
-  const unsigned long CARD_STATE_PUK_REQUIRED = 3;
-  const unsigned long CARD_STATE_PERMANENT_BLOCKED = 4;
-  const unsigned long CARD_STATE_PERSONALIZATION_IN_PROGRESS = 5;
-  const unsigned long CARD_STATE_PERSONALIZATION_READY = 6;
-  const unsigned long CARD_STATE_NETWORK_LOCKED = 7;
-  const unsigned long CARD_STATE_NETWORK_SUBSET_LOCKED = 8;
-  const unsigned long CARD_STATE_CORPORATE_LOCKED = 9;
-  const unsigned long CARD_STATE_SERVICE_PROVIDER_LOCKED = 10;
-  const unsigned long CARD_STATE_SIM_LOCKED = 11;
-  const unsigned long CARD_STATE_NETWORK_PUK_REQUIRED = 12;
-  const unsigned long CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
-  const unsigned long CARD_STATE_CORPORATE_PUK_REQUIRED = 14;
-  const unsigned long CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
-  const unsigned long CARD_STATE_SIM_PUK_REQUIRED = 16;
-  const unsigned long CARD_STATE_NETWORK1_LOCKED = 17;
-  const unsigned long CARD_STATE_NETWORK2_LOCKED = 18;
-  const unsigned long CARD_STATE_HRPD_NETWORK_LOCKED = 19;
-  const unsigned long CARD_STATE_RUIM_CORPORATE_LOCKED = 20;
-  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
-  const unsigned long CARD_STATE_RUIM_LOCKED = 22;
-  const unsigned long CARD_STATE_NETWORK1_PUK_REQUIRED = 23;
-  const unsigned long CARD_STATE_NETWORK2_PUK_REQUIRED = 24;
-  const unsigned long CARD_STATE_HRPD_NETWORK_PUK_REQUIRED = 25;
-  const unsigned long CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
-  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
-  const unsigned long CARD_STATE_RUIM_PUK_REQUIRED = 28;
-  const unsigned long CARD_STATE_ILLEGAL = 29;
-
-  const unsigned long CARD_STATE_UNDETECTED = 4294967295; // UINT32_MAX
-
-  // MUST match with enum IccLockType in MozIcc.webidl
-  const unsigned long CARD_LOCK_TYPE_PIN = 0;
-  const unsigned long CARD_LOCK_TYPE_PIN2 = 1;
-  const unsigned long CARD_LOCK_TYPE_PUK = 2;
-  const unsigned long CARD_LOCK_TYPE_PUK2 = 3;
-  const unsigned long CARD_LOCK_TYPE_NCK = 4;
-  const unsigned long CARD_LOCK_TYPE_NSCK = 5;
-  const unsigned long CARD_LOCK_TYPE_NCK1 = 6;
-  const unsigned long CARD_LOCK_TYPE_NCK2 = 7;
-  const unsigned long CARD_LOCK_TYPE_HNCK = 8;
-  const unsigned long CARD_LOCK_TYPE_CCK = 9;
-  const unsigned long CARD_LOCK_TYPE_SPCK = 10;
-  const unsigned long CARD_LOCK_TYPE_PCK = 11;
-  const unsigned long CARD_LOCK_TYPE_RCCK = 12;
-  const unsigned long CARD_LOCK_TYPE_RSPCK = 13;
-  const unsigned long CARD_LOCK_TYPE_NCK_PUK = 14;
-  const unsigned long CARD_LOCK_TYPE_NSCK_PUK = 15;
-  const unsigned long CARD_LOCK_TYPE_NCK1_PUK = 16;
-  const unsigned long CARD_LOCK_TYPE_NCK2_PUK = 17;
-  const unsigned long CARD_LOCK_TYPE_HNCK_PUK = 18;
-  const unsigned long CARD_LOCK_TYPE_CCK_PUK = 19;
-  const unsigned long CARD_LOCK_TYPE_SPCK_PUK = 20;
-  const unsigned long CARD_LOCK_TYPE_PCK_PUK = 21;
-  const unsigned long CARD_LOCK_TYPE_RCCK_PUK = 22;
-  const unsigned long CARD_LOCK_TYPE_RSPCK_PUK = 23;
-  const unsigned long CARD_LOCK_TYPE_FDN = 24;
-
-  // MUST match with enum IccContactType in MozIcc.webidl
-  const unsigned long CARD_CONTACT_TYPE_ADN = 0;
-  const unsigned long CARD_CONTACT_TYPE_FDN = 1;
-  const unsigned long CARD_CONTACT_TYPE_SDN = 2;
-
-  // MUST match with enum IccMvnoType in MozIcc.webidl
-  const unsigned long CARD_MVNO_TYPE_IMSI = 0;
-  const unsigned long CARD_MVNO_TYPE_SPN = 1;
-  const unsigned long CARD_MVNO_TYPE_GID = 2;
-
-  // MUST match with enum IccService in MozIcc.webidl
-  const unsigned long CARD_SERVICE_FDN = 0;
-
   /**
    * Called when a content process registers receiving unsolicited messages from
    * RadioInterfaceLayer in the chrome process. Only a content process that has
    * the 'mobileconnection' permission is allowed to register.
    */
   void registerIccMsg(in unsigned long clientId, in nsIIccListener listener);
   void unregisterIccMsg(in unsigned long clientId, in nsIIccListener listener);
 
   /**
-   * UICC Information
-   */
-  nsIIccInfo getIccInfo(in unsigned long clientId);
-
-  /**
-   * Card State
-   *
-   * One of the nsIIccProvider.CARD_STATE_* values.
-   */
-  unsigned long getCardState(in unsigned long clientId);
-
-  /**
    * STK interfaces.
    */
   void sendStkResponse(in unsigned long clientId,
                        in nsIDOMWindow window,
                        in jsval command,
                        in jsval response);
   void sendStkMenuSelection(in unsigned long clientId,
                             in nsIDOMWindow window,
@@ -169,54 +75,29 @@ interface nsIIccProvider : nsISupports
   void sendStkTimerExpiration(in unsigned long clientId,
                               in nsIDOMWindow window,
                               in jsval timer);
   void sendStkEventDownload(in unsigned long clientId,
                             in nsIDOMWindow window,
                             in jsval event);
 
   /**
-   * Card lock interfaces.
-   */
-  nsIDOMDOMRequest getCardLockEnabled(in unsigned long clientId,
-                                      in nsIDOMWindow window,
-                                      in unsigned long lockType);
-  nsIDOMDOMRequest unlockCardLock(in unsigned long clientId,
-                                  in nsIDOMWindow window,
-                                  in unsigned long lockType,
-                                  in DOMString password,
-                                  [optional] in DOMString newPin);
-  nsIDOMDOMRequest setCardLockEnabled(in unsigned long clientId,
-                                      in nsIDOMWindow window,
-                                      in unsigned long lockType,
-                                      in DOMString password,
-                                      in boolean enabled);
-  nsIDOMDOMRequest changeCardLockPassword(in unsigned long clientId,
-                                          in nsIDOMWindow window,
-                                          in unsigned long lockType,
-                                          in DOMString password,
-                                          in DOMString newPassword);
-  nsIDOMDOMRequest getCardLockRetryCount(in unsigned long clientId,
-                                         in nsIDOMWindow window,
-                                         in unsigned long lockType);
-
-  /**
    * Phonebook interfaces.
    */
   nsIDOMDOMRequest readContacts(in unsigned long clientId,
                                 in nsIDOMWindow window,
                                 in unsigned long contactType);
 
   nsIDOMDOMRequest updateContact(in unsigned long clientId,
                                  in nsIDOMWindow window,
                                  in unsigned long contactType,
                                  in jsval contact,
                                  in DOMString pin2);
 
-/**
+  /**
    * Secure Card Icc communication channel
    */
   void iccOpenChannel(in unsigned long clientId,
                       in DOMString aid,
                       in nsIIccChannelCallback callback);
 
   /**
    * Exchange Command APDU (C-APDU) with SIM on the given logical channel.
@@ -233,21 +114,9 @@ interface nsIIccProvider : nsISupports
                        in octet p2,
                        in short p3,
                        in DOMString data,
                        in nsIIccChannelCallback callback);
 
   void iccCloseChannel(in unsigned long clientId,
                        in long channel,
                        in nsIIccChannelCallback callback);
-
-  /**
-   * Helpers
-   */
-  nsIDOMDOMRequest matchMvno(in unsigned long clientId,
-                             in nsIDOMWindow window,
-                             in unsigned long mvnoType,
-                             in DOMString mvnoData);
-
-  nsISupports getServiceState(in unsigned long clientId,
-                              in nsIDOMWindow window,
-                              in unsigned long service);
 };
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/nsIIccService.idl
@@ -0,0 +1,329 @@
+/* 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 nsIIcc;
+interface nsIIccInfo;
+
+[scriptable, uuid(7c0ada3d-d8d4-493e-9243-fa3df39855e4)]
+interface nsIIccListener : nsISupports
+{
+  void notifyStkCommand(in DOMString aMessage);
+  void notifyStkSessionEnd();
+  void notifyCardStateChanged();
+  void notifyIccInfoChanged();
+};
+
+/**
+ * A callback interface for handling asynchronous response.
+ */
+[scriptable, uuid(b0e2899a-adc3-11e4-89cf-1b60eaa35b06)]
+interface nsIIccCallback : nsISupports
+{
+  /**
+   * The success callback with no result required:
+   * |unlockCardLock|, |setCardLockEnabled| and |changeCardLockPassword|.
+   */
+  void notifySuccess();
+
+  /**
+   * The success callback with boolean response:
+   * |getCardLockEnabled|, |matchMvno|, and |getServiceStateEnabled|.
+   */
+  void notifySuccessWithBoolean(in boolean aResult);
+
+  /**
+   * The success callback of |getCardLockRetryCount|.
+   *
+   * @param aCount
+   *        The number of remaining retries. -1 if unknown.
+   */
+  void notifyGetCardLockRetryCount(in long aCount);
+
+  /**
+   * The error callback of |getCardLockEnabled|, |getCardLockRetryCount|,
+   * |matchMvno|, and |getServiceStateEnabled|.
+   *
+   * @param aErrorMsg
+   *        The error message.
+   */
+  void notifyError(in DOMString aErrorMsg);
+
+  /**
+   * The error callback of |unlockCardLock|, |setCardLockEnabled| and
+   * |changeCardLockPassword|.
+   *
+   * @param aErrorMsg
+   *        The error message.
+   * @param aRetryCount
+   *        The number of remaining retries. -1 if unknown.
+   */
+  void notifyCardLockError(in DOMString aErrorMsg, in long aRetryCount);
+};
+
+%{C++
+#define ICC_SERVICE_CID \
+  { 0xbab0277a, 0x900e, 0x11e4, { 0x80, 0xc7, 0xdb, 0xd7, 0xad, 0x05, 0x24, 0x01 } }
+#define ICC_SERVICE_CONTRACTID \
+  "@mozilla.org/icc/iccservice;1"
+
+template<typename T> struct already_AddRefed;
+%}
+
+/**
+ * XPCOM Service for the selection of the ICC to be accessed.
+ */
+[scriptable, uuid(6590a04c-9ca4-11e4-ae95-570876ecc428)]
+interface nsIIccService : nsISupports
+{
+  /**
+   * Get Icc instance with specified Service Id.
+   *
+   * @param aServiceId
+   *        Started from 0 to nsIMobileConnectionService.numItems - 1;
+   *
+   * @return a nsIcc instance.
+   */
+  nsIIcc getIccByServiceId(in unsigned long aServiceId);
+};
+
+%{C++
+already_AddRefed<nsIIccService>
+NS_CreateIccService();
+%}
+
+/**
+ * XPCOM component that provides the access to the selected ICC.
+ */
+[scriptable, uuid(38a5bbe2-add6-11e4-ba9e-e390d1d19195)]
+interface nsIIcc : nsISupports
+{
+  /**
+   * Card State Constants
+   *
+   * Note: MUST be matched with enum IccCardState in MozIcc.webidl!
+   */
+  const unsigned long CARD_STATE_UNKNOWN = 0;
+  const unsigned long CARD_STATE_READY = 1;
+  const unsigned long CARD_STATE_PIN_REQUIRED = 2;
+  const unsigned long CARD_STATE_PUK_REQUIRED = 3;
+  const unsigned long CARD_STATE_PERMANENT_BLOCKED = 4;
+  const unsigned long CARD_STATE_PERSONALIZATION_IN_PROGRESS = 5;
+  const unsigned long CARD_STATE_PERSONALIZATION_READY = 6;
+  const unsigned long CARD_STATE_NETWORK_LOCKED = 7;
+  const unsigned long CARD_STATE_NETWORK_SUBSET_LOCKED = 8;
+  const unsigned long CARD_STATE_CORPORATE_LOCKED = 9;
+  const unsigned long CARD_STATE_SERVICE_PROVIDER_LOCKED = 10;
+  const unsigned long CARD_STATE_SIM_LOCKED = 11;
+  const unsigned long CARD_STATE_NETWORK_PUK_REQUIRED = 12;
+  const unsigned long CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
+  const unsigned long CARD_STATE_CORPORATE_PUK_REQUIRED = 14;
+  const unsigned long CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
+  const unsigned long CARD_STATE_SIM_PUK_REQUIRED = 16;
+  const unsigned long CARD_STATE_NETWORK1_LOCKED = 17;
+  const unsigned long CARD_STATE_NETWORK2_LOCKED = 18;
+  const unsigned long CARD_STATE_HRPD_NETWORK_LOCKED = 19;
+  const unsigned long CARD_STATE_RUIM_CORPORATE_LOCKED = 20;
+  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
+  const unsigned long CARD_STATE_RUIM_LOCKED = 22;
+  const unsigned long CARD_STATE_NETWORK1_PUK_REQUIRED = 23;
+  const unsigned long CARD_STATE_NETWORK2_PUK_REQUIRED = 24;
+  const unsigned long CARD_STATE_HRPD_NETWORK_PUK_REQUIRED = 25;
+  const unsigned long CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
+  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
+  const unsigned long CARD_STATE_RUIM_PUK_REQUIRED = 28;
+  const unsigned long CARD_STATE_ILLEGAL = 29;
+
+  const unsigned long CARD_STATE_UNDETECTED = 4294967295; // UINT32_MAX
+
+  /**
+   * Card Lock Constants
+   *
+   * Note: MUST be matched with enum IccLockType in MozIcc.webidl!
+   */
+  const unsigned long CARD_LOCK_TYPE_PIN = 0;
+  const unsigned long CARD_LOCK_TYPE_PIN2 = 1;
+  const unsigned long CARD_LOCK_TYPE_PUK = 2;
+  const unsigned long CARD_LOCK_TYPE_PUK2 = 3;
+  const unsigned long CARD_LOCK_TYPE_NCK = 4;
+  const unsigned long CARD_LOCK_TYPE_NSCK = 5;
+  const unsigned long CARD_LOCK_TYPE_NCK1 = 6;
+  const unsigned long CARD_LOCK_TYPE_NCK2 = 7;
+  const unsigned long CARD_LOCK_TYPE_HNCK = 8;
+  const unsigned long CARD_LOCK_TYPE_CCK = 9;
+  const unsigned long CARD_LOCK_TYPE_SPCK = 10;
+  const unsigned long CARD_LOCK_TYPE_PCK = 11;
+  const unsigned long CARD_LOCK_TYPE_RCCK = 12;
+  const unsigned long CARD_LOCK_TYPE_RSPCK = 13;
+  const unsigned long CARD_LOCK_TYPE_NCK_PUK = 14;
+  const unsigned long CARD_LOCK_TYPE_NSCK_PUK = 15;
+  const unsigned long CARD_LOCK_TYPE_NCK1_PUK = 16;
+  const unsigned long CARD_LOCK_TYPE_NCK2_PUK = 17;
+  const unsigned long CARD_LOCK_TYPE_HNCK_PUK = 18;
+  const unsigned long CARD_LOCK_TYPE_CCK_PUK = 19;
+  const unsigned long CARD_LOCK_TYPE_SPCK_PUK = 20;
+  const unsigned long CARD_LOCK_TYPE_PCK_PUK = 21;
+  const unsigned long CARD_LOCK_TYPE_RCCK_PUK = 22;
+  const unsigned long CARD_LOCK_TYPE_RSPCK_PUK = 23;
+  const unsigned long CARD_LOCK_TYPE_FDN = 24;
+
+  /**
+   * Contact Type Constants
+   *
+   * Note: MUST be matched with enum IccContactType in MozIcc.webidl!
+   */
+  const unsigned long CARD_CONTACT_TYPE_ADN = 0;
+  const unsigned long CARD_CONTACT_TYPE_FDN = 1;
+  const unsigned long CARD_CONTACT_TYPE_SDN = 2;
+
+  /**
+   * MVNO Type Constants
+   *
+   * Note: MUST be matched with enum IccMvnoType in MozIcc.webidl!
+   */
+  const unsigned long CARD_MVNO_TYPE_IMSI = 0;
+  const unsigned long CARD_MVNO_TYPE_SPN = 1;
+  const unsigned long CARD_MVNO_TYPE_GID = 2;
+
+  /**
+   * Card Service Constants
+   *
+   * Note: MUST be matched with enum IccService in MozIcc.webidl!
+   */
+  const unsigned long CARD_SERVICE_FDN = 0;
+
+  /**
+   * Called to register icc-related changes.
+   *
+   * 'mobileconnection' permission is required to register.
+   */
+  void registerListener(in nsIIccListener aListener);
+  void unregisterListener(in nsIIccListener aListener);
+
+  /**
+   * Information stored in this ICC.
+   */
+  readonly attribute nsIIccInfo iccInfo;
+
+  /**
+   * Indicates the state of this ICC.
+   *
+   * One of the CARD_STATE_* values.
+   */
+  readonly attribute unsigned long cardState;
+
+  /**
+   * Get the status of an ICC lock (e.g. the PIN lock).
+   *
+   * @param aLockType
+   *        One of the CARD_LOCK_TYPE_* values.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccessWithBoolean() if success.
+   *        nsIIccCallback::notifyError(), otherwise.
+   */
+  void getCardLockEnabled(in unsigned long aLockType,
+                          in nsIIccCallback aCallback);
+
+  /**
+   * Unlock a card lock.
+   *
+   * @param aLockType
+   *        One of the CARD_LOCK_TYPE_* values.
+   * @param aPassword
+   *        The password of this lock.
+   * @param aNewPin (Optional)
+   *        The new PIN to be set after PUK/PUK2 is unlock.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccess() if success.
+   *        nsIIccCallback::notifyCardLockError(), otherwise.
+   */
+  void unlockCardLock(in unsigned long aLockType,
+                      in DOMString aPassword,
+                      in DOMString aNewPin,
+                      in nsIIccCallback aCallback);
+
+  /**
+   * Enable/Disable a card lock.
+   *
+   * @param aLockType
+   *        One of the CARD_LOCK_TYPE_* values.
+   * @param aPassword
+   *        The password of this lock.
+   * @param aEnabled.
+   *        True to enable the lock. False to disable, otherwise.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccess() if success.
+   *        nsIIccCallback::notifyCardLockError(), otherwise.
+   */
+  void setCardLockEnabled(in unsigned long aLockType,
+                          in DOMString aPassword,
+                          in boolean aEnabled,
+                          in nsIIccCallback aCallback);
+
+  /**
+   * Change the password of a card lock.
+   *
+   * @param aLockType
+   *        One of the CARD_LOCK_TYPE_* values.
+   * @param aPassword
+   *        The password of this lock.
+   * @param aNewPassword.
+   *        The new password of this lock.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccess() if success.
+   *        nsIIccCallback::notifyCardLockError(), otherwise.
+   */
+  void changeCardLockPassword(in unsigned long aLockType,
+                              in DOMString aPassword,
+                              in DOMString aNewPassword,
+                              in nsIIccCallback aCallback);
+
+  /**
+   * Get the number of remaining tries of a lock.
+   *
+   * @param aLockType
+   *        One of the CARD_LOCK_TYPE_* values.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifyGetCardLockRetryCount() if success.
+   *        nsIIccCallback::notifyError(), otherwise.
+   */
+  void getCardLockRetryCount(in unsigned long aLockType,
+                             in nsIIccCallback aCallback);
+
+  /**
+   * Verify whether the passed data (matchData) matches with some ICC's field
+   * according to the mvno type (mvnoType).
+   *
+   * @param aMvnoType
+   *        One of CARD_MVNO_TYPE_* values.
+   * @param aMvnoData
+   *        Data to be compared with ICC's field.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccessWithBoolean() if success.
+   *        nsIIccCallback::notifyError(), otherwise.
+   */
+  void matchMvno(in unsigned long aMvnoType,
+                 in DOMString aMvnoData,
+                 in nsIIccCallback aCallback);
+
+  /**
+   * Retrieve the the availability of an icc service.
+   *
+   * @param aService
+   *        One of CARD_SERVICE_* values.
+   * @param aCallback
+   *        An instance of nsIIccCallback:
+   *        nsIIccCallback::notifySuccessWithBoolean() if success.
+   *        nsIIccCallback::notifyError(), otherwise.
+   */
+  void getServiceStateEnabled(in unsigned long aService,
+                              in nsIIccCallback aCallback);
+};
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccChild.cpp
@@ -0,0 +1,310 @@
+/* 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/icc/IccChild.h"
+#include "IccInfo.h"
+
+using mozilla::dom::IccInfo;
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+/**
+ * PIccChild Implementation.
+ */
+
+IccChild::IccChild()
+  : mCardState(nsIIcc::CARD_STATE_UNKNOWN)
+  , mIsAlive(true)
+{
+  MOZ_COUNT_CTOR(IccChild);
+}
+
+IccChild::~IccChild()
+{
+  MOZ_COUNT_DTOR(IccChild);
+}
+
+void
+IccChild::Init()
+{
+  OptionalIccInfoData infoData;
+
+  bool rv = SendInit(&infoData, &mCardState);
+  NS_ENSURE_TRUE_VOID(rv);
+
+  UpdateIccInfo(infoData);
+}
+
+void
+IccChild::Shutdown(){
+  if (mIsAlive) {
+    mIsAlive = false;
+    Send__delete__(this);
+  }
+
+  mListeners.Clear();
+  mIccInfo = nullptr;
+  mCardState = nsIIcc::CARD_STATE_UNKNOWN;
+}
+
+void
+IccChild::ActorDestroy(ActorDestroyReason why)
+{
+  mIsAlive = false;
+}
+
+bool
+IccChild::RecvNotifyCardStateChanged(const uint32_t& aCardState)
+{
+  mCardState = aCardState;
+
+  for (int32_t i = 0; i < mListeners.Count(); i++) {
+    mListeners[i]->NotifyCardStateChanged();
+  }
+
+  return true;
+}
+
+bool
+IccChild::RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData)
+{
+  UpdateIccInfo(aInfoData);
+
+  for (int32_t i = 0; i < mListeners.Count(); i++) {
+    mListeners[i]->NotifyIccInfoChanged();
+  }
+
+  return true;
+}
+
+PIccRequestChild*
+IccChild::AllocPIccRequestChild(const IccRequest& aRequest)
+{
+  MOZ_CRASH("Caller is supposed to manually construct a request!");
+}
+
+bool
+IccChild::DeallocPIccRequestChild(PIccRequestChild* aActor)
+{
+  delete aActor;
+  return true;
+}
+
+bool
+IccChild::SendRequest(const IccRequest& aRequest, nsIIccCallback* aRequestReply)
+{
+  NS_ENSURE_TRUE(mIsAlive, false);
+
+  // Deallocated in IccChild::DeallocPIccRequestChild().
+  IccRequestChild* actor = new IccRequestChild(aRequestReply);
+  SendPIccRequestConstructor(actor, aRequest);
+
+  return true;
+}
+
+void
+IccChild::UpdateIccInfo(const OptionalIccInfoData& aInfoData) {
+  if (aInfoData.type() == OptionalIccInfoData::Tvoid_t) {
+    mIccInfo = nullptr;
+    return;
+  }
+
+  NS_ENSURE_TRUE_VOID(aInfoData.type() == OptionalIccInfoData::TIccInfoData);
+
+  nsRefPtr<IccInfo> iccInfo;
+  const IccInfoData& infoData = aInfoData.get_IccInfoData();
+  if (infoData.iccType().EqualsLiteral("sim")
+      || infoData.iccType().EqualsLiteral("usim")) {
+    iccInfo = new GsmIccInfo(infoData);
+  } else if (infoData.iccType().EqualsLiteral("ruim")
+             || infoData.iccType().EqualsLiteral("csim")){
+    iccInfo = new CdmaIccInfo(infoData);
+  } else {
+    iccInfo = new IccInfo(infoData);
+  }
+
+  // We update the orignal one instead of replacing with a new one
+  // if the IccType is the same.
+  if (mIccInfo) {
+    nsString oldIccType;
+    nsString newIccType;
+    mIccInfo->GetIccType(oldIccType);
+    iccInfo->GetIccType(newIccType);
+
+    if (oldIccType.Equals(newIccType)) {
+      mIccInfo->Update(iccInfo);
+      return;
+    }
+  }
+
+  mIccInfo = iccInfo;
+}
+
+/**
+ * nsIIcc Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccChild, nsIIcc)
+
+NS_IMETHODIMP
+IccChild::RegisterListener(nsIIccListener *aListener)
+{
+  NS_ENSURE_TRUE(!mListeners.Contains(aListener), NS_ERROR_UNEXPECTED);
+
+  mListeners.AppendObject(aListener);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::UnregisterListener(nsIIccListener *aListener)
+{
+  NS_ENSURE_TRUE(mListeners.Contains(aListener), NS_ERROR_UNEXPECTED);
+
+  mListeners.RemoveObject(aListener);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetIccInfo(nsIIccInfo** aIccInfo)
+{
+  nsCOMPtr<nsIIccInfo> info(mIccInfo);
+  info.forget(aIccInfo);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardState(uint32_t* aCardState)
+{
+  *aCardState = mCardState;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardLockEnabled(uint32_t aLockType,
+                             nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetCardLockEnabledRequest(aLockType), aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::UnlockCardLock(uint32_t aLockType,
+                         const nsAString& aPassword,
+                         const nsAString& aNewPin,
+                         nsIIccCallback* aRequestReply)
+{
+  return SendRequest(UnlockCardLockRequest(aLockType,
+                                           nsString(aPassword),
+                                           nsString(aNewPin)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::SetCardLockEnabled(uint32_t aLockType,
+                             const nsAString& aPassword,
+                             bool aEnabled,
+                             nsIIccCallback* aRequestReply)
+{
+  return SendRequest(SetCardLockEnabledRequest(aLockType,
+                                               nsString(aPassword),
+                                               aEnabled),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::ChangeCardLockPassword(uint32_t aLockType,
+                                 const nsAString& aPassword,
+                                 const nsAString& aNewPassword,
+                                 nsIIccCallback* aRequestReply)
+{
+  return SendRequest(ChangeCardLockPasswordRequest(aLockType,
+                                                   nsString(aPassword),
+                                                   nsString(aNewPassword)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::GetCardLockRetryCount(uint32_t aLockType,
+                                nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetCardLockRetryCountRequest(aLockType), aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::MatchMvno(uint32_t aMvnoType,
+                    const nsAString& aMvnoData,
+                    nsIIccCallback* aRequestReply)
+{
+  return SendRequest(MatchMvnoRequest(aMvnoType, nsString(aMvnoData)),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccChild::GetServiceStateEnabled(uint32_t aService,
+                                 nsIIccCallback* aRequestReply)
+{
+  return SendRequest(GetServiceStateEnabledRequest(aService),
+                     aRequestReply)
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * PIccRequestChild Implementation.
+ */
+
+IccRequestChild::IccRequestChild(nsIIccCallback* aRequestReply)
+  : mRequestReply(aRequestReply)
+{
+  MOZ_COUNT_CTOR(IccRequestChild);
+  MOZ_ASSERT(aRequestReply);
+}
+
+bool
+IccRequestChild::Recv__delete__(const IccReply& aResponse)
+{
+  MOZ_ASSERT(mRequestReply);
+
+  switch(aResponse.type()) {
+    case IccReply::TIccReplySuccess:
+      return NS_SUCCEEDED(mRequestReply->NotifySuccess());
+    case IccReply::TIccReplySuccessWithBoolean: {
+      const IccReplySuccessWithBoolean& resultWithBoolean
+        = aResponse.get_IccReplySuccessWithBoolean();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifySuccessWithBoolean(resultWithBoolean.result()));
+    }
+    case IccReply::TIccReplyCardLockRetryCount: {
+      const IccReplyCardLockRetryCount& retryCount
+        = aResponse.get_IccReplyCardLockRetryCount();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifyGetCardLockRetryCount(retryCount.count()));
+    }
+    case IccReply::TIccReplyError: {
+      const IccReplyError& error = aResponse.get_IccReplyError();
+      return NS_SUCCEEDED(mRequestReply->NotifyError(error.message()));
+    }
+    case IccReply::TIccReplyCardLockError: {
+      const IccReplyCardLockError& error
+        = aResponse.get_IccReplyCardLockError();
+      return NS_SUCCEEDED(
+        mRequestReply->NotifyCardLockError(error.message(),
+                                           error.retryCount()));
+    }
+    default:
+      MOZ_CRASH("Received invalid response type!");
+  }
+
+  return true;
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccChild.h
@@ -0,0 +1,86 @@
+/* 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_icc_IccChild_h
+#define mozilla_dom_icc_IccChild_h
+
+#include "mozilla/dom/icc/PIccChild.h"
+#include "mozilla/dom/icc/PIccRequestChild.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+
+class IccInfo;
+
+namespace icc {
+
+class IccChild final : public PIccChild
+                     , public nsIIcc
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICC
+
+  explicit IccChild();
+
+void
+  Init();
+
+  void
+  Shutdown();
+
+protected:
+  virtual void
+  ActorDestroy(ActorDestroyReason why) override;
+
+  virtual PIccRequestChild*
+  AllocPIccRequestChild(const IccRequest& aRequest) override;
+
+  virtual bool
+  DeallocPIccRequestChild(PIccRequestChild* aActor) override;
+
+  virtual bool
+  RecvNotifyCardStateChanged(const uint32_t& aCardState) override;
+
+  virtual bool
+  RecvNotifyIccInfoChanged(const OptionalIccInfoData& aInfoData) override;
+
+private:
+  ~IccChild();
+
+  void
+  UpdateIccInfo(const OptionalIccInfoData& aInfoData);
+
+  bool
+  SendRequest(const IccRequest& aRequest, nsIIccCallback* aRequestReply);
+
+  nsCOMArray<nsIIccListener> mListeners;
+  nsRefPtr<IccInfo> mIccInfo;
+  uint32_t mCardState;
+  bool mIsAlive;
+};
+
+class IccRequestChild final : public PIccRequestChild
+{
+public:
+  explicit IccRequestChild(nsIIccCallback* aRequestReply);
+
+protected:
+  virtual bool
+  Recv__delete__(const IccReply& aReply) override;
+
+private:
+  virtual ~IccRequestChild() {
+    MOZ_COUNT_DTOR(IccRequestChild);
+  }
+
+  nsCOMPtr<nsIIccCallback> mRequestReply;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccChild_h
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccIPCService.cpp
@@ -0,0 +1,56 @@
+/* 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 "IccIPCService.h"
+
+#include "mozilla/dom/ContentChild.h"
+#include "mozilla/Preferences.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+NS_IMPL_ISUPPORTS(IccIPCService, nsIIccService)
+
+IccIPCService::IccIPCService()
+{
+  int32_t numRil = Preferences::GetInt("ril.numRadioInterfaces", 1);
+  mIccs.SetLength(numRil);
+}
+
+IccIPCService::~IccIPCService()
+{
+  uint32_t count = mIccs.Length();
+  for (uint32_t i = 0; i < count; i++) {
+    if (mIccs[i]) {
+      mIccs[i]->Shutdown();
+    }
+  }
+}
+
+NS_IMETHODIMP
+IccIPCService::GetIccByServiceId(uint32_t aServiceId, nsIIcc** aIcc)
+{
+  NS_ENSURE_TRUE(aServiceId < mIccs.Length(), NS_ERROR_INVALID_ARG);
+
+  if (!mIccs[aServiceId]) {
+    nsRefPtr<IccChild> child = new IccChild();
+
+    // |SendPIccConstructor| adds another reference to the child
+    // actor and removes in |DeallocPIccChild|.
+    ContentChild::GetSingleton()->SendPIccConstructor(child, aServiceId);
+    child->Init();
+
+    mIccs[aServiceId] = child;
+  }
+
+  nsCOMPtr<nsIIcc> icc(mIccs[aServiceId]);
+  icc.forget(aIcc);
+
+  return NS_OK;
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccIPCService.h
@@ -0,0 +1,35 @@
+/* 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_icc_IccIPCService_h
+#define mozilla_dom_icc_IccIPCService_h
+
+#include "nsCOMPtr.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+class IccChild;
+
+class IccIPCService final : public nsIIccService
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCSERVICE
+
+  IccIPCService();
+
+private:
+  ~IccIPCService();
+
+  nsTArray<nsRefPtr<IccChild>> mIccs;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccIPCService_h
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccParent.cpp
@@ -0,0 +1,320 @@
+/* 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/icc/IccParent.h"
+#include "nsIIccService.h"
+#include "IccInfo.h"
+
+using mozilla::dom::IccInfo;
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+namespace {
+
+static void
+GetIccInfoDataFromIccInfo(nsIIccInfo* aInInfo, IccInfoData& aOutData) {
+  aInInfo->GetIccType(aOutData.iccType());
+  aInInfo->GetIccid(aOutData.iccid());
+  aInInfo->GetMcc(aOutData.mcc());
+  aInInfo->GetMnc(aOutData.mnc());
+  aInInfo->GetSpn(aOutData.spn());
+  aInInfo->GetIsDisplayNetworkNameRequired(
+    &aOutData.isDisplayNetworkNameRequired());
+  aInInfo->GetIsDisplaySpnRequired(
+    &aOutData.isDisplaySpnRequired());
+
+  nsCOMPtr<nsIGsmIccInfo> gsmIccInfo(do_QueryInterface(aInInfo));
+  if (gsmIccInfo) {
+    gsmIccInfo->GetMsisdn(aOutData.phoneNumber());
+  }
+
+  nsCOMPtr<nsICdmaIccInfo> cdmaIccInfo(do_QueryInterface(aInInfo));
+  if (cdmaIccInfo) {
+    cdmaIccInfo->GetMdn(aOutData.phoneNumber());
+    cdmaIccInfo->GetPrlVersion(&aOutData.prlVersion());
+  }
+}
+
+} // anonymous namespace
+
+/**
+ * PIccParent Implementation.
+ */
+
+IccParent::IccParent(uint32_t aServiceId)
+{
+  MOZ_COUNT_CTOR(IccParent);
+
+  nsCOMPtr<nsIIccService> service =
+    do_GetService(ICC_SERVICE_CONTRACTID);
+
+  NS_ASSERTION(service, "Failed to get IccService!");
+
+  service->GetIccByServiceId(aServiceId, getter_AddRefs(mIcc));
+
+  NS_ASSERTION(mIcc, "Failed to get Icc with specified serviceId.");
+
+  mIcc->RegisterListener(this);
+}
+
+void
+IccParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  if (mIcc) {
+    mIcc->UnregisterListener(this);
+    mIcc = nullptr;
+  }
+}
+
+bool
+IccParent::RecvInit(OptionalIccInfoData* aInfoData,
+                    uint32_t* aCardState)
+{
+  NS_ENSURE_TRUE(mIcc, false);
+
+  nsresult rv = mIcc->GetCardState(aCardState);
+  NS_ENSURE_SUCCESS(rv, false);
+
+  nsCOMPtr<nsIIccInfo> iccInfo;
+  rv = mIcc->GetIccInfo(getter_AddRefs(iccInfo));
+  NS_ENSURE_SUCCESS(rv, false);
+
+  if (iccInfo) {
+    IccInfoData data;
+    GetIccInfoDataFromIccInfo(iccInfo, data);
+    *aInfoData = OptionalIccInfoData(data);
+
+    return true;
+  }
+
+  *aInfoData = OptionalIccInfoData(void_t());
+
+  return true;
+}
+
+PIccRequestParent*
+IccParent::AllocPIccRequestParent(const IccRequest& aRequest)
+{
+  NS_ASSERTION(mIcc, "AllocPIccRequestParent after actor was destroyed!");
+
+  IccRequestParent* actor = new IccRequestParent(mIcc);
+  // Add an extra ref for IPDL. Will be released in
+  // IccParent::DeallocPIccRequestParent().
+  actor->AddRef();
+  return actor;
+}
+
+bool
+IccParent::DeallocPIccRequestParent(PIccRequestParent* aActor)
+{
+  // IccRequestParent is refcounted, must not be freed manually.
+  static_cast<IccRequestParent*>(aActor)->Release();
+  return true;
+}
+
+bool
+IccParent::RecvPIccRequestConstructor(PIccRequestParent* aActor,
+                                      const IccRequest& aRequest)
+{
+  NS_ASSERTION(mIcc, "RecvPIccRequestConstructor after actor was destroyed!");
+
+  IccRequestParent* actor = static_cast<IccRequestParent*>(aActor);
+
+  switch (aRequest.type()) {
+    case IccRequest::TGetCardLockEnabledRequest:
+      return actor->DoRequest(aRequest.get_GetCardLockEnabledRequest());
+    case IccRequest::TUnlockCardLockRequest:
+      return actor->DoRequest(aRequest.get_UnlockCardLockRequest());
+    case IccRequest::TSetCardLockEnabledRequest:
+      return actor->DoRequest(aRequest.get_SetCardLockEnabledRequest());
+    case IccRequest::TChangeCardLockPasswordRequest:
+      return actor->DoRequest(aRequest.get_ChangeCardLockPasswordRequest());
+    case IccRequest::TGetCardLockRetryCountRequest:
+      return actor->DoRequest(aRequest.get_GetCardLockRetryCountRequest());
+    case IccRequest::TMatchMvnoRequest:
+      return actor->DoRequest(aRequest.get_MatchMvnoRequest());
+    case IccRequest::TGetServiceStateEnabledRequest:
+      return actor->DoRequest(aRequest.get_GetServiceStateEnabledRequest());
+    default:
+      MOZ_CRASH("Received invalid request type!");
+  }
+
+  return true;
+}
+
+/**
+ * nsIIccListener Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccParent, nsIIccListener)
+
+NS_IMETHODIMP
+IccParent::NotifyStkCommand(const nsAString & aMessage)
+{
+  // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyStkSessionEnd()
+{
+  // Bug 1114938 - [B2G][ICC] Refactor STK in MozIcc.webidl with IPDL.
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyCardStateChanged()
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  uint32_t cardState;
+  nsresult rv = mIcc->GetCardState(&cardState);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return SendNotifyCardStateChanged(cardState) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+NS_IMETHODIMP
+IccParent::NotifyIccInfoChanged()
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  nsCOMPtr<nsIIccInfo> iccInfo;
+  nsresult rv = mIcc->GetIccInfo(getter_AddRefs(iccInfo));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  if (!iccInfo) {
+    return SendNotifyIccInfoChanged(OptionalIccInfoData(void_t()))
+      ? NS_OK : NS_ERROR_FAILURE;
+  }
+
+  IccInfoData data;
+  GetIccInfoDataFromIccInfo(iccInfo, data);
+
+  return SendNotifyIccInfoChanged(OptionalIccInfoData(data))
+    ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * PIccRequestParent Implementation.
+ */
+
+IccRequestParent::IccRequestParent(nsIIcc* aIcc)
+  : mIcc(aIcc)
+{
+  MOZ_COUNT_CTOR(IccRequestParent);
+}
+
+void
+IccRequestParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+  mIcc = nullptr;
+}
+
+bool
+IccRequestParent::DoRequest(const GetCardLockEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetCardLockEnabled(aRequest.lockType(),
+                                               this));
+}
+
+bool
+IccRequestParent::DoRequest(const UnlockCardLockRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->UnlockCardLock(aRequest.lockType(),
+                                           aRequest.password(),
+                                           aRequest.newPin(),
+                                           this));
+}
+
+bool
+IccRequestParent::DoRequest(const SetCardLockEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->SetCardLockEnabled(aRequest.lockType(),
+                                               aRequest.password(),
+                                               aRequest.enabled(),
+                                               this));
+}
+
+bool
+IccRequestParent::DoRequest(const ChangeCardLockPasswordRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->ChangeCardLockPassword(aRequest.lockType(),
+                                                   aRequest.password(),
+                                                   aRequest.newPassword(),
+                                                   this));
+}
+
+bool
+IccRequestParent::DoRequest(const GetCardLockRetryCountRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetCardLockRetryCount(aRequest.lockType(),
+                                                  this));
+}
+
+bool
+IccRequestParent::DoRequest(const MatchMvnoRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->MatchMvno(aRequest.mvnoType(),
+                                      aRequest.mvnoData(),
+                                      this));
+}
+
+bool
+IccRequestParent::DoRequest(const GetServiceStateEnabledRequest& aRequest)
+{
+  return NS_SUCCEEDED(mIcc->GetServiceStateEnabled(aRequest.service(),
+                                                   this));
+}
+
+nsresult
+IccRequestParent::SendReply(const IccReply& aReply)
+{
+  NS_ENSURE_TRUE(mIcc, NS_ERROR_FAILURE);
+
+  return Send__delete__(this, aReply) ? NS_OK : NS_ERROR_FAILURE;
+}
+
+/**
+ * nsIIccCallback Implementation.
+ */
+
+NS_IMPL_ISUPPORTS(IccRequestParent, nsIIccCallback)
+
+NS_IMETHODIMP
+IccRequestParent::NotifySuccess()
+{
+  return SendReply(IccReplySuccess());
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifySuccessWithBoolean(bool aResult)
+{
+  return SendReply(IccReplySuccessWithBoolean(aResult));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyGetCardLockRetryCount(int32_t aCount)
+{
+  return SendReply(IccReplyCardLockRetryCount(aCount));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyError(const nsAString & aErrorMsg)
+{
+  return SendReply(IccReplyError(nsString(aErrorMsg)));
+}
+
+NS_IMETHODIMP
+IccRequestParent::NotifyCardLockError(const nsAString & aErrorMsg,
+                                      int32_t aRetryCount)
+{
+  return SendReply(IccReplyCardLockError(aRetryCount, nsString(aErrorMsg)));
+}
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/IccParent.h
@@ -0,0 +1,107 @@
+/* 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_icc_IccParent_h
+#define mozilla_dom_icc_IccParent_h
+
+#include "mozilla/dom/icc/PIccParent.h"
+#include "mozilla/dom/icc/PIccRequestParent.h"
+#include "nsIIccService.h"
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+class IccParent final : public PIccParent
+                      , public nsIIccListener
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCLISTENER
+
+  explicit IccParent(uint32_t aServiceId);
+
+protected:
+  virtual
+  ~IccParent()
+  {
+    MOZ_COUNT_DTOR(IccParent);
+  }
+
+  virtual void
+  ActorDestroy(ActorDestroyReason aWhy) override;
+
+  virtual bool
+  RecvInit(
+          OptionalIccInfoData* aInfoData,
+          uint32_t* aCardState) override;
+
+  virtual PIccRequestParent*
+  AllocPIccRequestParent(const IccRequest& aRequest) override;
+
+  virtual bool
+  DeallocPIccRequestParent(PIccRequestParent* aActor) override;
+
+  virtual bool
+  RecvPIccRequestConstructor(PIccRequestParent* aActor,
+                             const IccRequest& aRequest) override;
+
+private:
+  IccParent();
+  nsCOMPtr<nsIIcc> mIcc;
+};
+
+class IccRequestParent final : public PIccRequestParent
+                             , public nsIIccCallback
+{
+  friend class IccParent;
+
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIICCCALLBACK
+
+  explicit IccRequestParent(nsIIcc* icc);
+
+protected:
+  virtual void
+  ActorDestroy(ActorDestroyReason why) override;
+
+private:
+  ~IccRequestParent()
+  {
+    MOZ_COUNT_DTOR(IccRequestParent);
+  }
+
+  bool
+  DoRequest(const GetCardLockEnabledRequest& aRequest);
+
+  bool
+  DoRequest(const UnlockCardLockRequest& aRequest);
+
+  bool
+  DoRequest(const SetCardLockEnabledRequest& aRequest);
+
+  bool
+  DoRequest(const ChangeCardLockPasswordRequest& aRequest);
+
+  bool
+  DoRequest(const GetCardLockRetryCountRequest& aRequest);
+
+  bool
+  DoRequest(const MatchMvnoRequest& aRequest);
+
+  bool
+  DoRequest(const GetServiceStateEnabledRequest& aRequest);
+
+  nsresult
+  SendReply(const IccReply& aReply);
+
+  nsCOMPtr<nsIIcc> mIcc;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_icc_IccParent_h
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/PIcc.ipdl
@@ -0,0 +1,111 @@
+/* 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 protocol PContent;
+include protocol PIccRequest;
+include PIccTypes;
+
+using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+union OptionalIccInfoData
+{
+  void_t;
+  IccInfoData;
+};
+
+struct GetCardLockEnabledRequest
+{
+  uint32_t lockType;
+};
+
+struct UnlockCardLockRequest
+{
+  uint32_t lockType;
+  nsString password;
+  nsString newPin;
+};
+
+struct SetCardLockEnabledRequest
+{
+  uint32_t lockType;
+  nsString password;
+  bool enabled;
+};
+
+struct ChangeCardLockPasswordRequest
+{
+  uint32_t lockType;
+  nsString password;
+  nsString newPassword;
+};
+
+struct GetCardLockRetryCountRequest
+{
+  uint32_t lockType;
+};
+
+struct MatchMvnoRequest
+{
+  uint32_t mvnoType;
+  nsString mvnoData;
+};
+
+struct GetServiceStateEnabledRequest
+{
+  uint32_t service;
+};
+
+union IccRequest
+{
+  GetCardLockEnabledRequest;
+  UnlockCardLockRequest;
+  SetCardLockEnabledRequest;
+  ChangeCardLockPasswordRequest;
+  GetCardLockRetryCountRequest;
+  MatchMvnoRequest;
+  GetServiceStateEnabledRequest;
+};
+
+sync protocol PIcc
+{
+  manager PContent;
+  manages PIccRequest;
+
+child:
+  /**
+   * Notify CardStateChanged with updated CardState.
+   */
+  NotifyCardStateChanged(uint32_t aCardState);
+
+  /**
+   * Notify IccInfoChanged with updated IccInfo.
+   */
+  NotifyIccInfoChanged(OptionalIccInfoData aInfoData);
+
+parent:
+  /**
+   * Sent when the child no longer needs to use PIcc.
+   */
+  __delete__();
+
+  /**
+   * Sent when the child makes an asynchronous request to the parent.
+   */
+  PIccRequest(IccRequest aRequest);
+
+  /**
+   * Sync call to initialize the updated IccInfo/CardState.
+   */
+  sync Init()
+     returns (OptionalIccInfoData aInfoData, uint32_t aCardState);
+
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/PIccRequest.ipdl
@@ -0,0 +1,61 @@
+/* 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 protocol PIcc;
+include PIccTypes;
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+struct IccReplySuccess
+{
+};
+
+struct IccReplySuccessWithBoolean
+{
+  bool result;
+};
+
+struct IccReplyCardLockRetryCount
+{
+  int32_t count;
+};
+
+struct IccReplyError
+{
+  nsString message;
+};
+
+struct IccReplyCardLockError
+{
+  int32_t retryCount;
+  nsString message;
+};
+
+union IccReply
+{
+  // Success
+  IccReplySuccess;
+  IccReplySuccessWithBoolean;
+  IccReplyCardLockRetryCount;
+  // Error
+  IccReplyError;
+  IccReplyCardLockError;
+};
+
+protocol PIccRequest
+{
+  manager PIcc;
+
+child:
+  /**
+   * Sent when the asynchronous request has completed.
+   */
+  __delete__(IccReply response);
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/icc/ipc/PIccTypes.ipdlh
@@ -0,0 +1,24 @@
+/* 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/. */
+
+namespace mozilla {
+namespace dom {
+namespace icc {
+
+struct IccInfoData
+{
+  nsString  iccType;
+  nsString  iccid;
+  nsString  mcc;
+  nsString  mnc;
+  nsString  spn;
+  bool      isDisplayNetworkNameRequired;
+  bool      isDisplaySpnRequired;
+  nsString  phoneNumber;
+  int32_t   prlVersion;
+};
+
+} // namespace icc
+} // namespace dom
+} // namespace mozilla
\ No newline at end of file
--- a/dom/icc/moz.build
+++ b/dom/icc/moz.build
@@ -8,29 +8,48 @@ DIRS += ['interfaces']
 
 EXPORTS.mozilla.dom += [
     'Icc.h',
     'IccCardLockError.h',
     'IccInfo.h',
     'IccManager.h',
 ]
 
+EXPORTS.mozilla.dom.icc += [
+    'ipc/IccChild.h',
+    'ipc/IccParent.h',
+]
+
 UNIFIED_SOURCES += [
     'Assertions.cpp',
     'Icc.cpp',
+    'IccCallback.cpp',
     'IccCardLockError.cpp',
     "IccInfo.cpp",
     'IccListener.cpp',
     'IccManager.cpp',
+    'ipc/IccChild.cpp',
+    'ipc/IccIPCService.cpp',
+    'ipc/IccParent.cpp',
+]
+
+IPDL_SOURCES += [
+    'ipc/PIcc.ipdl',
+    'ipc/PIccRequest.ipdl',
+    'ipc/PIccTypes.ipdlh',
 ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
     EXTRA_JS_MODULES += [
         'gonk/StkProactiveCmdFactory.jsm',
     ]
+    EXTRA_COMPONENTS += [
+        'gonk/IccService.js',
+        'gonk/IccService.manifest',
+    ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -145,16 +145,17 @@
 
 #ifdef MOZ_NUWA_PROCESS
 #include <setjmp.h>
 #include "ipc/Nuwa.h"
 #endif
 
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
+#include "mozilla/dom/icc/IccChild.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionChild.h"
 #include "mozilla/dom/mobilemessage/SmsChild.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestChild.h"
 #include "mozilla/dom/PFileSystemRequestChild.h"
 #include "mozilla/dom/FileSystemTaskBase.h"
 #include "mozilla/dom/bluetooth/PBluetoothChild.h"
 #include "mozilla/dom/PFMRadioChild.h"
 #include "mozilla/ipc/InputStreamUtils.h"
@@ -178,16 +179,17 @@
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::cellbroadcast;
 using namespace mozilla::dom::devicestorage;
+using namespace mozilla::dom::icc;
 using namespace mozilla::dom::ipc;
 using namespace mozilla::dom::mobileconnection;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::dom::voicemail;
 using namespace mozilla::embedding;
 using namespace mozilla::hal_sandbox;
 using namespace mozilla::ipc;
@@ -1462,16 +1464,41 @@ ContentChild::AllocPHalChild()
 
 bool
 ContentChild::DeallocPHalChild(PHalChild* aHal)
 {
     delete aHal;
     return true;
 }
 
+PIccChild*
+ContentChild::SendPIccConstructor(PIccChild* aActor,
+                                  const uint32_t& aServiceId)
+{
+    // Add an extra ref for IPDL. Will be released in
+    // ContentChild::DeallocPIccChild().
+    static_cast<IccChild*>(aActor)->AddRef();
+    return PContentChild::SendPIccConstructor(aActor, aServiceId);
+}
+
+PIccChild*
+ContentChild::AllocPIccChild(const uint32_t& aServiceId)
+{
+    NS_NOTREACHED("No one should be allocating PIccChild actors");
+    return nullptr;
+}
+
+bool
+ContentChild::DeallocPIccChild(PIccChild* aActor)
+{
+    // IccChild is refcounted, must not be freed manually.
+    static_cast<IccChild*>(aActor)->Release();
+    return true;
+}
+
 asmjscache::PAsmJSCacheEntryChild*
 ContentChild::AllocPAsmJSCacheEntryChild(
                                     const asmjscache::OpenMode& aOpenMode,
                                     const asmjscache::WriteParams& aWriteParams,
                                     const IPC::Principal& aPrincipal)
 {
     NS_NOTREACHED("Should never get here!");
     return nullptr;
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -168,16 +168,23 @@ public:
     AllocPCrashReporterChild(const mozilla::dom::NativeThreadId& id,
                              const uint32_t& processType) override;
     virtual bool
     DeallocPCrashReporterChild(PCrashReporterChild*) override;
 
     virtual PHalChild* AllocPHalChild() override;
     virtual bool DeallocPHalChild(PHalChild*) override;
 
+    PIccChild*
+    SendPIccConstructor(PIccChild* aActor, const uint32_t& aServiceId);
+    virtual PIccChild*
+    AllocPIccChild(const uint32_t& aClientId) override;
+    virtual bool
+    DeallocPIccChild(PIccChild* aActor) override;
+
     virtual PMemoryReportRequestChild*
     AllocPMemoryReportRequestChild(const uint32_t& aGeneration,
                                    const bool& aAnonymize,
                                    const bool& aMinimizeMemoryUsage,
                                    const MaybeFileDesc& aDMDFile) override;
     virtual bool
     DeallocPMemoryReportRequestChild(PMemoryReportRequestChild* actor) override;
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -46,16 +46,17 @@
 #include "mozilla/dom/PContentBridgeParent.h"
 #include "mozilla/dom/PCycleCollectWithLogsParent.h"
 #include "mozilla/dom/PFMRadioParent.h"
 #include "mozilla/dom/PMemoryReportRequestParent.h"
 #include "mozilla/dom/asmjscache/AsmJSCache.h"
 #include "mozilla/dom/bluetooth/PBluetoothParent.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastParent.h"
 #include "mozilla/dom/devicestorage/DeviceStorageRequestParent.h"
+#include "mozilla/dom/icc/IccParent.h"
 #include "mozilla/dom/mobileconnection/MobileConnectionParent.h"
 #include "mozilla/dom/mobilemessage/SmsParent.h"
 #include "mozilla/dom/power/PowerManagerService.h"
 #include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/telephony/TelephonyParent.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/dom/voicemail/VoicemailParent.h"
 #include "mozilla/embedding/printingui/PrintingParent.h"
@@ -219,16 +220,17 @@ using base::ChildPrivileges;
 using base::KillProcess;
 
 #ifdef MOZ_CRASHREPORTER
 using namespace CrashReporter;
 #endif
 using namespace mozilla::dom::bluetooth;
 using namespace mozilla::dom::cellbroadcast;
 using namespace mozilla::dom::devicestorage;
+using namespace mozilla::dom::icc;
 using namespace mozilla::dom::indexedDB;
 using namespace mozilla::dom::power;
 using namespace mozilla::dom::mobileconnection;
 using namespace mozilla::dom::mobilemessage;
 using namespace mozilla::dom::telephony;
 using namespace mozilla::dom::voicemail;
 using namespace mozilla::embedding;
 using namespace mozilla::hal;
@@ -3382,16 +3384,37 @@ ContentParent::AllocPHalParent()
 
 bool
 ContentParent::DeallocPHalParent(hal_sandbox::PHalParent* aHal)
 {
     delete aHal;
     return true;
 }
 
+PIccParent*
+ContentParent::AllocPIccParent(const uint32_t& aServiceId)
+{
+    if (!AssertAppProcessPermission(this, "mobileconnection")) {
+        return nullptr;
+    }
+    IccParent* parent = new IccParent(aServiceId);
+    // We release this ref in DeallocPIccParent().
+    parent->AddRef();
+
+    return parent;
+}
+
+bool
+ContentParent::DeallocPIccParent(PIccParent* aActor)
+{
+    // IccParent is refcounted, must not be freed manually.
+    static_cast<IccParent*>(aActor)->Release();
+    return true;
+}
+
 PMemoryReportRequestParent*
 ContentParent::AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
                                                const bool &aAnonymize,
                                                const bool &aMinimizeMemoryUsage,
                                                const MaybeFileDesc &aDMDFile)
 {
     MemoryReportRequestParent* parent = new MemoryReportRequestParent();
     return parent;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -545,16 +545,19 @@ private:
     virtual bool RecvGetRandomValues(const uint32_t& length,
                                      InfallibleTArray<uint8_t>* randomValues) override;
 
     virtual bool RecvIsSecureURI(const uint32_t& aType, const URIParams& aURI,
                                  const uint32_t& aFlags, bool* aIsSecureURI) override;
 
     virtual bool DeallocPHalParent(PHalParent*) override;
 
+    virtual PIccParent* AllocPIccParent(const uint32_t& aServiceId) override;
+    virtual bool DeallocPIccParent(PIccParent* aActor) override;
+
     virtual PMemoryReportRequestParent*
     AllocPMemoryReportRequestParent(const uint32_t& aGeneration,
                                     const bool &aAnonymize,
                                     const bool &aMinimizeMemoryUsage,
                                     const MaybeFileDesc &aDMDFile) override;
     virtual bool DeallocPMemoryReportRequestParent(PMemoryReportRequestParent* actor) override;
 
     virtual PCycleCollectWithLogsParent*
@@ -738,17 +741,17 @@ private:
     virtual bool RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState) override;
 
     virtual bool RecvKeywordToURI(const nsCString& aKeyword,
                                   nsString* aProviderName,
                                   OptionalInputStreamParams* aPostData,
                                   OptionalURIParams* aURI) override;
 
     virtual bool RecvNotifyKeywordSearchLoading(const nsString &aProvider,
-                                                const nsString &aKeyword) override; 
+                                                const nsString &aKeyword) override;
 
     virtual void ProcessingError(Result aCode, const char* aMsgName) override;
 
     virtual bool RecvAllocateLayerTreeId(uint64_t* aId) override;
     virtual bool RecvDeallocateLayerTreeId(const uint64_t& aId) override;
 
     virtual bool RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
                                               int32_t* aStatus,
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -16,16 +16,17 @@ include protocol PCycleCollectWithLogs;
 include protocol PCrashReporter;
 include protocol PDocAccessible;
 include protocol PExternalHelperApp;
 include protocol PDeviceStorageRequest;
 include protocol PFileDescriptorSet;
 include protocol PFMRadio;
 include protocol PFileSystemRequest;
 include protocol PHal;
+include protocol PIcc;
 include protocol PProcessHangMonitor;
 include protocol PImageBridge;
 include protocol PMemoryReportRequest;
 include protocol PMobileConnection;
 include protocol PNecko;
 include protocol PPluginModule;
 include protocol PPrinting;
 include protocol POfflineCacheUpdate;
@@ -374,16 +375,17 @@ prio(normal upto urgent) sync protocol P
     manages PCycleCollectWithLogs;
     manages PDocAccessible;
     manages PDeviceStorageRequest;
     manages PFileSystemRequest;
     manages PExternalHelperApp;
     manages PFileDescriptorSet;
     manages PFMRadio;
     manages PHal;
+    manages PIcc;
     manages PMemoryReportRequest;
     manages PMobileConnection;
     manages PNecko;
     manages POfflineCacheUpdate;
     manages PPrinting;
     manages PScreenManager;
     manages PSms;
     manages PSpeechSynthesis;
@@ -650,16 +652,18 @@ parent:
 
     async GetSystemMemory(uint64_t getterId);
 
     sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
         returns (bool isSecureURI);
 
     PHal();
 
+    PIcc(uint32_t serviceId);
+
     PMobileConnection(uint32_t clientId);
 
     PNecko();
 
     PPrinting();
 
     prio(high) sync PScreenManager()
         returns (uint32_t numberOfScreens,
--- a/dom/mobileconnection/MobileConnection.cpp
+++ b/dom/mobileconnection/MobileConnection.cpp
@@ -10,27 +10,24 @@
 #include "mozilla/dom/DataErrorEvent.h"
 #include "mozilla/dom/MozClirModeEvent.h"
 #include "mozilla/dom/MozEmergencyCbModeEvent.h"
 #include "mozilla/dom/MozOtaStatusEvent.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "nsIDOMDOMRequest.h"
+#include "nsIIccInfo.h"
 #include "nsIPermissionManager.h"
 #include "nsIVariant.h"
 #include "nsJSON.h"
 #include "nsJSUtils.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 
-#ifdef MOZ_B2G_RIL
-#include "nsIIccInfo.h"
-#endif // MOZ_B2G_RIL
-
 #define MOBILECONN_ERROR_INVALID_PARAMETER NS_LITERAL_STRING("InvalidParameter")
 #define MOBILECONN_ERROR_INVALID_PASSWORD  NS_LITERAL_STRING("InvalidPassword")
 
 #ifdef CONVERT_STRING_TO_NULLABLE_ENUM
 #undef CONVERT_STRING_TO_NULLABLE_ENUM
 #endif
 #define CONVERT_STRING_TO_NULLABLE_ENUM(_string, _enumType, _enum)      \
 {                                                                       \
@@ -44,28 +41,24 @@
   }                                                                     \
 }
 
 using mozilla::ErrorResult;
 using namespace mozilla::dom;
 using namespace mozilla::dom::mobileconnection;
 
 class MobileConnection::Listener final : public nsIMobileConnectionListener
-#ifdef MOZ_B2G_RIL
-                                           , public nsIIccListener
-#endif // MOZ_B2G_RIL
+                                       , public nsIIccListener
 {
   MobileConnection* mMobileConnection;
 
 public:
   NS_DECL_ISUPPORTS
   NS_FORWARD_SAFE_NSIMOBILECONNECTIONLISTENER(mMobileConnection)
-#ifdef MOZ_B2G_RIL
   NS_FORWARD_SAFE_NSIICCLISTENER(mMobileConnection)
-#endif // MOZ_B2G_RIL
 
   explicit Listener(MobileConnection* aMobileConnection)
     : mMobileConnection(aMobileConnection)
   {
     MOZ_ASSERT(mMobileConnection);
   }
 
   void Disconnect()
@@ -76,40 +69,38 @@ public:
 
 private:
   ~Listener()
   {
     MOZ_ASSERT(!mMobileConnection);
   }
 };
 
-#ifdef MOZ_B2G_RIL
 NS_IMPL_ISUPPORTS(MobileConnection::Listener, nsIMobileConnectionListener,
                   nsIIccListener)
-#else
-NS_IMPL_ISUPPORTS(MobileConnection::Listener, nsIMobileConnectionListener)
-#endif // MOZ_B2G_RIL
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(MobileConnection)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MobileConnection,
                                                   DOMEventTargetHelper)
   // Don't traverse mListener because it doesn't keep any reference to
   // MobileConnection but a raw pointer instead. Neither does mMobileConnection
   // because it's an xpcom service owned object and is only released at shutting
   // down.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mVoice)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mData)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIccHandler)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MobileConnection,
                                                 DOMEventTargetHelper)
   tmp->Shutdown();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mVoice)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mData)
+  NS_IMPL_CYCLE_COLLECTION_UNLINK(mIccHandler)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MobileConnection)
   // MobileConnection does not expose nsIMobileConnectionListener. mListener is
   // the exposed nsIMobileConnectionListener and forwards the calls it receives
   // to us.
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
 
@@ -131,61 +122,62 @@ MobileConnection::MobileConnection(nsPID
   // for it explicitly below.
   if (!service) {
     NS_WARNING("Could not acquire nsIMobileConnectionService!");
     return;
   }
 
   nsresult rv = service->GetItemByServiceId(mClientId,
                                             getter_AddRefs(mMobileConnection));
-#ifdef MOZ_B2G_RIL
-  mIcc = do_GetService(NS_RILCONTENTHELPER_CONTRACTID);
 
-  if (NS_FAILED(rv) || !mMobileConnection || !mIcc) {
-    NS_WARNING("Could not acquire nsIMobileConnection or nsIIccProvider!");
-#else
   if (NS_FAILED(rv) || !mMobileConnection) {
     NS_WARNING("Could not acquire nsIMobileConnection!");
-#endif // MOZ_B2G_RIL
     return;
   }
 
   mListener = new Listener(this);
   mVoice = new MobileConnectionInfo(GetOwner());
   mData = new MobileConnectionInfo(GetOwner());
 
   if (CheckPermission("mobileconnection")) {
     DebugOnly<nsresult> rv = mMobileConnection->RegisterListener(mListener);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                      "Failed registering mobile connection messages with service");
     UpdateVoice();
     UpdateData();
 
-#ifdef MOZ_B2G_RIL
-    rv = mIcc->RegisterIccMsg(mClientId, mListener);
+    nsCOMPtr<nsIIccService> iccService = do_GetService(ICC_SERVICE_CONTRACTID);
+
+    if (iccService) {
+      iccService->GetIccByServiceId(mClientId, getter_AddRefs(mIccHandler));
+    }
+
+    if (!mIccHandler) {
+      NS_WARNING("Could not acquire nsIMobileConnection or nsIIcc!");
+      return;
+    }
+
+    rv = mIccHandler->RegisterListener(mListener);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                      "Failed registering icc messages with service");
     UpdateIccId();
-#endif // MOZ_B2G_RIL
   }
 }
 
 void
 MobileConnection::Shutdown()
 {
   if (mListener) {
     if (mMobileConnection) {
       mMobileConnection->UnregisterListener(mListener);
     }
 
-#ifdef MOZ_B2G_RIL
-    if (mIcc) {
-      mIcc->UnregisterIccMsg(mClientId, mListener);
+    if (mIccHandler) {
+      mIccHandler->UnregisterListener(mListener);
     }
-#endif // MOZ_B2G_RIL
 
     mListener->Disconnect();
     mListener = nullptr;
   }
 }
 
 MobileConnection::~MobileConnection()
 {
@@ -241,32 +233,30 @@ MobileConnection::UpdateData()
   nsCOMPtr<nsIMobileConnectionInfo> info;
   mMobileConnection->GetData(getter_AddRefs(info));
   mData->Update(info);
 }
 
 bool
 MobileConnection::UpdateIccId()
 {
-#ifdef MOZ_B2G_RIL
   nsAutoString iccId;
   nsCOMPtr<nsIIccInfo> iccInfo;
-  if (mIcc &&
-      NS_SUCCEEDED(mIcc->GetIccInfo(mClientId, getter_AddRefs(iccInfo))) &&
+  if (mIccHandler &&
+      NS_SUCCEEDED(mIccHandler->GetIccInfo(getter_AddRefs(iccInfo))) &&
       iccInfo) {
     iccInfo->GetIccid(iccId);
   } else {
     iccId.SetIsVoid(true);
   }
 
   if (!mIccId.Equals(iccId)) {
     mIccId = iccId;
     return true;
   }
-#endif // MOZ_B2G_RIL
 
   return false;
 }
 
 nsresult
 MobileConnection::NotifyError(nsIDOMDOMRequest* aRequest, const nsAString& aMessage)
 {
   nsCOMPtr<nsIDOMRequestService> rs = do_GetService(DOMREQUEST_SERVICE_CONTRACTID);
@@ -1129,17 +1119,16 @@ MobileConnection::NotifyLastKnownHomeNet
 }
 
 NS_IMETHODIMP
 MobileConnection::NotifyNetworkSelectionModeChanged()
 {
   return NS_OK;
 }
 
-#ifdef MOZ_B2G_RIL
 // nsIIccListener
 
 NS_IMETHODIMP
 MobileConnection::NotifyStkCommand(const nsAString& aMessage)
 {
   return NS_OK;
 }
 
@@ -1166,9 +1155,8 @@ MobileConnection::NotifyIccInfoChanged()
     return NS_OK;
   }
 
   nsRefPtr<AsyncEventDispatcher> asyncDispatcher =
     new AsyncEventDispatcher(this, NS_LITERAL_STRING("iccchange"), false);
 
   return asyncDispatcher->PostDOMEvent();
 }
-#endif // MOZ_B2G_RIL
--- a/dom/mobileconnection/MobileConnection.h
+++ b/dom/mobileconnection/MobileConnection.h
@@ -6,48 +6,41 @@
 #define mozilla_dom_MobileConnection_h
 
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/MobileConnectionInfo.h"
 #include "mozilla/dom/MobileNetworkInfo.h"
 #include "mozilla/dom/MozMobileConnectionBinding.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsIIccService.h"
 #include "nsIMobileConnectionService.h"
 #include "nsWeakPtr.h"
 
-#ifdef MOZ_B2G_RIL
-#include "nsIIccProvider.h"
-#endif // MOZ_B2G_RIL
-
 namespace mozilla {
 namespace dom {
 
 class MobileConnection final : public DOMEventTargetHelper
-                                 , private nsIMobileConnectionListener
-#ifdef MOZ_B2G_RIL
-                                 , private nsIIccListener
-#endif // MOZ_B2G_RIL
+                             , private nsIMobileConnectionListener
+                             , private nsIIccListener
 {
   /**
    * Class MobileConnection doesn't actually expose
    * nsIMobileConnectionListener. Instead, it owns an
    * nsIMobileConnectionListener derived instance mListener and passes it to
    * nsIMobileConnectionService. The onreceived events are first delivered to
    * mListener and then forwarded to its owner, MobileConnection. See also bug
    * 775997 comment #51.
    */
   class Listener;
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIMOBILECONNECTIONLISTENER
-#ifdef MOZ_B2G_RIL
   NS_DECL_NSIICCLISTENER
-#endif // MOZ_B2G_RIL
   NS_REALLY_FORWARD_NSIDOMEVENTTARGET(DOMEventTargetHelper)
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MobileConnection,
                                            DOMEventTargetHelper)
 
   MobileConnection(nsPIDOMWindow *aWindow, uint32_t aClientId);
 
   void
   Shutdown();
@@ -164,19 +157,17 @@ public:
 
 private:
   ~MobileConnection();
 
 private:
   uint32_t mClientId;
   nsString mIccId;
   nsCOMPtr<nsIMobileConnection> mMobileConnection;
-#ifdef MOZ_B2G_RIL
-  nsCOMPtr<nsIIccProvider> mIcc;
-#endif // MOZ_B2G_RIL
+  nsCOMPtr<nsIIcc> mIccHandler;
   nsRefPtr<Listener> mListener;
   nsRefPtr<MobileConnectionInfo> mVoice;
   nsRefPtr<MobileConnectionInfo> mData;
 
   bool
   CheckPermission(const char* aType) const;
 
   void
--- a/dom/mobilemessage/gonk/MmsService.js
+++ b/dom/mobilemessage/gonk/MmsService.js
@@ -401,17 +401,17 @@ MmsConnection.prototype = {
     if (!this.connected) {
       this.pendingCallbacks.push(callback);
 
       let errorStatus;
       if (getRadioDisabledState()) {
         if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
         errorStatus = _HTTP_STATUS_RADIO_DISABLED;
       } else if (this.radioInterface.rilContext.cardState !=
-                 Ci.nsIIccProvider.CARD_STATE_READY) {
+                 Ci.nsIIcc.CARD_STATE_READY) {
         if (DEBUG) debug("Error! SIM card is not ready when sending MMS.");
         errorStatus = _HTTP_STATUS_NO_SIM_CARD;
       }
       if (errorStatus != null) {
         this.flushPendingCallbacks(errorStatus);
         return true;
       }
 
--- a/dom/mobilemessage/gonk/SmsService.js
+++ b/dom/mobilemessage/gonk/SmsService.js
@@ -881,17 +881,17 @@ SmsService.prototype = {
       if (!gPhoneNumberUtils.isPlainPhoneNumber(options.number)) {
         if (DEBUG) debug("Error! Address is invalid when sending SMS: " + options.number);
         errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR;
       } else if (radioState == Ci.nsIMobileConnection.MOBILE_RADIO_STATE_UNKNOWN ||
                  radioState == Ci.nsIMobileConnection.MOBILE_RADIO_STATE_DISABLED) {
         if (DEBUG) debug("Error! Radio is disabled when sending SMS.");
         errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
       } else if (gRadioInterfaces[aServiceId].rilContext.cardState !=
-                 Ci.nsIIccProvider.CARD_STATE_READY) {
+                 Ci.nsIIcc.CARD_STATE_READY) {
         if (DEBUG) debug("Error! SIM card is not ready when sending SMS.");
         errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
       }
       if (errorCode) {
         if (aSilent) {
           aRequest.notifySendMessageFailed(errorCode, aSendingMessage);
           return;
         }
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -59,16 +59,17 @@ DIRS += [
     'encoding',
     'events',
     'fetch',
     'filehandle',
     'filesystem',
     'fmradio',
     'geolocation',
     'html',
+    'icc',
     'json',
     'jsurl',
     'asmjscache',
     'mathml',
     'media',
     'messages',
     'mobileconnection',
     'notification',
@@ -117,17 +118,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
     DIRS += [
         'speakermanager',
         'tethering',
         'wifi',
     ]
 
 if CONFIG['MOZ_B2G_RIL']:
     DIRS += [
-        'icc',
         'wappush',
     ]
 
 if CONFIG['MOZ_PAY']:
     DIRS += ['payment']
 
 if CONFIG['MOZ_GAMEPAD']:
     DIRS += ['gamepad']
--- a/dom/phonenumberutils/PhoneNumberUtils.jsm
+++ b/dom/phonenumberutils/PhoneNumberUtils.jsm
@@ -18,19 +18,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/PhoneNumberNormalizer.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "MCC_ISO3166_TABLE",
                                   "resource://gre/modules/mcc_iso3166_table.jsm");
 
 #ifdef MOZ_B2G_RIL
 XPCOMUtils.defineLazyServiceGetter(this, "mobileConnection",
                                    "@mozilla.org/mobileconnection/mobileconnectionservice;1",
                                    "nsIMobileConnectionService");
-XPCOMUtils.defineLazyServiceGetter(this, "icc",
-                                   "@mozilla.org/ril/content-helper;1",
-                                   "nsIIccProvider");
+XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
+                                   "@mozilla.org/icc/iccservice;1",
+                                   "nsIIccService");
 #endif
 
 this.PhoneNumberUtils = {
   init: function() {
     ppmm.addMessageListener(["PhoneNumberService:FuzzyMatch"], this);
   },
   //  1. See whether we have a network mcc
   //  2. If we don't have that, look for the simcard mcc
@@ -41,32 +41,33 @@ this.PhoneNumberUtils = {
   _mcc: '724',
 
   getCountryName: function getCountryName() {
     let mcc;
     let countryName;
 
 #ifdef MOZ_B2G_RIL
     // TODO: Bug 926740 - PhoneNumberUtils for multisim
-    // In Multi-sim, there is more than one client in 
-    // iccProvider/mobileConnectionProvider. Each client represents a
+    // In Multi-sim, there is more than one client in
+    // iccService/mobileConnectionService. Each client represents a
     // icc/mobileConnection service. To maintain the backward compatibility with
     // single sim, we always use client 0 for now. Adding support for multiple
     // sim will be addressed in bug 926740, if needed.
     let clientId = 0;
 
     // Get network mcc
     let connection = mobileConnection.getItemByServiceId(clientId);
     let voice = connection && connection.voice;
     if (voice && voice.network && voice.network.mcc) {
       mcc = voice.network.mcc;
     }
 
     // Get SIM mcc
-    let iccInfo = icc.getIccInfo(clientId);
+    let icc = gIccService.getIccByServiceId(clientId);
+    let iccInfo = icc && icc.iccInfo;
     if (!mcc && iccInfo && iccInfo.mcc) {
       mcc = iccInfo.mcc;
     }
 
     // Attempt to grab last known sim mcc from prefs
     if (!mcc) {
       try {
         mcc = Services.prefs.getCharPref("ril.lastKnownSimMcc");
--- a/dom/push/PushService.jsm
+++ b/dom/push/PushService.jsm
@@ -1770,24 +1770,25 @@ this.PushService = {
     try {
       if (!prefs.get("udp.wakeupEnabled")) {
         debug("UDP support disabled, we do not send any carrier info");
         throw new Error("UDP disabled");
       }
 
       let nm = Cc["@mozilla.org/network/manager;1"].getService(Ci.nsINetworkManager);
       if (nm.active && nm.active.type == Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE) {
-        let icc = Cc["@mozilla.org/ril/content-helper;1"].getService(Ci.nsIIccProvider);
+        let iccService = Cc["@mozilla.org/icc/iccservice;1"].getService(Ci.nsIIccService);
         // TODO: Bug 927721 - PushService for multi-sim
-        // In Multi-sim, there is more than one client in iccProvider. Each
-        // client represents a icc service. To maintain backward compatibility
+        // In Multi-sim, there is more than one client in iccService. Each
+        // client represents a icc handle. To maintain backward compatibility
         // with single sim, we always use client 0 for now. Adding support
         // for multiple sim will be addressed in bug 927721, if needed.
         let clientId = 0;
-        let iccInfo = icc.getIccInfo(clientId);
+        let icc = iccService.getIccByServiceId(clientId);
+        let iccInfo = icc && icc.iccInfo;
         if (iccInfo) {
           debug("Running on mobile data");
 
           let ips = {};
           let prefixLengths = {};
           nm.active.getAddresses(ips, prefixLengths);
 
           return {
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -93,18 +93,18 @@ IccInfo.prototype = {
 
   // nsIIccInfo
 
   iccType: null,
   iccid: null,
   mcc: null,
   mnc: null,
   spn: null,
-  isDisplayNetworkNameRequired: null,
-  isDisplaySpnRequired: null
+  isDisplayNetworkNameRequired: false,
+  isDisplaySpnRequired: false
 };
 
 function GsmIccInfo() {}
 GsmIccInfo.prototype = {
   __proto__: IccInfo.prototype,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
                                          Ci.nsIIccInfo]),
 
@@ -126,44 +126,49 @@ CdmaIccInfo.prototype = {
 };
 
 function RILContentHelper() {
   this.updateDebugFlag();
 
   this.numClients = gNumRadioInterfaces;
   if (DEBUG) debug("Number of clients: " + this.numClients);
 
+  this._iccs = [];
   this.rilContexts = [];
   for (let clientId = 0; clientId < this.numClients; clientId++) {
+    this._iccs.push(new Icc(this, clientId));
     this.rilContexts[clientId] = {
-      cardState: Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
+      cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
       iccInfo: null
     };
   }
 
   this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   this._windowsMap = [];
+  this._requestMap = [];
   this._iccListeners = [];
   this._iccChannelCallback = [];
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
 }
 
 RILContentHelper.prototype = {
   __proto__: DOMRequestIpcHelper.prototype,
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccProvider,
+                                         Ci.nsIIccService,
                                          Ci.nsIObserver,
                                          Ci.nsISupportsWeakReference]),
   classID:   RILCONTENTHELPER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
                                     classDescription: "RILContentHelper",
-                                    interfaces: [Ci.nsIIccProvider]}),
+                                    interfaces: [Ci.nsIIccProvider,
+                                                 Ci.nsIIccService]}),
 
   updateDebugFlag: function() {
     try {
       DEBUG = RIL.DEBUG_CONTENT_HELPER ||
               Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
     } catch (e) {}
   },
 
@@ -201,16 +206,18 @@ RILContentHelper.prototype = {
       }
     }
 
     this.updateInfo(newInfo, rilContext.iccInfo);
   },
 
   _windowsMap: null,
 
+  _requestMap: null,
+
   rilContexts: null,
 
   getRilContext: function(clientId) {
     // Update ril contexts by sending IPC message to chrome only when the first
     // time we require it. The information will be updated by following info
     // changed messages.
     this.getRilContext = function getRilContext(clientId) {
       return this.rilContexts[clientId];
@@ -229,152 +236,16 @@ RILContentHelper.prototype = {
 
     return this.rilContexts[clientId];
   },
 
   /**
    * nsIIccProvider
    */
 
-  getIccInfo: function(clientId) {
-    let context = this.getRilContext(clientId);
-    return context && context.iccInfo;
-  },
-
-  getCardState: function(clientId) {
-    let context = this.getRilContext(clientId);
-    return context && context.cardState;
-  },
-
-  matchMvno: function(clientId, window, mvnoType, mvnoData) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-
-    cpmm.sendAsyncMessage("RIL:MatchMvno", {
-      clientId: clientId,
-      data: {
-        requestId: requestId,
-        mvnoType: mvnoType,
-        mvnoData: mvnoData
-      }
-    });
-    return request;
-  },
-
-  getCardLockEnabled: function(clientId, window, lockType) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:GetCardLockEnabled", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  unlockCardLock: function(clientId, window, lockType, password, newPin) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        newPin: newPin,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  setCardLockEnabled: function(clientId, window, lockType, password, enabled) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:SetCardLockEnabled", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        enabled: enabled,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  changeCardLockPassword: function(clientId, window, lockType, password,
-                                   newPassword) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:ChangeCardLockPassword", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        password: password,
-        newPassword: newPassword,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
-  getCardLockRetryCount: function(clientId, window, lockType) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
-    this._windowsMap[requestId] = window;
-
-    cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
-      clientId: clientId,
-      data: {
-        lockType: lockType,
-        requestId: requestId
-      }
-    });
-    return request;
-  },
-
   sendStkResponse: function(clientId, window, command, response) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
     response.command = command;
     cpmm.sendAsyncMessage("RIL:SendStkResponse", {
       clientId: clientId,
@@ -540,37 +411,16 @@ RILContentHelper.prototype = {
         contact: iccContact,
         pin2: pin2
       }
     });
 
     return request;
   },
 
-  getServiceState: function(clientId, window, service) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    return new window.Promise((resolve, reject) => {
-      let requestId =
-        this.getPromiseResolverId({resolve: resolve, reject: reject});
-      this._windowsMap[requestId] = window;
-
-      cpmm.sendAsyncMessage("RIL:GetServiceState", {
-        clientId: clientId,
-        data: {
-          requestId: requestId,
-          service: service
-        }
-      });
-    });
-  },
-
   _iccListeners: null,
 
   registerListener: function(listenerType, clientId, listener) {
     if (!this[listenerType]) {
       return;
     }
     let listeners = this[listenerType][clientId];
     if (!listeners) {
@@ -716,72 +566,66 @@ RILContentHelper.prototype = {
     }
 
     let data = msg.json.data;
     let clientId = msg.json.clientId;
     switch (msg.name) {
       case "RIL:CardStateChanged":
         if (this.rilContexts[clientId].cardState != data.cardState) {
           this.rilContexts[clientId].cardState = data.cardState;
-          this._deliverEvent(clientId,
-                             "_iccListeners",
-                             "notifyCardStateChanged",
-                             null);
+          this._deliverIccEvent(clientId,
+                                "notifyCardStateChanged",
+                                null);
         }
         break;
       case "RIL:IccInfoChanged":
         this.updateIccInfo(clientId, data);
-        this._deliverEvent(clientId,
-                           "_iccListeners",
-                           "notifyIccInfoChanged",
-                           null);
+        this._deliverIccEvent(clientId,
+                              "notifyIccInfoChanged",
+                              null);
         break;
       case "RIL:GetCardLockResult": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          this.fireRequestError(requestId, data.errorMsg);
+          callback.notifyError(data.errorMsg);
           break;
         }
 
-        this.fireRequestSuccess(requestId,
-                                Cu.cloneInto({ enabled: data.enabled },
-                                             requestWindow));
+        callback.notifySuccessWithBoolean(data.enabled);
         break;
       }
       case "RIL:SetUnlockCardLockResult": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          let cardLockError = new requestWindow.IccCardLockError(data.errorMsg,
-                                                                 data.retryCount);
-          this.fireRequestDetailedError(requestId, cardLockError);
+          let retryCount =
+            (data.retryCount !== undefined) ? data.retryCount : -1;
+          callback.notifyCardLockError(data.errorMsg, retryCount);
           break;
         }
 
-        this.fireRequestSuccess(requestId, null);
+        callback.notifySuccess();
         break;
       }
       case "RIL:CardLockRetryCount": {
         let requestId = data.requestId;
-        let requestWindow = this._windowsMap[requestId];
-        delete this._windowsMap[requestId];
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
 
         if (data.errorMsg) {
-          this.fireRequestError(data.requestId, data.errorMsg);
+          callback.notifyError(data.errorMsg);
           break;
         }
 
-        this.fireRequestSuccess(data.requestId,
-                                Cu.cloneInto({ retryCount: data.retryCount },
-                                             requestWindow));
+        callback.notifyGetCardLockRetryCount(data.retryCount);
         break;
       }
       case "RIL:StkCommand":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
                            [JSON.stringify(data)]);
         break;
       case "RIL:StkSessionEnd":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
@@ -796,22 +640,40 @@ RILContentHelper.prototype = {
         this.handleIccExchangeAPDU(data);
         break;
       case "RIL:ReadIccContacts":
         this.handleReadIccContacts(data);
         break;
       case "RIL:UpdateIccContact":
         this.handleUpdateIccContact(data);
         break;
-      case "RIL:MatchMvno":
-        this.handleSimpleRequest(data.requestId, data.errorMsg, data.result);
+      case "RIL:MatchMvno": {
+        let requestId = data.requestId;
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
+
+        if (data.errorMsg) {
+          callback.notifyError(data.errorMsg);
+          break;
+        }
+        callback.notifySuccessWithBoolean(data.result);
         break;
-      case "RIL:GetServiceState":
-        this.handleGetServiceState(data);
+      }
+      case "RIL:GetServiceState": {
+        let requestId = data.requestId;
+        let callback = this._requestMap[requestId];
+        delete this._requestMap[requestId];
+
+        if (data.errorMsg) {
+          callback.notifyError(data.errorMsg);
+          break;
+        }
+        callback.notifySuccessWithBoolean(data.result);
         break;
+      }
     }
   },
 
   handleSimpleRequest: function(requestId, errorMsg, result) {
     if (errorMsg) {
       this.fireRequestError(requestId, errorMsg);
     } else {
       this.fireRequestSuccess(requestId, result);
@@ -904,30 +766,16 @@ RILContentHelper.prototype = {
     }
 
     let contact = new window.mozContact(prop);
     contact.id = iccContact.contactId;
 
     this.fireRequestSuccess(message.requestId, contact);
   },
 
-  handleGetServiceState: function(message) {
-    let requestId = message.requestId;
-    let requestWindow = this._windowsMap[requestId];
-    delete this._windowsMap[requestId];
-
-    let resolver = this.takePromiseResolver(requestId);
-    if (message.errorMsg) {
-      resolver.reject(new requestWindow.DOMError(message.errorMsg));
-      return;
-    }
-
-    resolver.resolve(message.result);
-  },
-
   _deliverEvent: function(clientId, listenerType, name, args) {
     if (!this[listenerType]) {
       return;
     }
     let thisListeners = this[listenerType][clientId];
     if (!thisListeners) {
       return;
     }
@@ -942,12 +790,241 @@ RILContentHelper.prototype = {
         throw new Error("No handler for " + name);
       }
       try {
         handler.apply(listener, args);
       } catch (e) {
         if (DEBUG) debug("listener for " + name + " threw an exception: " + e);
       }
     }
+  },
+
+  /**
+   * nsIIccService interface.
+   */
+
+  _iccs: null, // An array of Icc instances.
+
+  getIccByServiceId: function(serviceId) {
+    let icc = this._iccs[serviceId];
+    if (!icc) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    return icc;
+  },
+
+  /**
+   * Bridge APIs from nsIIccService to nsIIccProvider
+   */
+
+  _deliverIccEvent: function(clientId, name, args) {
+    let icc = this._iccs[clientId];
+    if (!icc) {
+      if (DEBUG) debug("_deliverIccEvent: Invalid clientId: " + clientId);
+      return;
+    }
+
+    icc.deliverListenerEvent(name, args);
+  },
+
+  getIccInfo: function(clientId) {
+    let context = this.getRilContext(clientId);
+    return context && context.iccInfo;
+  },
+
+  getCardState: function(clientId) {
+    let context = this.getRilContext(clientId);
+    return context && context.cardState;
+  },
+
+  matchMvno: function(clientId, mvnoType, mvnoData, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:MatchMvno", {
+      clientId: clientId,
+      data: {
+        requestId: requestId,
+        mvnoType: mvnoType,
+        mvnoData: mvnoData
+      }
+    });
+  },
+
+  getCardLockEnabled: function(clientId, lockType, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetCardLockEnabled", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        requestId: requestId
+      }
+    });
+  },
+
+  unlockCardLock: function(clientId, lockType, password, newPin, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        newPin: newPin,
+        requestId: requestId
+      }
+    });
+  },
+
+  setCardLockEnabled: function(clientId, lockType, password, enabled, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:SetCardLockEnabled", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        enabled: enabled,
+        requestId: requestId
+      }
+    });
+  },
+
+  changeCardLockPassword: function(clientId, lockType, password, newPassword,
+                                   callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:ChangeCardLockPassword", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        password: password,
+        newPassword: newPassword,
+        requestId: requestId
+      }
+    });
+  },
+
+  getCardLockRetryCount: function(clientId, lockType, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
+      clientId: clientId,
+      data: {
+        lockType: lockType,
+        requestId: requestId
+      }
+    });
+  },
+
+  getServiceStateEnabled: function(clientId, service, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._requestMap[requestId] = callback;
+
+    cpmm.sendAsyncMessage("RIL:GetServiceState", {
+      clientId: clientId,
+      data: {
+        requestId: requestId,
+        service: service
+      }
+    });
+  }
+};
+
+function Icc(aIccProvider, aClientId) {
+  this._iccProvider = aIccProvider;
+  this._clientId = aClientId;
+  this._listeners = [];
+}
+Icc.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
+
+  _iccProvider: null,
+  _clientId: -1,
+  _listeners: null,
+
+  deliverListenerEvent: function(aName, aArgs) {
+    let listeners = this._listeners.slice();
+    for (let listener of listeners) {
+      if (this._listeners.indexOf(listener) === -1) {
+        continue;
+      }
+      let handler = listener[aName];
+      if (typeof handler != "function") {
+        throw new Error("No handler for " + aName);
+      }
+      try {
+        handler.apply(listener, aArgs);
+      } catch (e) {
+        if (DEBUG) {
+          debug("listener for " + aName + " threw an exception: " + e);
+        }
+      }
+    }
+  },
+
+  /**
+   * nsIIcc interface.
+   */
+  registerListener: function(aListener) {
+    if (this._listeners.indexOf(aListener) >= 0) {
+      throw Cr.NS_ERROR_UNEXPECTED;
+    }
+
+    this._listeners.push(aListener);
+    cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
+  },
+
+  unregisterListener: function(aListener) {
+    let index = this._listeners.indexOf(aListener);
+    if (index >= 0) {
+      this._listeners.splice(index, 1);
+    }
+  },
+
+  get iccInfo() {
+    return this._iccProvider.getIccInfo(this._clientId);
+  },
+
+  get cardState() {
+    return this._iccProvider.getCardState(this._clientId);
+  },
+
+  getCardLockEnabled: function(aLockType, aCallback) {
+    this._iccProvider.getCardLockEnabled(this._clientId, aLockType, aCallback);
+  },
+
+  unlockCardLock: function(aLockType, aPassword, aNewPin, aCallback) {
+    this._iccProvider.unlockCardLock(this._clientId, aLockType,
+                                     aPassword, aNewPin, aCallback);
+  },
+
+  setCardLockEnabled: function(aLockType, aPassword, aEnabled, aCallback) {
+    this._iccProvider.setCardLockEnabled(this._clientId, aLockType,
+                                         aPassword, aEnabled, aCallback);
+  },
+
+  changeCardLockPassword: function(aLockType, aPassword, aNewPassword, aCallback) {
+    this._iccProvider.changeCardLockPassword(this._clientId, aLockType,
+                                             aPassword, aNewPassword, aCallback);
+  },
+
+  getCardLockRetryCount: function(aLockType, aCallback) {
+    this._iccProvider.getCardLockRetryCount(this._clientId, aLockType, aCallback);
+  },
+
+  matchMvno: function(aMvnoType, aMvnoData, aCallback) {
+    this._iccProvider.matchMvno(this._clientId, aMvnoType, aMvnoData, aCallback);
+  },
+
+  getServiceStateEnabled: function(aService, aCallback) {
+    this._iccProvider.getServiceStateEnabled(this._clientId, aService, aCallback);
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper]);
--- a/dom/system/gonk/RILContentHelper.manifest
+++ b/dom/system/gonk/RILContentHelper.manifest
@@ -8,11 +8,13 @@
 #
 # Unless required by applicable law or agreed to in writing, software
 # distributed under the License is distributed on an "AS IS" BASIS,
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
 # RILContentHelper.js
+# TODO: Bug 815526, deprecate RILContentHelper:
+#       To be removed from b2g/installer/package-manifest.in as well.
 component {472816e1-1fd6-4405-996c-806f9ea68174} RILContentHelper.js
 contract @mozilla.org/ril/content-helper;1 {472816e1-1fd6-4405-996c-806f9ea68174}
 category profile-after-change RILContentHelper @mozilla.org/ril/content-helper;1
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -82,16 +82,17 @@ const INT32_MAX = 2147483647;
 const NETWORK_TYPE_UNKNOWN     = Ci.nsINetworkInterface.NETWORK_TYPE_UNKNOWN;
 const NETWORK_TYPE_WIFI        = Ci.nsINetworkInterface.NETWORK_TYPE_WIFI;
 const NETWORK_TYPE_MOBILE      = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE;
 const NETWORK_TYPE_MOBILE_MMS  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_MMS;
 const NETWORK_TYPE_MOBILE_SUPL = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_SUPL;
 const NETWORK_TYPE_MOBILE_IMS  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_IMS;
 const NETWORK_TYPE_MOBILE_DUN  = Ci.nsINetworkInterface.NETWORK_TYPE_MOBILE_DUN;
 
+// TODO: Bug 815526, deprecate RILContentHelper.
 const RIL_IPC_ICCMANAGER_MSG_NAMES = [
   "RIL:GetRilContext",
   "RIL:SendStkResponse",
   "RIL:SendStkMenuSelection",
   "RIL:SendStkTimerExpiration",
   "RIL:SendStkEventDownload",
   "RIL:GetCardLockEnabled",
   "RIL:UnlockCardLock",
@@ -122,16 +123,20 @@ function updateDebugFlag() {
   DEBUG = RIL.DEBUG_RIL || debugPref;
 }
 updateDebugFlag();
 
 function debug(s) {
   dump("-*- RadioInterfaceLayer: " + s + "\n");
 }
 
+XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
+                                   "@mozilla.org/icc/gonkiccservice;1",
+                                   "nsIGonkIccService");
+
 XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
                                    "@mozilla.org/mobilemessage/mobilemessageservice;1",
                                    "nsIMobileMessageService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSmsService",
                                    "@mozilla.org/sms/gonksmsservice;1",
                                    "nsIGonkSmsService");
 
@@ -172,16 +177,17 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "nsIIccMessenger");
 
 XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() {
   let stk = {};
   Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk);
   return stk.StkProactiveCmdFactory;
 });
 
+// TODO: Bug 815526, deprecate RILContentHelper.
 XPCOMUtils.defineLazyGetter(this, "gMessageManager", function() {
   return {
     QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener,
                                            Ci.nsIObserver]),
 
     ril: null,
 
     // Manage message targets in terms of topic. Only the authorized and
@@ -881,18 +887,18 @@ IccInfo.prototype = {
 
   // nsIIccInfo
 
   iccType: null,
   iccid: null,
   mcc: null,
   mnc: null,
   spn: null,
-  isDisplayNetworkNameRequired: null,
-  isDisplaySpnRequired: null
+  isDisplayNetworkNameRequired: false,
+  isDisplaySpnRequired: false
 };
 
 function GsmIccInfo() {}
 GsmIccInfo.prototype = {
   __proto__: IccInfo.prototype,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
                                          Ci.nsIIccInfo]),
 
@@ -1418,28 +1424,29 @@ function RadioInterfaceLayer() {
   this.radioInterfaces = [];
   for (let clientId = 0; clientId < numIfaces; clientId++) {
     this.radioInterfaces.push(new RadioInterface(clientId, workerMessenger));
   }
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
 
-  gMessageManager.init(this);
+  gMessageManager.init(this); // TODO: Bug 815526, deprecate RILContentHelper.
   gRadioEnabledController.init(this);
   gDataConnectionManager.init(this);
 }
 RadioInterfaceLayer.prototype = {
 
   classID:   RADIOINTERFACELAYER_CID,
   classInfo: XPCOMUtils.generateCI({classID: RADIOINTERFACELAYER_CID,
                                     classDescription: "RadioInterfaceLayer",
                                     interfaces: [Ci.nsIRadioInterfaceLayer]}),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRadioInterfaceLayer,
+                                         Ci.nsIRadioInterfaceLayer_new, // TODO: Bug 815526, deprecate RILContentHelper.
                                          Ci.nsIObserver]),
 
   /**
    * nsIObserver interface methods.
    */
 
   observe: function(subject, topic, data) {
     switch (topic) {
@@ -1671,23 +1678,24 @@ WorkerMessenger.prototype = {
     }).bind(this));
   }
 };
 
 function RadioInterface(aClientId, aWorkerMessenger) {
   this.clientId = aClientId;
   this.workerMessenger = {
     send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId),
+    // TODO: Bug 815526, deprecate RILContentHelper.
     sendWithIPCMessage:
       aWorkerMessenger.sendWithIPCMessage.bind(aWorkerMessenger, aClientId),
   };
   aWorkerMessenger.registerClient(aClientId, this);
 
   this.rilContext = {
-    cardState:      Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
+    cardState:      Ci.nsIIcc.CARD_STATE_UNKNOWN,
     iccInfo:        null,
     imsi:           null
   };
 
   this.operatorInfo = {};
 
   let lock = gSettingsService.createLock();
 
@@ -1775,22 +1783,24 @@ RadioInterface.prototype = {
       }
     }
 
     return false;
   },
 
   isCardPresent: function() {
     let cardState = this.rilContext.cardState;
-    return cardState !== Ci.nsIIccProvider.CARD_STATE_UNDETECTED &&
-      cardState !== Ci.nsIIccProvider.CARD_STATE_UNKNOWN;
+    return cardState !== Ci.nsIIcc.CARD_STATE_UNDETECTED &&
+      cardState !== Ci.nsIIcc.CARD_STATE_UNKNOWN;
   },
 
   /**
    * Process a message from the content process.
+   *
+   * TODO: Bug 815526, deprecate RILContentHelper
    */
   receiveMessage: function(msg) {
     switch (msg.name) {
       case "RIL:GetRilContext":
         // This message is sync.
         return this.rilContext;
       case "RIL:GetCardLockEnabled":
         this.workerMessenger.sendWithIPCMessage(msg, "iccGetCardLockEnabled",
@@ -1911,16 +1921,19 @@ RadioInterface.prototype = {
         // gRadioEnabledController should know the radio state for each client,
         // so notify gRadioEnabledController here.
         gRadioEnabledController.notifyRadioStateChanged(this.clientId,
                                                         message.radioState);
         break;
       case "cardstatechange":
         this.rilContext.cardState = message.cardState;
         gRadioEnabledController.receiveCardState(this.clientId);
+        gIccService.notifyCardStateChanged(this.clientId,
+                                           this.rilContext.cardState);
+        // TODO: Bug 815526, deprecate RILContentHelper.
         gMessageManager.sendIccMessage("RIL:CardStateChanged",
                                        this.clientId, message);
         break;
       case "sms-received":
         this.handleSmsReceived(message);
         break;
       case "cellbroadcast-received":
         this.handleCellbroadcastMessageReceived(message);
@@ -1928,42 +1941,45 @@ RadioInterface.prototype = {
       case "nitzTime":
         this.handleNitzTime(message);
         break;
       case "iccinfochange":
         this.handleIccInfoChange(message);
         break;
       case "iccimsi":
         this.rilContext.imsi = message.imsi;
+        gIccService.notifyImsiChanged(this.clientId, this.rilContext.imsi);
         break;
       case "iccmbdn":
         this.handleIccMbdn(message);
         break;
       case "iccmwis":
         this.handleIccMwis(message.mwi);
         break;
       case "stkcommand":
         this.handleStkProactiveCommand(message);
         break;
       case "stksessionend":
+        // TODO: Bug 815526, deprecate RILContentHelper.
         gMessageManager.sendIccMessage("RIL:StkSessionEnd", this.clientId, null);
         break;
       case "cdma-info-rec-received":
         this.handleCdmaInformationRecords(message.records);
         break;
       default:
         throw new Error("Don't know about this message type: " +
                         message.rilMessageType);
     }
   },
 
   // Matches the mvnoData pattern with imsi. Characters 'x' and 'X' are skipped
   // and not compared. E.g., if the mvnoData passed is '310260x10xxxxxx',
   // then the function returns true only if imsi has the same first 6 digits,
   // 8th and 9th digit.
+  // TODO: Bug 815526, deprecate RILContentHelper.
   isImsiMatches: function(mvnoData) {
     let imsi = this.rilContext.imsi;
 
     // This should not be an error, but a mismatch.
     if (mvnoData.length > imsi.length) {
       return false;
     }
 
@@ -1971,16 +1987,17 @@ RadioInterface.prototype = {
       let c = mvnoData[i];
       if ((c !== 'x') && (c !== 'X') && (c !== imsi[i])) {
         return false;
       }
     }
     return true;
   },
 
+  // TODO: Bug 815526, deprecate RILContentHelper.
   matchMvno: function(target, message) {
     if (DEBUG) this.debug("matchMvno: " + JSON.stringify(message));
 
     if (!message || !message.mvnoData) {
       message.errorMsg = RIL.GECKO_ERROR_INVALID_PARAMETER;
     }
 
     if (!message.errorMsg) {
@@ -2208,16 +2225,18 @@ RadioInterface.prototype = {
     // Note: returnNumber and returnMessage is not available from UICC.
     service.notifyStatusChanged(this.clientId, mwi.active, mwi.msgCount,
                                 null, null);
   },
 
   handleIccInfoChange: function(message) {
     let oldSpn = this.rilContext.iccInfo ? this.rilContext.iccInfo.spn : null;
 
+    // TODO: Bug 815526, deprecate RILContentHelper:
+    //       Move the logic of updating iccInfo to IccService.js.
     if (!message || !message.iccid) {
       // If iccInfo is already `null`, don't have to clear it and send
       // RIL:IccInfoChanged.
       if (!this.rilContext.iccInfo) {
         return;
       }
 
       // Card is not detected, clear iccInfo to null.
@@ -2237,27 +2256,21 @@ RadioInterface.prototype = {
         return;
       }
 
       this.updateInfo(message, this.rilContext.iccInfo);
     }
 
     // RIL:IccInfoChanged corresponds to a DOM event that gets fired only
     // when iccInfo has changed.
+    // TODO: Bug 815526, deprecate RILContentHelper.
     gMessageManager.sendIccMessage("RIL:IccInfoChanged",
                                    this.clientId,
                                    message.iccid ? message : null);
-
-    // Update lastKnownSimMcc.
-    if (message.mcc) {
-      try {
-        Services.prefs.setCharPref("ril.lastKnownSimMcc",
-                                   message.mcc.toString());
-      } catch (e) {}
-    }
+    gIccService.notifyIccInfoChanged(this.clientId, this.rilContext.iccInfo);
 
     // Update lastKnownHomeNetwork.
     if (message.mcc && message.mnc) {
       let lastKnownHomeNetwork = message.mcc + "-" + message.mnc;
       // Append spn information if available.
       if (message.spn) {
         lastKnownHomeNetwork += "-" + message.spn;
       }
@@ -2275,16 +2288,17 @@ RadioInterface.prototype = {
   handleStkProactiveCommand: function(message) {
     if (DEBUG) this.debug("handleStkProactiveCommand " + JSON.stringify(message));
     let iccId = this.rilContext.iccInfo && this.rilContext.iccInfo.iccid;
     if (iccId) {
       gIccMessenger
         .notifyStkProactiveCommand(iccId,
                                    gStkCmdFactory.createCommand(message));
     }
+    // TODO: Bug 815526, deprecate RILContentHelper.
     gMessageManager.sendIccMessage("RIL:StkCommand", this.clientId, message);
   },
 
   _convertCbGsmGeographicalScope: function(aGeographicalScope) {
     return (aGeographicalScope != null)
       ? aGeographicalScope
       : Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID;
   },
--- a/dom/system/gonk/moz.build
+++ b/dom/system/gonk/moz.build
@@ -84,18 +84,18 @@ EXTRA_JS_MODULES += [
     'systemlibs.js',
 ]
 
 if CONFIG['MOZ_B2G_RIL']:
     XPIDL_SOURCES += [
         'nsIRadioInterfaceLayer.idl',
     ]
     EXTRA_COMPONENTS += [
-        'RILContentHelper.js',
-        'RILContentHelper.manifest',
+        'RILContentHelper.js', # TODO: Bug 815526, deprecate RILContentHelper.
+        'RILContentHelper.manifest', # TODO: Bug 815526, deprecate RILContentHelper.
         'RILSystemMessengerHelper.js',
         'RILSystemMessengerHelper.manifest',
     ]
     EXTRA_JS_MODULES += [
         'ril_consts.js',
         'ril_worker.js',
         'ril_worker_buf_object.js',
         'RILSystemMessenger.jsm',
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -20,17 +20,17 @@ interface nsIRilNetworkInterface : nsINe
   readonly attribute DOMString mmsProxy; // Empty string if not set.
   readonly attribute long      mmsPort;  // -1 if not set.
 };
 
 [scriptable, uuid(4441e660-4ad0-11e4-916c-0800200c9a66)]
 interface nsIRilContext : nsISupports
 {
   /**
-   * One of the nsIIccProvider.CARD_STATE_* values.
+   * One of the nsIIcc.CARD_STATE_* values.
    */
   readonly attribute unsigned long cardState;
 
   readonly attribute DOMString imsi;
 
   readonly attribute nsIIccInfo iccInfo;
 };
 
@@ -74,8 +74,18 @@ interface nsIRadioInterfaceLayer : nsISu
    * Select a proper client for dialing emergency call.
    *
    * @return clientId or -1 if none of the clients are avaialble.
    */
   unsigned long getClientIdForEmergencyCall();
 
   void setMicrophoneMuted(in boolean muted);
 };
+
+
+/**
+ * Helper Interface to define new APIs of nsIRadioInterfaceLayer during
+ * ril-interfaces frozen phase.
+ */
+[scriptable, uuid(f8ec63da-c22e-11e4-89f3-b767dae42a13)]
+interface nsIRadioInterfaceLayer_new : nsIRadioInterfaceLayer
+{
+};
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -2572,17 +2572,17 @@ this.CALL_FAIL_ERROR_UNSPECIFIED = 0xfff
 
 // See nsIMobileConnection::MOBILE_RADIO_STATE_*
 this.GECKO_RADIOSTATE_UNKNOWN   = -1;
 this.GECKO_RADIOSTATE_ENABLED   = 0;
 this.GECKO_RADIOSTATE_DISABLED  = 1;
 
 // Only used in ril_worker.js
 this.GECKO_CARDSTATE_UNINITIALIZED = 4294967294; // UINT32_MAX - 1
-// See nsIIccProvider::CARD_STATE_*
+// See nsIIcc::CARD_STATE_*
 this.GECKO_CARDSTATE_UNDETECTED = 4294967295; // UINT32_MAX
 this.GECKO_CARDSTATE_UNKNOWN = 0;
 this.GECKO_CARDSTATE_READY = 1;
 this.GECKO_CARDSTATE_PIN_REQUIRED = 2;
 this.GECKO_CARDSTATE_PUK_REQUIRED = 3;
 this.GECKO_CARDSTATE_PERMANENT_BLOCKED = 4;
 this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = 5;
 this.GECKO_CARDSTATE_PERSONALIZATION_READY = 6;
@@ -2605,17 +2605,17 @@ this.GECKO_CARDSTATE_RUIM_LOCKED = 22;
 this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = 23;
 this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = 24;
 this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = 25;
 this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
 this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
 this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = 28;
 this.GECKO_CARDSTATE_ILLEGAL = 29;
 
-// See nsIIccProvider::CARD_LOCK_TYPE_*
+// See nsIIcc::CARD_LOCK_TYPE_*
 this.GECKO_CARDLOCK_PIN = 0;
 this.GECKO_CARDLOCK_PIN2 = 1;
 this.GECKO_CARDLOCK_PUK = 2;
 this.GECKO_CARDLOCK_PUK2 = 3;
 this.GECKO_CARDLOCK_NCK = 4;
 this.GECKO_CARDLOCK_NSCK = 5;
 this.GECKO_CARDLOCK_NCK1 = 6;
 this.GECKO_CARDLOCK_NCK2 = 7;
@@ -2648,27 +2648,27 @@ GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOC
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_PUK2] = ICC_SEL_CODE_SIM_PUK2;
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NCK] = ICC_SEL_CODE_PH_NET_PIN;
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_NSCK] = ICC_SEL_CODE_PH_NETSUB_PIN;
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_CCK] = ICC_SEL_CODE_PH_CORP_PIN;
 GECKO_CARDLOCK_TO_SEL_CODE[GECKO_CARDLOCK_SPCK] = ICC_SEL_CODE_PH_SP_PIN;
 // TODO: Bug 1116072: identify the mapping between RIL_PERSOSUBSTATE_SIM_SIM @
 //       ril.h and TS 27.007, clause 8.65 for GECKO_CARDLOCK_PCK.
 
-// See nsIIccProvider::CARD_CONTACT_TYPE_*
+// See nsIIcc::CARD_CONTACT_TYPE_*
 this.GECKO_CARDCONTACT_TYPE_ADN = 0;
 this.GECKO_CARDCONTACT_TYPE_FDN = 1;
 this.GECKO_CARDCONTACT_TYPE_SDN = 2;
 
-// See nsIIccProvider::CARD_MVNO_TYPE_*
+// See nsIIcc::CARD_MVNO_TYPE_*
 this.GECKO_CARDMVNO_TYPE_IMSI = 0;
 this.GECKO_CARDMVNO_TYPE_SPN = 1;
 this.GECKO_CARDMVNO_TYPE_GID = 2;
 
-// See nsIIccProvider::CARD_MVNO_TYPE_*
+// See nsIIcc::CARD_SERVICE_*
 this.GECKO_CARDSERVICE_FDN = 0;
 
 // See ril.h RIL_PersoSubstate
 this.PERSONSUBSTATE = {};
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_UNKNOWN] = GECKO_CARDSTATE_UNKNOWN;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_IN_PROGRESS] = GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_READY] = GECKO_CARDSTATE_PERSONALIZATION_READY;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK] = GECKO_CARDSTATE_NETWORK_LOCKED;
--- a/dom/system/gonk/tests/marionette/test_ril_code_quality.py
+++ b/dom/system/gonk/tests/marionette/test_ril_code_quality.py
@@ -1,13 +1,13 @@
 """
 The test performs the static code analysis check by JSHint.
 
 Target js files:
-- RILContentHelper.js
+- RILContentHelper.js TODO: Bug 815526, deprecate RILContentHelper.
 - RadioInterfaceLayer.js
 - ril_worker.js
 - ril_consts.js
 
 If the js file contains the line of 'importScript()' (Ex: ril_worker.js), the
 test will perform a special merge step before excuting JSHint.
 
 Ex: Script A
@@ -95,17 +95,17 @@ class StringUtility:
 
 
 class ResourceUriFileReader:
 
     """Handle the process of reading the source code from system."""
 
     URI_PREFIX = 'resource://gre/'
     URI_PATH = {
-        'RILContentHelper.js':    'components/RILContentHelper.js',
+        'RILContentHelper.js':    'components/RILContentHelper.js', #TODO: Bug 815526, deprecate RILContentHelper.
         'RadioInterfaceLayer.js': 'components/RadioInterfaceLayer.js',
         'ril_worker.js':          'modules/ril_worker.js',
         'ril_consts.js':          'modules/ril_consts.js',
         'systemlibs.js':          'modules/systemlibs.js',
         'worker_buf.js':          'modules/workers/worker_buf.js',
     }
 
     CODE_OPEN_CHANNEL_BY_URI = '''
@@ -349,16 +349,17 @@ class TestRILCodeQuality(MarionetteTestC
             JSHintEngine(self.marionette,
                          self._read_local_file(self.JSHINT_PATH),
                          self._read_local_file(self.JSHINTRC_PATH)),
             self._get_extended_error_message)
 
     def tearDown(self):
         MarionetteTestCase.tearDown(self)
 
+    # TODO: Bug 815526, deprecate RILContentHelper.
     def test_RILContentHelper(self):
         self._check('RILContentHelper.js')
 
     def test_RadioInterfaceLayer(self):
         self._check('RadioInterfaceLayer.js')
 
     # Bug 936504. Disable the test for 'ril_worker.js'. It sometimes runs very
     # slow and causes the timeout fail on try server.
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
@@ -28,75 +28,75 @@ add_test(function test_personalization_s
 
     ril._isCdma = isCdma;
     ril._processICCStatus(iccStatus);
     equal(ril.cardState, geckoCardState);
   }
 
   // Test GSM personalization state.
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK_SUBSET_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
-                      Ci.nsIIccProvider.CARD_STATE_CORPORATE_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_CORPORATE_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
-                      Ci.nsIIccProvider.CARD_STATE_SERVICE_PROVIDER_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM,
-                      Ci.nsIIccProvider.CARD_STATE_SIM_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_SIM_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_CORPORATE_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_CORPORATE_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_SIM_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_SIM_PUK_REQUIRED);
 
   testPersonalization(false, CARD_PERSOSUBSTATE_UNKNOWN,
-                      Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+                      Ci.nsIIcc.CARD_STATE_UNKNOWN);
   testPersonalization(false, CARD_PERSOSUBSTATE_IN_PROGRESS,
-                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
+                      Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
   testPersonalization(false, CARD_PERSOSUBSTATE_READY,
-                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_READY);
+                      Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
 
   // Test CDMA personalization state.
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK1_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK1_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK2_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK2_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
-                      Ci.nsIIccProvider.CARD_STATE_HRPD_NETWORK_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_CORPORATE_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_LOCKED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK1_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK1_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_NETWORK2_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_NETWORK2_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
-                      Ci.nsIIccProvider.CARD_STATE_RUIM_PUK_REQUIRED);
+                      Ci.nsIIcc.CARD_STATE_RUIM_PUK_REQUIRED);
 
   testPersonalization(true, CARD_PERSOSUBSTATE_UNKNOWN,
-                      Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+                      Ci.nsIIcc.CARD_STATE_UNKNOWN);
   testPersonalization(true, CARD_PERSOSUBSTATE_IN_PROGRESS,
-                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
+                      Ci.nsIIcc.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
   testPersonalization(true, CARD_PERSOSUBSTATE_READY,
-                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_READY);
+                      Ci.nsIIcc.CARD_STATE_PERSONALIZATION_READY);
 
   run_next_test();
 });
 
 /**
  * Verify SIM app_state in _processICCStatus
  */
 add_test(function test_card_app_state() {
@@ -116,27 +116,27 @@ add_test(function test_card_app_state() 
       }],
     };
 
     ril._processICCStatus(iccStatus);
     equal(ril.cardState, geckoCardState);
   }
 
   testCardAppState(CARD_APPSTATE_ILLEGAL,
-                   Ci.nsIIccProvider.CARD_STATE_ILLEGAL);
+                   Ci.nsIIcc.CARD_STATE_ILLEGAL);
   testCardAppState(CARD_APPSTATE_PIN,
-                   Ci.nsIIccProvider.CARD_STATE_PIN_REQUIRED);
+                   Ci.nsIIcc.CARD_STATE_PIN_REQUIRED);
   testCardAppState(CARD_APPSTATE_PUK,
-                   Ci.nsIIccProvider.CARD_STATE_PUK_REQUIRED);
+                   Ci.nsIIcc.CARD_STATE_PUK_REQUIRED);
   testCardAppState(CARD_APPSTATE_READY,
-                   Ci.nsIIccProvider.CARD_STATE_READY);
+                   Ci.nsIIcc.CARD_STATE_READY);
   testCardAppState(CARD_APPSTATE_UNKNOWN,
-                   Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+                   Ci.nsIIcc.CARD_STATE_UNKNOWN);
   testCardAppState(CARD_APPSTATE_DETECTED,
-                   Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+                   Ci.nsIIcc.CARD_STATE_UNKNOWN);
 
   run_next_test();
 });
 
 /**
  * Verify permanent blocked for ICC.
  */
 add_test(function test_icc_permanent_blocked() {
@@ -154,17 +154,17 @@ add_test(function test_icc_permanent_blo
       apps: [
       {
         pin1_replaced: pin1_replaced,
         pin1: pin1
       }]
     };
 
     ril._processICCStatus(iccStatus);
-    equal(ril.cardState, Ci.nsIIccProvider.CARD_STATE_PERMANENT_BLOCKED);
+    equal(ril.cardState, Ci.nsIIcc.CARD_STATE_PERMANENT_BLOCKED);
   }
 
   testPermanentBlocked(1,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED,
                        CARD_PINSTATE_UNKNOWN);
   testPermanentBlocked(1,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED);
--- a/dom/webidl/MozIcc.webidl
+++ b/dom/webidl/MozIcc.webidl
@@ -124,16 +124,26 @@ dictionary IccSetCardLockOptions
 
  DOMString? newPin = null; // Used for changing password operation.
                            // Necessary for lock types: "pin", "pin2"
 
  boolean enabled; // Used for enabling/disabling operation.
                   // Necessary for lock types: "pin", "fdn"
 };
 
+dictionary IccCardLockStatus
+{
+  boolean enabled; // True when CardLock is enabled.
+};
+
+dictionary IccCardLockRetryCount
+{
+  long retryCount; // The number of remaining retries. -1 if unkown.
+};
+
 [Pref="dom.icc.enabled",
  CheckPermissions="mobileconnection",
  AvailableIn="CertifiedApps"]
 interface MozIcc : EventTarget
 {
   // Integrated Circuit Card Information.
 
   /**
@@ -242,16 +252,17 @@ interface MozIcc : EventTarget
    *
    * @param lockType
    *        Identifies the lock type.
    *
    * @return a DOMRequest.
    *         The request's result will be an object containing
    *         information about the specified lock's status.
    *         e.g. {enabled: true}.
+   *         @see IccCardLockStatus.
    */
   [Throws]
   DOMRequest getCardLock(IccLockType lockType);
 
   /**
    * Unlock a card lock.
    *
    * @param info
@@ -284,18 +295,18 @@ interface MozIcc : EventTarget
   /**
    * Retrieve the number of remaining tries for unlocking the card.
    *
    * @param lockType
    *        Identifies the lock type.
    *
    * @return a DOMRequest.
    *         The request's result will be an object containing the number of
-   *         remaining retries.
-   *         e.g. {retryCount: 3}.
+   *         remaining retries. e.g. {retryCount: 3}.
+   *         @see IccCardLockRetryCount.
    */
   [Throws]
   DOMRequest getCardLockRetryCount(IccLockType lockType);
 
   // Integrated Circuit Card Phonebook Interfaces.
 
   /**
    * Read ICC contacts.
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -224,16 +224,17 @@ WEBIDL_FILES = [
     'HTMLTableSectionElement.webidl',
     'HTMLTemplateElement.webidl',
     'HTMLTextAreaElement.webidl',
     'HTMLTimeElement.webidl',
     'HTMLTitleElement.webidl',
     'HTMLTrackElement.webidl',
     'HTMLUListElement.webidl',
     'HTMLVideoElement.webidl',
+    'IccCardLockError.webidl',
     'IDBCursor.webidl',
     'IDBDatabase.webidl',
     'IDBEnvironment.webidl',
     'IDBFactory.webidl',
     'IDBFileHandle.webidl',
     'IDBFileRequest.webidl',
     'IDBIndex.webidl',
     'IDBKeyRange.webidl',
@@ -282,16 +283,19 @@ WEBIDL_FILES = [
     'MimeType.webidl',
     'MimeTypeArray.webidl',
     'MMICall.webidl',
     'MouseEvent.webidl',
     'MouseScrollEvent.webidl',
     'MozActivity.webidl',
     'MozCellBroadcast.webidl',
     'MozCellBroadcastMessage.webidl',
+    'MozIcc.webidl',
+    'MozIccInfo.webidl',
+    'MozIccManager.webidl',
     'MozMmsMessage.webidl',
     'MozMobileCellInfo.webidl',
     'MozMobileConnection.webidl',
     'MozMobileConnectionArray.webidl',
     'MozMobileConnectionInfo.webidl',
     'MozMobileMessageManager.webidl',
     'MozMobileNetworkInfo.webidl',
     'MozPowerManager.webidl',
@@ -646,24 +650,16 @@ if CONFIG['MOZ_B2G_BT']:
         ]
     else:
         WEBIDL_FILES += [
             'BluetoothAdapter.webidl',
             'BluetoothDevice.webidl',
             'BluetoothManager.webidl',
         ]
 
-if CONFIG['MOZ_B2G_RIL']:
-    WEBIDL_FILES += [
-        'IccCardLockError.webidl',
-        'MozIcc.webidl',
-        'MozIccInfo.webidl',
-        'MozIccManager.webidl',
-    ]
-
 if CONFIG['MOZ_NFC']:
     WEBIDL_FILES += [
          'MozIsoDepTech.webidl',
          'MozNDEFRecord.webidl',
          'MozNFC.webidl',
          'MozNFCPeer.webidl',
          'MozNFCTag.webidl',
          'NfcOptions.webidl',
--- a/dom/wifi/WifiWorker.js
+++ b/dom/wifi/WifiWorker.js
@@ -845,16 +845,26 @@ var WifiManager = (function() {
       }
       manager.handlePostWifiScan();
       notify("scanresultsavailable");
       return true;
     }
     if (eventData.indexOf("CTRL-EVENT-EAP") === 0) {
       return handleWpaEapEvents(event);
     }
+    if (eventData.indexOf("CTRL-EVENT-ASSOC-REJECT") === 0) {
+      debug("CTRL-EVENT-ASSOC-REJECT: network error");
+      notify("passwordmaybeincorrect");
+      if (manager.authenticationFailuresCount > MAX_RETRIES_ON_AUTHENTICATION_FAILURE) {
+        manager.authenticationFailuresCount = 0;
+        debug("CTRL-EVENT-ASSOC-REJECT: disconnect network");
+        notify("disconnected", {connectionInfo: manager.connectionInfo});
+      }
+      return true;
+    }
     if (eventData.indexOf("WPS-TIMEOUT") === 0) {
       notifyStateChange({ state: "WPS_TIMEOUT", BSSID: null, id: -1 });
       return true;
     }
     if (eventData.indexOf("WPS-FAIL") === 0) {
       notifyStateChange({ state: "WPS_FAIL", BSSID: null, id: -1 });
       return true;
     }
@@ -2157,17 +2167,20 @@ function WifiWorker() {
       case "ASSOCIATING":
         // id has not yet been filled in, so we can only report the ssid and
         // bssid. mode and frequency are simply made up.
         self.currentNetwork =
           { bssid: WifiManager.connectionInfo.bssid,
             ssid: quote(WifiManager.connectionInfo.ssid),
             mode: MODE_ESS,
             frequency: 0};
-        self._fireEvent("onconnecting", { network: netToDOM(self.currentNetwork) });
+        WifiManager.getNetworkConfiguration(self.currentNetwork, function (){
+          // Notify again because we get complete network information.
+          self._fireEvent("onconnecting", { network: netToDOM(self.currentNetwork) });
+        });
         break;
       case "ASSOCIATED":
         // set to full power mode when ready to do 4 way handsharke.
         WifiManager.setPowerSavingMode(false);
         if (!self.currentNetwork) {
           self.currentNetwork =
             { bssid: WifiManager.connectionInfo.bssid,
               ssid: quote(WifiManager.connectionInfo.ssid) };
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -208,16 +208,17 @@ static void Shutdown();
 #include "nsGeolocation.h"
 #include "nsDeviceSensors.h"
 #ifdef MOZ_GAMEPAD
 #include "mozilla/dom/GamepadService.h"
 #endif
 #include "mozilla/dom/nsCSPService.h"
 #include "mozilla/dom/nsCSPContext.h"
 #include "nsICellBroadcastService.h"
+#include "nsIIccService.h"
 #include "nsISmsService.h"
 #include "nsIMmsService.h"
 #include "nsIMobileConnectionService.h"
 #include "nsIMobileMessageService.h"
 #include "nsIMobileMessageDatabaseService.h"
 #include "nsIPowerManagerService.h"
 #include "nsIAlarmHalService.h"
 #include "nsIMediaManager.h"
@@ -333,16 +334,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsHapticF
 #endif
 #endif
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(ThirdPartyUtil, Init)
 #ifndef DISABLE_MOZ_RIL_GEOLOC
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsICellBroadcastService,
                                          NS_CreateCellBroadcastService)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsISmsService, NS_CreateSmsService)
 #endif
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIIccService, NS_CreateIccService)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMmsService, NS_CreateMmsService)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageService,
                                          NS_CreateMobileMessageService)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIMobileMessageDatabaseService,
                                          NS_CreateMobileMessageDatabaseService)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIPowerManagerService,
                                          PowerManagerService::GetInstance)
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIAlarmHalService,
@@ -793,16 +795,17 @@ NS_DEFINE_NAMED_CID(CELLBROADCAST_SERVIC
 #ifdef MOZ_WIDGET_GONK
 NS_DEFINE_NAMED_CID(GONK_GPS_GEOLOCATION_PROVIDER_CID);
 #endif
 NS_DEFINE_NAMED_CID(TELEPHONY_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_VOICEMAIL_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MOBILE_CONNECTION_SERVICE_CID);
 NS_DEFINE_NAMED_CID(SMS_SERVICE_CID);
 #endif
+NS_DEFINE_NAMED_CID(ICC_SERVICE_CID);
 NS_DEFINE_NAMED_CID(MMS_SERVICE_CID);
 NS_DEFINE_NAMED_CID(MOBILE_MESSAGE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(MOBILE_MESSAGE_DATABASE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_POWERMANAGERSERVICE_CID);
 NS_DEFINE_NAMED_CID(OSFILECONSTANTSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_ALARMHALSERVICE_CID);
 NS_DEFINE_NAMED_CID(TCPSOCKETCHILD_CID);
 NS_DEFINE_NAMED_CID(TCPSOCKETPARENT_CID);
@@ -1087,16 +1090,17 @@ static const mozilla::Module::CIDEntry k
 #endif
 #endif
   { &kTHIRDPARTYUTIL_CID, false, nullptr, ThirdPartyUtilConstructor },
   { &kNS_STRUCTUREDCLONECONTAINER_CID, false, nullptr, nsStructuredCloneContainerConstructor },
 #ifndef DISABLE_MOZ_RIL_GEOLOC
   { &kCELLBROADCAST_SERVICE_CID, false, nullptr, nsICellBroadcastServiceConstructor },
   { &kSMS_SERVICE_CID, false, nullptr, nsISmsServiceConstructor },
 #endif
+  { &kICC_SERVICE_CID, false, nullptr, nsIIccServiceConstructor },
   { &kMMS_SERVICE_CID, false, nullptr, nsIMmsServiceConstructor },
   { &kMOBILE_MESSAGE_SERVICE_CID, false, nullptr, nsIMobileMessageServiceConstructor },
   { &kMOBILE_MESSAGE_DATABASE_SERVICE_CID, false, nullptr, nsIMobileMessageDatabaseServiceConstructor },
   { &kNS_POWERMANAGERSERVICE_CID, false, nullptr, nsIPowerManagerServiceConstructor },
   { &kOSFILECONSTANTSSERVICE_CID, true, nullptr, OSFileConstantsServiceConstructor },
   { &kNS_ALARMHALSERVICE_CID, false, nullptr, nsIAlarmHalServiceConstructor },
   { &kTCPSOCKETCHILD_CID, false, nullptr, TCPSocketChildConstructor },
   { &kTCPSOCKETPARENT_CID, false, nullptr, TCPSocketParentConstructor },
@@ -1250,16 +1254,17 @@ static const mozilla::Module::ContractID
 #endif
 #endif
   { THIRDPARTYUTIL_CONTRACTID, &kTHIRDPARTYUTIL_CID },
   { NS_STRUCTUREDCLONECONTAINER_CONTRACTID, &kNS_STRUCTUREDCLONECONTAINER_CID },
 #ifndef DISABLE_MOZ_RIL_GEOLOC
   { CELLBROADCAST_SERVICE_CONTRACTID, &kCELLBROADCAST_SERVICE_CID },
   { SMS_SERVICE_CONTRACTID, &kSMS_SERVICE_CID },
 #endif
+  { ICC_SERVICE_CONTRACTID, &kICC_SERVICE_CID },
   { MMS_SERVICE_CONTRACTID, &kMMS_SERVICE_CID },
   { MOBILE_MESSAGE_SERVICE_CONTRACTID, &kMOBILE_MESSAGE_SERVICE_CID },
   { MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID, &kMOBILE_MESSAGE_DATABASE_SERVICE_CID },
   { POWERMANAGERSERVICE_CONTRACTID, &kNS_POWERMANAGERSERVICE_CID },
   { OSFILECONSTANTSSERVICE_CONTRACTID, &kOSFILECONSTANTSSERVICE_CID },
   { ALARMHALSERVICE_CONTRACTID, &kNS_ALARMHALSERVICE_CID },
   { "@mozilla.org/tcp-socket-child;1", &kTCPSOCKETCHILD_CID },
   { "@mozilla.org/tcp-socket-parent;1", &kTCPSOCKETPARENT_CID },
--- a/services/mobileid/MobileIdentityManager.jsm
+++ b/services/mobileid/MobileIdentityManager.jsm
@@ -51,19 +51,19 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "@mozilla.org/AppsService;1",
                                    "nsIAppsService");
 
 #ifdef MOZ_B2G_RIL
 XPCOMUtils.defineLazyServiceGetter(this, "Ril",
                                    "@mozilla.org/ril;1",
                                    "nsIRadioInterfaceLayer");
 
-XPCOMUtils.defineLazyServiceGetter(this, "IccProvider",
-                                   "@mozilla.org/ril/content-helper;1",
-                                   "nsIIccProvider");
+XPCOMUtils.defineLazyServiceGetter(this, "IccService",
+                                   "@mozilla.org/icc/iccservice;1",
+                                   "nsIIccService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "MobileConnectionService",
                                    "@mozilla.org/mobileconnection/mobileconnectionservice;1",
                                    "nsIMobileConnectionService");
 #endif
 
 
 this.MobileIdentityManager = {
@@ -111,21 +111,21 @@ this.MobileIdentityManager = {
   // We have these getters to allow mocking RIL stuff from the tests.
   get ril() {
     if (this._ril) {
       return this._ril;
     }
     return Ril;
   },
 
-  get iccProvider() {
-    if (this._iccProvider) {
-      return this._iccProvider;
+  get iccService() {
+    if (this._iccService) {
+      return this._iccService;
     }
-    return IccProvider;
+    return IccService;
   },
 
   get mobileConnectionService() {
     if (this._mobileConnectionService) {
       return this._mobileConnectionService;
     }
     return MobileConnectionService;
   },
@@ -148,18 +148,20 @@ this.MobileIdentityManager = {
         // If we receive a notification about an ICC info change, we clear
         // the ICC related caches so they can be rebuilt with the new changes.
 
         log.debug("ICC info changed observed. Clearing caches");
 
         // We don't need to keep listening for changes until we rebuild the
         // cache again.
         for (let i = 0; i < self._iccInfo.length; i++) {
-          self.iccProvider.unregisterIccMsg(self._iccInfo[i].clientId,
-                                            iccListener);
+          let icc = self.iccService.getIccByServiceId(i);
+          if (icc) {
+            icc.unregisterListener(iccListener);
+          }
         }
 
         self._iccInfo = null;
         self._iccIds = null;
       }
     };
 
     // _iccInfo is a local cache containing the information about the SIM cards
@@ -209,17 +211,20 @@ this.MobileIdentityManager = {
         // GSM SIMs may have MSISDN while CDMA SIMs may have MDN
         msisdn: info.msisdn || info.mdn || null,
         operator: operator,
         roaming: voice && voice.roaming
       });
 
       // We need to subscribe to ICC change notifications so we can refresh
       // the cache if any change is observed.
-      this.iccProvider.registerIccMsg(i, iccListener);
+      let icc = this.iccService.getIccByServiceId(i);
+      if (icc) {
+        icc.registerListener(iccListener);
+      }
     }
 
     return this._iccInfo;
 #endif
     return null;
   },
 
   get iccIds() {
--- a/services/mobileid/tests/xpcshell/test_mobileid_manager.js
+++ b/services/mobileid/tests/xpcshell/test_mobileid_manager.js
@@ -997,23 +997,29 @@ add_test(function() {
 
   MobileIdentityManager._mobileConnectionService = {
     _interfaces: [RADIO_INTERFACE, ANOTHER_RADIO_INTERFACE],
     getItemByServiceId: function(aIndex) {
       return this._interfaces[aIndex];
     }
   };
 
-  MobileIdentityManager._iccProvider = {
+  MobileIdentityManager._iccService = {
+    _iccs: [],
     _listeners: [],
-    registerIccMsg: function(aClientId, aIccListener) {
-      this._listeners.push(aIccListener);
-    },
-    unregisterIccMsg: function() {
-      this._listeners.pop();
+    getIccByServiceId: function(aClientId) {
+      let self = this;
+      this_iccs.push({
+        registerListener: function(aIccListener) {
+          self._listeners.push(aIccListener);
+        },
+        unregisterListener: function() {
+          self._listeners.pop();
+        }
+      });
     }
   };
 
   let ui = new MockUi();
   ui.startFlow = function() {
     // At this point we've already built the ICC cache.
     let interfaces = MobileIdentityManager._ril._interfaces;
     for (let i = 0; i < interfaces.length; i++) {
@@ -1022,27 +1028,27 @@ add_test(function() {
       do_check_eq(interfaceIccInfo.iccid, mIdIccInfo.iccId);
       do_check_eq(interfaceIccInfo.mcc, mIdIccInfo.mcc);
       do_check_eq(interfaceIccInfo.mnc, mIdIccInfo.mnc);
       do_check_eq(interfaceIccInfo.msisdn, mIdIccInfo.msisdn);
       do_check_eq(interfaceIccInfo.operator, mIdIccInfo.operator);
     }
 
     // We should have listeners for each valid icc.
-    do_check_eq(MobileIdentityManager._iccProvider._listeners.length, 2);
+    do_check_eq(MobileIdentityManager._iccService._listeners.length, 2);
 
     // We can mock an ICC change event at this point.
-    MobileIdentityManager._iccProvider._listeners[0].notifyIccInfoChanged();
+    MobileIdentityManager._iccService._listeners[0].notifyIccInfoChanged();
 
     // After the ICC change event the caches should be null.
     do_check_null(MobileIdentityManager._iccInfo);
     do_check_null(MobileIdentityManager._iccIds);
 
     // And we should have unregistered all listeners for ICC change events.
-    do_check_eq(MobileIdentityManager._iccProvider._listeners.length, 0);
+    do_check_eq(MobileIdentityManager._iccService._listeners.length, 0);
 
     do_test_finished();
     run_next_test();
   };
   MobileIdentityManager.ui = ui;
 
   let credStore = new MockCredStore();
   credStore.getByOrigin = function() {
@@ -1099,34 +1105,40 @@ add_test(function() {
 
   MobileIdentityManager._mobileConnectionService = {
     _interfaces: [INVALID_RADIO_INTERFACE],
     getItemByServiceId: function(aIndex) {
       return this._interfaces[aIndex];
     }
   };
 
-  MobileIdentityManager._iccProvider = {
+  MobileIdentityManager._iccService = {
+    _iccs: [],
     _listeners: [],
-    registerIccMsg: function(aClientId, aIccListener) {
-      this._listeners.push(aIccListener);
-    },
-    unregisterIccMsg: function() {
-      this._listeners.pop();
+    getIccByServiceId: function(aClientId) {
+      let self = this;
+      this_iccs.push({
+        registerListener: function(aIccListener) {
+          self._listeners.push(aIccListener);
+        },
+        unregisterListener: function() {
+          self._listeners.pop();
+        }
+      });
     }
   };
 
   let ui = new MockUi();
   ui.startFlow = function() {
     // At this point we've already built the ICC cache.
     do_check_eq(MobileIdentityManager._iccInfo.length, 0);
     do_check_eq(MobileIdentityManager._iccIds.length, 0);
 
     // We should have listeners for each valid icc.
-    do_check_eq(MobileIdentityManager._iccProvider._listeners.length, 0);
+    do_check_eq(MobileIdentityManager._iccService._listeners.length, 0);
 
     do_test_finished();
     run_next_test();
   };
   MobileIdentityManager.ui = ui;
 
   let credStore = new MockCredStore();
   credStore.getByOrigin = function() {