Merge m-c to fx-team a=merge
authorWes Kocher <wkocher@mozilla.com>
Mon, 23 Jun 2014 19:07:22 -0700
changeset 212389 cc4602e0c1d89622c7be5da0555c42f323ae43e4
parent 212388 d825d00cceeef0485feb9720fc8cd193ce3786fb (current diff)
parent 212170 e86b84998b186642cb162adb265af423f7f4555a (diff)
child 212390 5e0288a4e39831da5f45d2ed8a4d0c2e68a61eb9
push id515
push userraliiev@mozilla.com
push dateMon, 06 Oct 2014 12:51:51 +0000
treeherdermozilla-release@267c7a481bef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team a=merge
dom/system/gonk/tests/test_ril_worker_icc.js
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -105,16 +105,17 @@ pref("browser.sessionstore.max_tabs_undo
 
 /* these should help performance */
 pref("mozilla.widget.force-24bpp", true);
 pref("mozilla.widget.use-buffer-pixmap", true);
 pref("mozilla.widget.disable-native-theme", true);
 pref("layout.reflow.synthMouseMove", false);
 pref("layers.enable-tiles", true);
 pref("layers.low-precision-buffer", true);
+pref("layers.low-precision-opacity", "0.5");
 /*
    Cross Process Mutex is not supported on Mac OS X so progressive
    paint cannot be enabled for B2G on Mac OS X desktop
 */
 #ifdef MOZ_WIDGET_COCOA
 pref("layers.progressive-paint", false);
 #else
 pref("layers.progressive-paint", true);
@@ -905,19 +906,16 @@ pref("gfx.canvas.azure.accelerated", tru
 pref("gfx.canvas.skiagl.dynamic-cache", true);
 
 // Limit skia to canvases the size of the device screen or smaller
 pref("gfx.canvas.max-size-for-skia-gl", -1);
 
 // enable fence with readpixels for SurfaceStream
 pref("gfx.gralloc.fence-with-readpixels", true);
 
-// Cell Broadcast API
-pref("ril.cellbroadcast.disabled", false);
-
 // The url of the page used to display network error details.
 pref("b2g.neterror.url", "app://system.gaiamobile.org/net_error.html");
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -659,23 +659,23 @@ let settingsToObserve = {
     prefName: 'layers.offmainthreadcomposition.log-animations',
     defaultValue: false
   },
   'debug.paint-flashing.enabled': {
     prefName: 'nglayout.debug.paint_flashing',
     defaultValue: false
   },
   'devtools.eventlooplag.threshold': 100,
+  'dom.mozApps.use_reviewer_certs': false,
   'layers.draw-borders': false,
   'layers.draw-tile-borders': false,
   'layers.dump': false,
   'layers.enable-tiles': true,
   'layers.simple-tiles': false,
   'privacy.donottrackheader.enabled': false,
-  'ril.cellbroadcast.disabled': false,
   'ril.radio.disabled': false,
   'ril.mms.requestReadReport.enabled': {
     prefName: 'dom.mms.requestReadReport',
     defaultValue: true
   },
   'ril.mms.requestStatusReport.enabled': {
     prefName: 'dom.mms.requestStatusReport',
     defaultValue: false
--- a/b2g/chrome/content/touchcontrols.css
+++ b/b2g/chrome/content/touchcontrols.css
@@ -8,16 +8,22 @@
 .controlsOverlay {
   -moz-box-pack: center;
   -moz-box-align: end;
   padding: 20px;
   -moz-box-flex: 1;
   -moz-box-orient: horizontal;
 }
 
+.controlsOverlay[scaled] {
+  /* scaled attribute in videocontrols.css causes conflict
+     due to different -moz-box-orient values */
+  -moz-box-align: end;
+}
+
 .controlBar {
   -moz-box-flex: 1;
   font-size: 16pt;
   padding: 10px;
   background-color: rgba(50,50,50,0.8);
   border-radius: 8px;
   width: 100%;
 }
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -35,16 +35,17 @@ contract @mozilla.org/dom/messages/syste
 # ProcessGlobal.js
 component {1a94c87a-5ece-4d11-91e1-d29c29f21b28} ProcessGlobal.js
 contract @mozilla.org/b2g-process-global;1 {1a94c87a-5ece-4d11-91e1-d29c29f21b28}
 category app-startup ProcessGlobal service,@mozilla.org/b2g-process-global;1
 
 # OMAContentHandler.js
 component {a6b2ab13-9037-423a-9897-dde1081be323} OMAContentHandler.js
 contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oma.drm.message {a6b2ab13-9037-423a-9897-dde1081be323}
+contract @mozilla.org/uriloader/content-handler;1?type=application/vnd.oma.dd+xml {a6b2ab13-9037-423a-9897-dde1081be323}
 
 # PaymentGlue.js
 component {8b83eabc-7929-47f4-8b48-4dea8d887e4b} PaymentGlue.js
 contract @mozilla.org/payment/ui-glue;1 {8b83eabc-7929-47f4-8b48-4dea8d887e4b}
 
 # TelProtocolHandler.js
 component {782775dd-7351-45ea-aff1-0ffa872cfdd2} TelProtocolHandler.js
 contract @mozilla.org/network/protocol;1?name=tel {782775dd-7351-45ea-aff1-0ffa872cfdd2}
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="276ce45e78b09c4a4ee643646f691d22804754c1">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="3326b51017252e09ccdd715dec6c5e12a7d1ecfe"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
@@ -109,29 +109,31 @@
   <project name="platform/prebuilts/qemu-kernel" path="prebuilts/qemu-kernel" revision="ec4a882d411d0d4ceadc5912ab4ce6fd4df23ab7"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b86c0ecb186ffdbfb85d9c65b8a4b084b3ee9514"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="31ec211efafde89ab39472d7bd040f00d1b71945"/>
   <project name="platform/system/extras" path="system/extras" revision="4d4bc6e7777887d93340f577d9b46de4a7c75f26"/>
   <project name="platform/system/media" path="system/media" revision="df2cdd433738a891102873710bdd3c3db7adb0cc"/>
   <project name="platform/system/netd" path="system/netd" revision="ea8103eae5642621ca8202e00620f4ca954ed413"/>
   <project name="platform/system/security" path="system/security" revision="360f51f7af191316cd739f229db1c5f7233be063"/>
   <project name="platform/system/vold" path="system/vold" revision="153df4d067a4149c7d78f1c92fed2ce2bd6a272e"/>
+  <!--original fetch url was git://github.com/t2m-foxfone/-->
+  <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="jb_3.2" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="34ed8345250bb97262d70a052217a92e83444ede"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="243b6f3d219592a84c7318e9446cde397233ae39"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="33faca8033c6f8cda0c383ab40d69c7a45e6db38"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="30a441fb7275fc5bc347f84ccb29e977a7eca34e"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="2b1d8b5b7a760230f4c94c02e733e3929f44253a"/>
   <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="e81502511cda303c803e63f049574634bc96f9f2"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="81c4a859d75d413ad688067829d21b7ba9205f81"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
   <project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
   <project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
-  <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="494c177966fdc31183a5f7af82dc9130f523da4b"/>
+  <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="5b934dc57dae25f286b0e7210dc6ff47f3244927"/>
   <project name="platform/frameworks/base" path="frameworks/base" revision="af3e4fbdc9369643a92015ea2657361f3b1b46fe"/>
   <project name="platform/frameworks/native" path="frameworks/native" revision="33a2b51f78416536e1bfba0c0b7776db307f3a4f"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="484802559ed106bac4811bd01c024ca64f741e60"/>
   <project name="platform/hardware/qcom/audio" path="hardware/qcom/audio" revision="83f363a26069e9c188d2aaef5b9ef63e84ad1511"/>
   <project name="platform/hardware/qcom/camera" path="hardware/qcom/camera" revision="5e110615212302c5d798a3c223dcee458817651c"/>
   <project name="platform/hardware/qcom/display" path="hardware/qcom/display" revision="280d29203b2aa30d713c5a6cc63d626e5a7df822"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "aba00cfd579caaf205e05c269f0a8100f242f39c", 
+    "revision": "8ac363347c96715adf6bec5fc30a975a2cfbaafd", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="cc67f31dc638c0b7edba3cf7e3d87cadf0ed52bf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="2a165bebfa19b11b697837409f9550dd2917c46c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="41cc1de26e4edbe12add0009cdc0bd292f2e94fe"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="45479c07cb6ba8c733093d6ee32c767c090c9a28"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="bbb7659d8ea2afb396f99b3dc971ab3c42da3778"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="c510babaf88dfa2cfe2c202afb2649ee124569af"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="23db533981ee2cd04fc5d946420402aed2792381"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="c2544b1797eb5c59f484c442a24c4dc14c37e68c"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/browser/devtools/scratchpad/test/browser_scratchpad_display_non_error_exceptions.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_display_non_error_exceptions.js
@@ -36,17 +36,17 @@ function runTests()
     result: message + openComment + "Hello World!" + closeComment,
     label: "message display output"
   },
   {
     // Display error1, throw new Error("Ouch")
     method: "display",
     code: error1,
     result: error1 + openComment +
-            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
+            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
     label: "error display output"
   },
   {
     // Display error2, throw "A thrown string"
     method: "display",
     code: error2,
     result: error2 + openComment + "Exception: A thrown string" + closeComment,
     label: "thrown string display output"
@@ -73,17 +73,17 @@ function runTests()
     result: message,
     label: "message run output"
   },
   {
     // Run error1, throw new Error("Ouch")
     method: "run",
     code: error1,
     result: error1 + openComment +
-            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:1" + closeComment,
+            "Exception: Ouch!\n@" + scratchpad.uniqueName + ":1:7" + closeComment,
     label: "error run output"
   },
   {
     // Run error2, throw "A thrown string"
     method: "run",
     code: error2,
     result: error2 + openComment + "Exception: A thrown string" + closeComment,
     label: "thrown string run output"
--- a/browser/devtools/scratchpad/test/browser_scratchpad_display_outputs_errors.js
+++ b/browser/devtools/scratchpad/test/browser_scratchpad_display_outputs_errors.js
@@ -32,17 +32,17 @@ function runTests()
     code: message,
     result: message + openComment + "Hello World!" + closeComment,
     label: "message display output"
   },
   {
     method: "display",
     code: error,
     result: error + openComment + "Exception: Ouch!\n@" +
-            scratchpad.uniqueName + ":1:1" + closeComment,
+            scratchpad.uniqueName + ":1:7" + closeComment,
     label: "error display output",
   },
   {
     method: "display",
     code: syntaxError,
     result: syntaxError + openComment + "Exception: syntax error\n@" +
             scratchpad.uniqueName + ":1" + closeComment,
     label: "syntaxError display output",
@@ -52,17 +52,17 @@ function runTests()
     code: message,
     result: message,
     label: "message run output",
   },
   {
     method: "run",
     code: error,
     result: error + openComment + "Exception: Ouch!\n@" +
-            scratchpad.uniqueName + ":1:1" + closeComment,
+            scratchpad.uniqueName + ":1:7" + closeComment,
     label: "error run output",
   },
   {
     method: "run",
     code: syntaxError,
     result: syntaxError + openComment + "Exception: syntax error\n@" +
             scratchpad.uniqueName + ":1" + closeComment,
     label: "syntaxError run output",
new file mode 100644
--- /dev/null
+++ b/content/base/src/AutocompleteFieldList.h
@@ -0,0 +1,141 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * This file contains the list of field names that are used in @autocomplete
+ * attribute for <input>, <select> and <textarea> controls. It is designed
+ * to be used as inline input through the magic of C preprocessing.
+ *
+ * The first argument to AUTOCOMPLETE_* macro is the identifier for the token
+ * The second argument is the string value of the token
+ */
+
+#ifndef AUTOCOMPLETE_FIELD_NAME
+#define AUTOCOMPLETE_FIELD_NAME(name_, value_)
+#define DEFINED_AUTOCOMPLETE_FIELD_NAME
+#endif
+
+#ifndef AUTOCOMPLETE_CONTACT_FIELD_NAME
+#define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_)
+#define DEFINED_AUTOCOMPLETE_CONTACT_FIELD_NAME
+#endif
+
+#ifndef AUTOCOMPLETE_FIELD_HINT
+#define AUTOCOMPLETE_FIELD_HINT(name_, value_)
+#define DEFINED_AUTOCOMPLETE_FIELD_HINT
+#endif
+
+#ifndef AUTOCOMPLETE_FIELD_CONTACT_HINT
+#define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_)
+#define DEFINED_AUTOCOMPLETE_FIELD_CONTACT_HINT
+#endif
+
+#ifndef AUTOCOMPLETE_CATEGORY
+#define AUTOCOMPLETE_CATEGORY(name_, value_)
+#define DEFINED_AUTOCOMPLETE_CATEGORY
+#endif
+
+AUTOCOMPLETE_FIELD_NAME(OFF, "off")
+AUTOCOMPLETE_FIELD_NAME(ON, "on")
+
+// Name types
+AUTOCOMPLETE_FIELD_NAME(NAME, "name")
+// AUTOCOMPLETE_FIELD_NAME(HONORIFIX_PREFIX, "honorifix-prefix")
+AUTOCOMPLETE_FIELD_NAME(GIVEN_NAME, "given-name")
+AUTOCOMPLETE_FIELD_NAME(ADDITIONAL_NAME, "additional-name")
+AUTOCOMPLETE_FIELD_NAME(FAMILY_NAME, "family-name")
+// AUTOCOMPLETE_FIELD_NAME(HONORIFIX_SUFFIX, "honorifix-suffix")
+// AUTOCOMPLETE_FIELD_NAME(NICKNAME, "nickname")
+// AUTOCOMPLETE_FIELD_NAME(ORGANIZATION_TITLE, "organization-title")
+
+// Login types
+AUTOCOMPLETE_FIELD_NAME(USERNAME, "username")
+AUTOCOMPLETE_FIELD_NAME(NEW_PASSWORD, "new-password")
+AUTOCOMPLETE_FIELD_NAME(CURRENT_PASSWORD, "current-password")
+
+// Address types
+AUTOCOMPLETE_FIELD_NAME(ORGANIZATION, "organization")
+AUTOCOMPLETE_FIELD_NAME(STREET_ADDRESS, "street-address")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LINE1, "address-line1")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LINE2, "address-line2")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LINE3, "address-line3")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LEVEL4, "address-level4")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LEVEL3, "address-level3")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LEVEL2, "address-level2")
+AUTOCOMPLETE_FIELD_NAME(ADDRESS_LEVEL1, "address-level1")
+AUTOCOMPLETE_FIELD_NAME(COUNTRY, "country")
+AUTOCOMPLETE_FIELD_NAME(COUNTRY_NAME, "country-name")
+AUTOCOMPLETE_FIELD_NAME(POSTAL_CODE, "postal-code")
+
+// Credit Card types
+// AUTOCOMPLETE_FIELD_NAME(CC_NAME, "cc-name")
+// AUTOCOMPLETE_FIELD_NAME(CC_GIVEN_NAME, "cc-given-name")
+// AUTOCOMPLETE_FIELD_NAME(CC_ADDITIONAL_NAME, "cc-additional-name")
+// AUTOCOMPLETE_FIELD_NAME(CC_FAMILY_NAME, "cc-family-name")
+// AUTOCOMPLETE_FIELD_NAME(CC_NUMBER, "cc-number")
+// AUTOCOMPLETE_FIELD_NAME(CC_EXP, "cc-exp")
+// AUTOCOMPLETE_FIELD_NAME(CC_EXP_MONTH, "cc-exp-month")
+// AUTOCOMPLETE_FIELD_NAME(CC_EXP_YEAR, "cc-exp-year")
+// AUTOCOMPLETE_FIELD_NAME(CC_CSC, "cc-csc")
+// AUTOCOMPLETE_FIELD_NAME(CC_TYPE, "cc-type")
+
+// Additional field types
+// AUTOCOMPLETE_FIELD_NAME(LANGUAGE, "language")
+// AUTOCOMPLETE_FIELD_NAME(BDAY, "bday")
+// AUTOCOMPLETE_FIELD_NAME(BDAY_DAY, "bday-day")
+// AUTOCOMPLETE_FIELD_NAME(BDAY_MONTH, "bday-month")
+// AUTOCOMPLETE_FIELD_NAME(BDAY_YEAR, "bday-year")
+// AUTOCOMPLETE_FIELD_NAME(SEX, "sex")
+// AUTOCOMPLETE_FIELD_NAME(URL, "url")
+// AUTOCOMPLETE_FIELD_NAME(PHOTO, "photo")
+
+// Contact category types
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL, "tel")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_COUNTRY_CODE, "tel-country-code")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_NATIONAL, "tel-national")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_AREA_CODE, "tel-area-code")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_LOCAL, "tel-local")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_LOCAL_PREFIX, "tel-local-prefix")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_LOCAL_SUFFIX, "tel-local-suffix")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(TEL_EXTENSION, "tel-extension")
+AUTOCOMPLETE_CONTACT_FIELD_NAME(EMAIL, "email")
+// AUTOCOMPLETE_CONTACT_FIELD_NAME(IMPP, "impp")
+
+AUTOCOMPLETE_FIELD_HINT(SHIPPING, "shipping")
+AUTOCOMPLETE_FIELD_HINT(BILLING, "billing")
+
+AUTOCOMPLETE_FIELD_CONTACT_HINT(HOME, "home")
+AUTOCOMPLETE_FIELD_CONTACT_HINT(WORK, "work")
+AUTOCOMPLETE_FIELD_CONTACT_HINT(MOBILE, "mobile")
+AUTOCOMPLETE_FIELD_CONTACT_HINT(FAX, "fax")
+// AUTOCOMPLETE_FIELD_CONTACT_HINT(PAGER, "pager")
+
+AUTOCOMPLETE_CATEGORY(NORMAL, "normal")
+AUTOCOMPLETE_CATEGORY(CONTACT, "contact")
+
+#ifdef DEFINED_AUTOCOMPLETE_FIELD_NAME
+#undef AUTOCOMPLETE_FIELD_NAME
+#undef DEFINED_AUTOCOMPLETE_FIELD_NAME
+#endif
+
+#ifdef DEFINED_AUTOCOMPLETE_CONTACT_FIELD_NAME
+#undef AUTOCOMPLETE_CONTACT_FIELD_NAME
+#undef DEFINED_AUTOCOMPLETE_CONTACT_FIELD_NAME
+#endif
+
+#ifdef DEFINED_AUTOCOMPLETE_FIELD_HINT
+#undef AUTOCOMPLETE_FIELD_HINT
+#undef DEFINED_AUTOCOMPLETE_FIELD_HINT
+#endif
+
+#ifdef DEFINED_AUTOCOMPLETE_FIELD_CONTACT_HINT
+#undef AUTOCOMPLETE_FIELD_CONTACT_HINT
+#undef DEFINED_AUTOCOMPLETE_FIELD_CONTACT_HINT
+#endif
+
+#ifdef DEFINED_AUTOCOMPLETE_CATEGORY
+#undef AUTOCOMPLETE_CATEGORY
+#undef DEFINED_AUTOCOMPLETE_CATEGORY
+#endif
--- a/content/base/src/moz.build
+++ b/content/base/src/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS += [
+    'AutocompleteFieldList.h',
     'mozAutoDocUpdate.h',
     'nsAtomListUtils.h',
     'nsAttrAndChildArray.h',
     'nsAttrName.h',
     'nsAttrValue.h',
     'nsAttrValueInlines.h',
     'nsContentList.h',
     'nsContentListDeclarations.h',
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -248,165 +248,77 @@ bool nsContentUtils::sFragmentParsingAct
 
 #if !(defined(DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
 bool nsContentUtils::sDOMWindowDumpEnabled;
 #endif
 
 // Subset of http://www.whatwg.org/specs/web-apps/current-work/#autofill-field-name
 enum AutocompleteFieldName
 {
-  eAutocompleteFieldName_OFF,
-  eAutocompleteFieldName_ON,
-
-  // Name types
-  eAutocompleteFieldName_NAME,
-  //eAutocompleteFieldName_HONORIFIC_PREFIX,
-  eAutocompleteFieldName_GIVEN_NAME,
-  eAutocompleteFieldName_ADDITIONAL_NAME,
-  eAutocompleteFieldName_FAMILY_NAME,
-  //eAutocompleteFieldName_HONORIFIC_SUFFIX,
-  //eAutocompleteFieldName_NICKNAME,
-  //eAutocompleteFieldName_ORGANIZATION_TITLE,
-
-  // Login types
-  eAutocompleteFieldName_USERNAME,
-  eAutocompleteFieldName_NEW_PASSWORD,
-  eAutocompleteFieldName_CURRENT_PASSWORD,
-
-  // Address types
-  eAutocompleteFieldName_ORGANIZATION,
-  eAutocompleteFieldName_STREET_ADDRESS,
-  eAutocompleteFieldName_ADDRESS_LINE1,
-  eAutocompleteFieldName_ADDRESS_LINE2,
-  eAutocompleteFieldName_ADDRESS_LINE3,
-  eAutocompleteFieldName_ADDRESS_LEVEL4,
-  eAutocompleteFieldName_ADDRESS_LEVEL3,
-  eAutocompleteFieldName_ADDRESS_LEVEL2,
-  eAutocompleteFieldName_ADDRESS_LEVEL1,
-  eAutocompleteFieldName_COUNTRY,
-  eAutocompleteFieldName_COUNTRY_NAME,
-  eAutocompleteFieldName_POSTAL_CODE,
-
-  // Credit card types
-  /*
-  eAutocompleteFieldName_CC_NAME,
-  eAutocompleteFieldName_CC_GIVEN_NAME,
-  eAutocompleteFieldName_CC_ADDITIONAL_NAME,
-  eAutocompleteFieldName_CC_FAMILY_NAME,
-  eAutocompleteFieldName_CC_NUMBER,
-  eAutocompleteFieldName_CC_EXP,
-  eAutocompleteFieldName_CC_EXP_MONTH,
-  eAutocompleteFieldName_CC_EXP_YEAR,
-  eAutocompleteFieldName_CC_CSC,
-  eAutocompleteFieldName_CC_TYPE
-  */
-
-  // Additional field types
-  /*
-  eAutocompleteFieldName_LANGUAGE,
-  eAutocompleteFieldName_BDAY,
-  eAutocompleteFieldName_BDAY_DAY,
-  eAutocompleteFieldName_BDAY_MONTH,
-  eAutocompleteFieldName_BDAY_YEAR,
-  eAutocompleteFieldName_SEX,
-  eAutocompleteFieldName_URL,
-  eAutocompleteFieldName_PHOTO,
-  */
-
-  // Contact category types
-  eAutocompleteFieldName_TEL,
-  eAutocompleteFieldName_TEL_COUNTRY_CODE,
-  eAutocompleteFieldName_TEL_NATIONAL,
-  eAutocompleteFieldName_TEL_AREA_CODE,
-  eAutocompleteFieldName_TEL_LOCAL,
-  eAutocompleteFieldName_TEL_LOCAL_PREFIX,
-  eAutocompleteFieldName_TEL_LOCAL_SUFFIX,
-  eAutocompleteFieldName_TEL_EXTENSION,
-  eAutocompleteFieldName_EMAIL,
-  //eAutocompleteFieldName_IMPP,
-
-  eAutocompleteFieldName_last, // Dummy to check table sizes
+  #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
+    eAutocompleteFieldName_##name_,
+  #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
+    AUTOCOMPLETE_FIELD_NAME(name_, value_)
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_NAME
+  #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
 };
 
 enum AutocompleteFieldHint
 {
-  eAutocompleteFieldHint_SHIPPING,
-  eAutocompleteFieldHint_BILLING,
-  eAutocompleteFieldHint_last, // Dummy to check table sizes
+  #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
+    eAutocompleteFieldHint_##name_,
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_HINT
 };
 
 enum AutocompleteFieldContactHint
 {
-  eAutocompleteFieldContactHint_HOME,
-  eAutocompleteFieldContactHint_WORK,
-  eAutocompleteFieldContactHint_MOBILE,
-  eAutocompleteFieldContactHint_FAX,
-  //eAutocompleteFieldContactHint_PAGER,
-  eAutocompleteFieldContactHint_last, // Dummy to check table sizes
+  #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
+    eAutocompleteFieldContactHint_##name_,
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
 };
 
 enum AutocompleteCategory
 {
-  eAutocompleteCategory_NORMAL,
-  eAutocompleteCategory_CONTACT,
+  #define AUTOCOMPLETE_CATEGORY(name_, value_) eAutocompleteCategory_##name_,
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_CATEGORY
 };
 
 static const nsAttrValue::EnumTable kAutocompleteFieldNameTable[] = {
-  { "off", eAutocompleteFieldName_OFF },
-  { "on", eAutocompleteFieldName_ON },
-
-  { "name", eAutocompleteFieldName_NAME },
-  { "given-name", eAutocompleteFieldName_GIVEN_NAME },
-  { "additional-name", eAutocompleteFieldName_ADDITIONAL_NAME },
-  { "family-name", eAutocompleteFieldName_FAMILY_NAME },
-
-  { "username", eAutocompleteFieldName_USERNAME },
-  { "new-password", eAutocompleteFieldName_NEW_PASSWORD },
-  { "current-password", eAutocompleteFieldName_CURRENT_PASSWORD },
-
-  { "organization", eAutocompleteFieldName_ORGANIZATION },
-  { "street-address", eAutocompleteFieldName_STREET_ADDRESS },
-  { "address-line1", eAutocompleteFieldName_ADDRESS_LINE1 },
-  { "address-line2", eAutocompleteFieldName_ADDRESS_LINE2 },
-  { "address-line3", eAutocompleteFieldName_ADDRESS_LINE3 },
-  { "address-level4", eAutocompleteFieldName_ADDRESS_LEVEL4 },
-  { "address-level3", eAutocompleteFieldName_ADDRESS_LEVEL3 },
-  { "address-level2", eAutocompleteFieldName_ADDRESS_LEVEL2 },
-  { "address-level1", eAutocompleteFieldName_ADDRESS_LEVEL1 },
-  { "country", eAutocompleteFieldName_COUNTRY },
-  { "country-name", eAutocompleteFieldName_COUNTRY_NAME },
-  { "postal-code", eAutocompleteFieldName_POSTAL_CODE },
+  #define AUTOCOMPLETE_FIELD_NAME(name_, value_) \
+    { value_, eAutocompleteFieldName_##name_ },
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_NAME
   { 0 }
 };
 
 static const nsAttrValue::EnumTable kAutocompleteContactFieldNameTable[] = {
-  { "tel", eAutocompleteFieldName_TEL },
-  { "tel-country-code", eAutocompleteFieldName_TEL_COUNTRY_CODE },
-  { "tel-national", eAutocompleteFieldName_TEL_NATIONAL },
-  { "tel-area-code", eAutocompleteFieldName_TEL_AREA_CODE },
-  { "tel-local", eAutocompleteFieldName_TEL_LOCAL },
-  { "tel-local-prefix", eAutocompleteFieldName_TEL_LOCAL_PREFIX },
-  { "tel-local-suffix", eAutocompleteFieldName_TEL_LOCAL_SUFFIX },
-  { "tel-extension", eAutocompleteFieldName_TEL_EXTENSION },
-
-  { "email", eAutocompleteFieldName_EMAIL },
+  #define AUTOCOMPLETE_CONTACT_FIELD_NAME(name_, value_) \
+    { value_, eAutocompleteFieldName_##name_ },
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_CONTACT_FIELD_NAME
   { 0 }
 };
 
 static const nsAttrValue::EnumTable kAutocompleteFieldHintTable[] = {
-  { "shipping", eAutocompleteFieldHint_SHIPPING },
-  { "billing", eAutocompleteFieldHint_BILLING },
+  #define AUTOCOMPLETE_FIELD_HINT(name_, value_) \
+    { value_, eAutocompleteFieldHint_##name_ },
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_HINT
   { 0 }
 };
 
 static const nsAttrValue::EnumTable kAutocompleteContactFieldHintTable[] = {
-  { "home", eAutocompleteFieldContactHint_HOME },
-  { "work", eAutocompleteFieldContactHint_WORK },
-  { "mobile", eAutocompleteFieldContactHint_MOBILE },
-  { "fax", eAutocompleteFieldContactHint_FAX },
+  #define AUTOCOMPLETE_FIELD_CONTACT_HINT(name_, value_) \
+    { value_, eAutocompleteFieldContactHint_##name_ },
+  #include "AutocompleteFieldList.h"
+  #undef AUTOCOMPLETE_FIELD_CONTACT_HINT
   { 0 }
 };
 
 namespace {
 
 static NS_DEFINE_CID(kParserServiceCID, NS_PARSERSERVICE_CID);
 static NS_DEFINE_CID(kCParserCID, NS_PARSER_CID);
 
@@ -519,22 +431,16 @@ nsresult
 nsContentUtils::Init()
 {
   if (sInitialized) {
     NS_WARNING("Init() called twice");
 
     return NS_OK;
   }
 
-  // Check that all the entries in the autocomplete enums are handled in EnumTables
-  MOZ_ASSERT(eAutocompleteFieldName_last == ArrayLength(kAutocompleteFieldNameTable)
-             + ArrayLength(kAutocompleteContactFieldNameTable) - 2);
-  MOZ_ASSERT(eAutocompleteFieldHint_last == ArrayLength(kAutocompleteFieldHintTable) - 1);
-  MOZ_ASSERT(eAutocompleteFieldContactHint_last == ArrayLength(kAutocompleteContactFieldHintTable) - 1);
-
   sNameSpaceManager = nsNameSpaceManager::GetInstance();
   NS_ENSURE_TRUE(sNameSpaceManager, NS_ERROR_OUT_OF_MEMORY);
 
   sXPConnect = nsXPConnect::XPConnect();
 
   sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
   if(!sSecurityManager)
     return NS_ERROR_FAILURE;
--- a/content/media/test/mochitest.ini
+++ b/content/media/test/mochitest.ini
@@ -340,16 +340,17 @@ skip-if = buildapp == 'b2g' || e10s # b2
 [test_controls.html]
 [test_currentTime.html]
 [test_decode_error.html]
 [test_decoder_disable.html]
 [test_defaultMuted.html]
 [test_delay_load.html]
 skip-if = buildapp == 'b2g' # bug 1021676
 [test_error_in_video_document.html]
+skip-if = toolkit == 'android' # bug 608634
 [test_error_on_404.html]
 [test_fastSeek.html]
 [test_fastSeek-forwards.html]
 [test_info_leak.html]
 [test_invalid_reject.html]
 [test_load.html]
 [test_load_candidates.html]
 [test_load_same_resource.html]
--- a/dom/alarm/AlarmDB.jsm
+++ b/dom/alarm/AlarmDB.jsm
@@ -31,55 +31,52 @@ AlarmDB.prototype = {
   __proto__: IndexedDBHelper.prototype,
 
   init: function init() {
     debug("init()");
 
     this.initDBHelper(ALARMDB_NAME, ALARMDB_VERSION, [ALARMSTORE_NAME]);
   },
 
-  upgradeSchema: function upgradeSchema(aTransaction, aDb, aOldVersion, aNewVersion) {
+  upgradeSchema: function upgradeSchema(aTransaction, aDb,
+                                        aOldVersion, aNewVersion) {
     debug("upgradeSchema()");
 
-    let objectStore = aDb.createObjectStore(ALARMSTORE_NAME, { keyPath: "id", autoIncrement: true });
+    let objStore =
+      aDb.createObjectStore(ALARMSTORE_NAME,
+                            { keyPath: "id", autoIncrement: true });
 
-    objectStore.createIndex("date",           "date",           { unique: false });
-    objectStore.createIndex("ignoreTimezone", "ignoreTimezone", { unique: false });
-    objectStore.createIndex("timezoneOffset", "timezoneOffset", { unique: false });
-    objectStore.createIndex("data",           "data",           { unique: false });
-    objectStore.createIndex("pageURL",        "pageURL",        { unique: false });
-    objectStore.createIndex("manifestURL",    "manifestURL",    { unique: false });
+    objStore.createIndex("date",           "date",           { unique: false });
+    objStore.createIndex("ignoreTimezone", "ignoreTimezone", { unique: false });
+    objStore.createIndex("timezoneOffset", "timezoneOffset", { unique: false });
+    objStore.createIndex("data",           "data",           { unique: false });
+    objStore.createIndex("pageURL",        "pageURL",        { unique: false });
+    objStore.createIndex("manifestURL",    "manifestURL",    { unique: false });
 
     debug("Created object stores and indexes");
   },
 
   /**
    * @param aAlarm
    *        The record to be added.
    * @param aSuccessCb
    *        Callback function to invoke with result ID.
    * @param aErrorCb [optional]
    *        Callback function to invoke when there was an error.
    */
   add: function add(aAlarm, aSuccessCb, aErrorCb) {
     debug("add()");
 
-    this.newTxn(
-      "readwrite",
-      ALARMSTORE_NAME,
-      function txnCb(aTxn, aStore) {
-        debug("Going to add " + JSON.stringify(aAlarm));
-        aStore.put(aAlarm).onsuccess = function setTxnResult(aEvent) {
-          aTxn.result = aEvent.target.result;
-          debug("Request successful. New record ID: " + aTxn.result);
-        };
-      },
-      aSuccessCb,
-      aErrorCb
-    );
+    this.newTxn("readwrite", ALARMSTORE_NAME, function txnCb(aTxn, aStore) {
+      debug("Going to add " + JSON.stringify(aAlarm));
+      aStore.put(aAlarm).onsuccess = function setTxnResult(aEvent) {
+        aTxn.result = aEvent.target.result;
+        debug("Request successful. New record ID: " + aTxn.result);
+      };
+    }, aSuccessCb, aErrorCb);
   },
 
   /**
    * @param aId
    *        The ID of record to be removed.
    * @param aManifestURL
    *        The manifest URL of the app that alarm belongs to.
    *        If null, directly remove the ID record; otherwise,
@@ -87,69 +84,57 @@ AlarmDB.prototype = {
    * @param aSuccessCb
    *        Callback function to invoke with result.
    * @param aErrorCb [optional]
    *        Callback function to invoke when there was an error.
    */
   remove: function remove(aId, aManifestURL, aSuccessCb, aErrorCb) {
     debug("remove()");
 
-    this.newTxn(
-      "readwrite",
-      ALARMSTORE_NAME,
-      function txnCb(aTxn, aStore) {
-        debug("Going to remove " + aId);
+    this.newTxn("readwrite", ALARMSTORE_NAME, function txnCb(aTxn, aStore) {
+      debug("Going to remove " + aId);
 
-        // Look up the existing record and compare the manifestURL
-        // to see if the alarm to be removed belongs to this app.
-        aStore.get(aId).onsuccess = function doRemove(aEvent) {
-          let alarm = aEvent.target.result;
+      // Look up the existing record and compare the manifestURL
+      // to see if the alarm to be removed belongs to this app.
+      aStore.get(aId).onsuccess = function doRemove(aEvent) {
+        let alarm = aEvent.target.result;
 
-          if (!alarm) {
-            debug("Alarm doesn't exist. No need to remove it.");
-            return;
-          }
+        if (!alarm) {
+          debug("Alarm doesn't exist. No need to remove it.");
+          return;
+        }
 
-          if (aManifestURL && aManifestURL != alarm.manifestURL) {
-            debug("Cannot remove the alarm added by other apps.");
-            return;
-          }
+        if (aManifestURL && aManifestURL != alarm.manifestURL) {
+          debug("Cannot remove the alarm added by other apps.");
+          return;
+        }
 
-          aStore.delete(aId);
-        };
-      },
-      aSuccessCb,
-      aErrorCb
-    );
+        aStore.delete(aId);
+      };
+    }, aSuccessCb, aErrorCb);
   },
 
   /**
    * @param aManifestURL
    *        The manifest URL of the app that alarms belong to.
    *        If null, directly return all alarms; otherwise,
    *        only return the alarms that belong to this app.
    * @param aSuccessCb
    *        Callback function to invoke with result array.
    * @param aErrorCb [optional]
    *        Callback function to invoke when there was an error.
    */
   getAll: function getAll(aManifestURL, aSuccessCb, aErrorCb) {
     debug("getAll()");
 
-    this.newTxn(
-      "readonly",
-      ALARMSTORE_NAME,
-      function txnCb(aTxn, aStore) {
-        if (!aTxn.result) {
-          aTxn.result = [];
-        }
+    this.newTxn("readonly", ALARMSTORE_NAME, function txnCb(aTxn, aStore) {
+      if (!aTxn.result) {
+        aTxn.result = [];
+      }
 
-        let index = aStore.index("manifestURL");
-        index.mozGetAll(aManifestURL).onsuccess = function setTxnResult(aEvent) {
-          aTxn.result = aEvent.target.result;
-          debug("Request successful. Record count: " + aTxn.result.length);
-        };
-      },
-      aSuccessCb,
-      aErrorCb
-    );
+      let index = aStore.index("manifestURL");
+      index.mozGetAll(aManifestURL).onsuccess = function setTxnResult(aEvent) {
+        aTxn.result = aEvent.target.result;
+        debug("Request successful. Record count: " + aTxn.result.length);
+      };
+    }, aSuccessCb, aErrorCb);
   }
 };
--- a/dom/alarm/AlarmService.jsm
+++ b/dom/alarm/AlarmService.jsm
@@ -24,45 +24,47 @@ XPCOMUtils.defineLazyGetter(this, "appsS
   return Cc["@mozilla.org/AppsService;1"].getService(Ci.nsIAppsService);
 });
 
 XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                    "@mozilla.org/parentprocessmessagemanager;1",
                                    "nsIMessageListenerManager");
 
 XPCOMUtils.defineLazyGetter(this, "messenger", function() {
-  return Cc["@mozilla.org/system-message-internal;1"].getService(Ci.nsISystemMessagesInternal);
+  return Cc["@mozilla.org/system-message-internal;1"]
+           .getService(Ci.nsISystemMessagesInternal);
 });
 
 XPCOMUtils.defineLazyGetter(this, "powerManagerService", function() {
-  return Cc["@mozilla.org/power/powermanagerservice;1"].getService(Ci.nsIPowerManagerService);
+  return Cc["@mozilla.org/power/powermanagerservice;1"]
+           .getService(Ci.nsIPowerManagerService);
 });
 
 /**
  * AlarmService provides an API to schedule alarms using the device's RTC.
  *
  * AlarmService is primarily used by the mozAlarms API (navigator.mozAlarms)
  * which uses IPC to communicate with the service.
  *
  * AlarmService can also be used by Gecko code by importing the module and then
  * using AlarmService.add() and AlarmService.remove(). Only Gecko code running
  * in the parent process should do this.
  */
 
 this.AlarmService = {
   init: function init() {
     debug("init()");
+
     Services.obs.addObserver(this, "profile-change-teardown", false);
     Services.obs.addObserver(this, "webapps-clear-data",false);
 
     this._currentTimezoneOffset = (new Date()).getTimezoneOffset();
 
-    let alarmHalService =
-      this._alarmHalService = Cc["@mozilla.org/alarmHalService;1"]
-                              .getService(Ci.nsIAlarmHalService);
+    let alarmHalService = this._alarmHalService =
+      Cc["@mozilla.org/alarmHalService;1"].getService(Ci.nsIAlarmHalService);
 
     alarmHalService.setAlarmFiredCb(this._onAlarmFired.bind(this));
     alarmHalService.setTimezoneChangedCb(this._onTimezoneChanged.bind(this));
 
     // Add the messages to be listened to.
     this._messages = ["AlarmsManager:GetAll",
                       "AlarmsManager:Add",
                       "AlarmsManager:Remove"];
@@ -104,54 +106,52 @@ this.AlarmService = {
 
     // To prevent the hacked child process from sending commands to parent
     // to schedule alarms, we need to check its permission and manifest URL.
     if (this._messages.indexOf(aMessage.name) != -1) {
       if (!aMessage.target.assertPermission("alarms")) {
         debug("Got message from a child process with no 'alarms' permission.");
         return null;
       }
+
       if (!aMessage.target.assertContainApp(json.manifestURL)) {
         debug("Got message from a child process containing illegal manifest URL.");
         return null;
       }
     }
 
     let mm = aMessage.target.QueryInterface(Ci.nsIMessageSender);
+
     switch (aMessage.name) {
       case "AlarmsManager:GetAll":
-        this._db.getAll(
-          json.manifestURL,
+        this._db.getAll(json.manifestURL,
           function getAllSuccessCb(aAlarms) {
             debug("Callback after getting alarms from database: " +
                   JSON.stringify(aAlarms));
+
             this._sendAsyncMessage(mm, "GetAll", true, json.requestId, aAlarms);
           }.bind(this),
           function getAllErrorCb(aErrorMsg) {
             this._sendAsyncMessage(mm, "GetAll", false, json.requestId, aErrorMsg);
-          }.bind(this)
-        );
+          }.bind(this));
         break;
 
       case "AlarmsManager:Add":
         // Prepare a record for the new alarm to be added.
-        let newAlarm = {
-          date: json.date,
-          ignoreTimezone: json.ignoreTimezone,
-          data: json.data,
-          pageURL: json.pageURL,
-          manifestURL: json.manifestURL
-        };
+        let newAlarm = { date: json.date,
+                         ignoreTimezone: json.ignoreTimezone,
+                         data: json.data,
+                         pageURL: json.pageURL,
+                         manifestURL: json.manifestURL };
 
         this.add(newAlarm, null,
           // Receives the alarm ID as the last argument.
           this._sendAsyncMessage.bind(this, mm, "Add", true, json.requestId),
           // Receives the error message as the last argument.
-          this._sendAsyncMessage.bind(this, mm, "Add", false, json.requestId)
-        );
+          this._sendAsyncMessage.bind(this, mm, "Add", false, json.requestId));
         break;
 
       case "AlarmsManager:Remove":
         this.remove(json.id, json.manifestURL);
         break;
 
       default:
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
@@ -164,18 +164,17 @@ this.AlarmService = {
     debug("_sendAsyncMessage()");
 
     if (!aMessageManager) {
       debug("Invalid message manager: null");
       throw Components.results.NS_ERROR_FAILURE;
     }
 
     let json = null;
-    switch (aMessageName)
-    {
+    switch (aMessageName) {
       case "Add":
         json = aSuccess ?
           { requestId: aRequestId, id: aData } :
           { requestId: aRequestId, errorMsg: aData };
         break;
 
       case "GetAll":
         json = aSuccess ?
@@ -184,66 +183,63 @@ this.AlarmService = {
         break;
 
       default:
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
         break;
     }
 
     aMessageManager.sendAsyncMessage("AlarmsManager:" + aMessageName +
-                                     ":Return:" + (aSuccess ? "OK" : "KO"), json);
+                                       ":Return:" + (aSuccess ? "OK" : "KO"),
+                                     json);
   },
 
   _removeAlarmFromDb: function _removeAlarmFromDb(aId, aManifestURL,
                                                   aRemoveSuccessCb) {
     debug("_removeAlarmFromDb()");
 
     // If the aRemoveSuccessCb is undefined or null, set a dummy callback for
     // it which is needed for _db.remove().
     if (!aRemoveSuccessCb) {
       aRemoveSuccessCb = function removeSuccessCb() {
         debug("Remove alarm from DB successfully.");
       };
     }
 
-    this._db.remove(
-      aId,
-      aManifestURL,
-      aRemoveSuccessCb,
-      function removeErrorCb(aErrorMsg) {
-        throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-      }
-    );
+    this._db.remove(aId, aManifestURL, aRemoveSuccessCb,
+                    function removeErrorCb(aErrorMsg) {
+                      throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+                    });
   },
 
   /**
    * Create a copy of the alarm that does not expose internal fields to
    * receivers and sticks to the public |respectTimezone| API rather than the
    * boolean |ignoreTimezone| field.
    */
   _publicAlarm: function _publicAlarm(aAlarm) {
-    let alarm = {
-      "id":              aAlarm.id,
-      "date":            aAlarm.date,
-      "respectTimezone": aAlarm.ignoreTimezone ?
-                           "ignoreTimezone" : "honorTimezone",
-      "data":            aAlarm.data
-    };
+    let alarm = { "id": aAlarm.id,
+                  "date": aAlarm.date,
+                  "respectTimezone": aAlarm.ignoreTimezone ?
+                                       "ignoreTimezone" : "honorTimezone",
+                  "data": aAlarm.data };
 
     return alarm;
   },
 
   _fireSystemMessage: function _fireSystemMessage(aAlarm) {
     debug("Fire system message: " + JSON.stringify(aAlarm));
 
     let manifestURI = Services.io.newURI(aAlarm.manifestURL, null, null);
     let pageURI = Services.io.newURI(aAlarm.pageURL, null, null);
 
-    messenger.sendMessage("alarm", this._publicAlarm(aAlarm),
-                          pageURI, manifestURI);
+    messenger.sendMessage("alarm",
+                          this._publicAlarm(aAlarm),
+                          pageURI,
+                          manifestURI);
   },
 
   _notifyAlarmObserver: function _notifyAlarmObserver(aAlarm) {
     debug("_notifyAlarmObserver()");
 
     if (aAlarm.manifestURL) {
       this._fireSystemMessage(aAlarm);
     } else if (typeof aAlarm.alarmFiredCb === "function") {
@@ -271,31 +267,31 @@ this.AlarmService = {
       if (nextAlarmTime <= Date.now()) {
         this._removeAlarmFromDb(nextAlarm.id, null);
         this._notifyAlarmObserver(nextAlarm);
       } else {
         this._currentAlarm = nextAlarm;
         break;
       }
     }
+
     this._debugCurrentAlarm();
   },
 
   _onTimezoneChanged: function _onTimezoneChanged(aTimezoneOffset) {
     debug("_onTimezoneChanged()");
 
     this._currentTimezoneOffset = aTimezoneOffset;
     this._restoreAlarmsFromDb();
   },
 
   _restoreAlarmsFromDb: function _restoreAlarmsFromDb() {
     debug("_restoreAlarmsFromDb()");
 
-    this._db.getAll(
-      null,
+    this._db.getAll(null,
       function getAllSuccessCb(aAlarms) {
         debug("Callback after getting alarms from database: " +
               JSON.stringify(aAlarms));
 
         // Clear any alarms set or queued in the cache.
         let alarmQueue = this._alarmQueue;
         alarmQueue.length = 0;
         this._currentAlarm = null;
@@ -306,28 +302,27 @@ this.AlarmService = {
           if (this._getAlarmTime(aAlarm) > Date.now()) {
             alarmQueue.push(aAlarm);
           } else {
             this._removeAlarmFromDb(aAlarm.id, null);
             this._notifyAlarmObserver(aAlarm);
           }
         }.bind(this));
 
-        // Set the next alarm from queue.
+        // Set the next alarm from the queue.
         if (alarmQueue.length) {
           alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
           this._currentAlarm = alarmQueue.shift();
         }
 
         this._debugCurrentAlarm();
       }.bind(this),
       function getAllErrorCb(aErrorMsg) {
         throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-      }
-    );
+      });
   },
 
   _getAlarmTime: function _getAlarmTime(aAlarm) {
     // Avoid casting a Date object to a Date again to
     // preserve milliseconds. See bug 810973.
     let alarmTime;
     if (aAlarm.date instanceof Date) {
       alarmTime = aAlarm.date.getTime();
@@ -336,17 +331,18 @@ this.AlarmService = {
     }
 
     // For an alarm specified with "ignoreTimezone", it must be fired respect
     // to the user's timezone.  Supposing an alarm was set at 7:00pm at Tokyo,
     // it must be gone off at 7:00pm respect to Paris' local time when the user
     // is located at Paris.  We can adjust the alarm UTC time by calculating
     // the difference of the orginal timezone and the current timezone.
     if (aAlarm.ignoreTimezone) {
-       alarmTime += (this._currentTimezoneOffset - aAlarm.timezoneOffset) * 60000;
+      alarmTime +=
+        (this._currentTimezoneOffset - aAlarm.timezoneOffset) * 60000;
     }
     return alarmTime;
   },
 
   _sortAlarmByTimeStamps: function _sortAlarmByTimeStamps(aAlarm1, aAlarm2) {
     return this._getAlarmTime(aAlarm1) - this._getAlarmTime(aAlarm2);
   },
 
@@ -397,18 +393,17 @@ this.AlarmService = {
 
     if (!aNewAlarm.date) {
       aErrorCb("alarm.date is null");
       return;
     }
 
     aNewAlarm['timezoneOffset'] = this._currentTimezoneOffset;
 
-    this._db.add(
-      aNewAlarm,
+    this._db.add(aNewAlarm,
       function addSuccessCb(aNewId) {
         debug("Callback after adding alarm in database.");
 
         aNewAlarm['id'] = aNewId;
 
         // Now that the alarm has been added to the database, we can tack on
         // the non-serializable callback to the in-memory object.
         aNewAlarm['alarmFiredCb'] = aAlarmFiredCb;
@@ -417,17 +412,17 @@ this.AlarmService = {
         if (this._currentAlarm == null) {
           this._currentAlarm = aNewAlarm;
           this._debugCurrentAlarm();
           aSuccessCb(aNewId);
           return;
         }
 
         // If the new alarm is earlier than the current alarm, swap them and
-        // push the previous alarm back to queue.
+        // push the previous alarm back to the queue.
         let alarmQueue = this._alarmQueue;
         let aNewAlarmTime = this._getAlarmTime(aNewAlarm);
         let currentAlarmTime = this._getAlarmTime(this._currentAlarm);
         if (aNewAlarmTime < currentAlarmTime) {
           alarmQueue.unshift(this._currentAlarm);
           this._currentAlarm = aNewAlarm;
           this._debugCurrentAlarm();
           aSuccessCb(aNewId);
@@ -437,34 +432,32 @@ this.AlarmService = {
         // Push the new alarm in the queue.
         alarmQueue.push(aNewAlarm);
         alarmQueue.sort(this._sortAlarmByTimeStamps.bind(this));
         this._debugCurrentAlarm();
         aSuccessCb(aNewId);
       }.bind(this),
       function addErrorCb(aErrorMsg) {
         aErrorCb(aErrorMsg);
-      }.bind(this)
-    );
+      }.bind(this));
   },
 
   /*
    * Remove the alarm associated with an ID.
    *
    * @param number aAlarmId
    *        The ID of the alarm to be removed.
    * @param string aManifestURL
    *        Manifest URL for application which added the alarm. (Optional)
    * @returns void
    */
   remove: function(aAlarmId, aManifestURL) {
     debug("remove(" + aAlarmId + ", " + aManifestURL + ")");
-    this._removeAlarmFromDb(
-      aAlarmId,
-      aManifestURL,
+
+    this._removeAlarmFromDb(aAlarmId, aManifestURL,
       function removeSuccessCb() {
         debug("Callback after removing alarm from database.");
 
         // If there are no alarms set, nothing to do.
         if (!this._currentAlarm) {
           debug("No alarms set.");
           return;
         }
@@ -483,35 +476,37 @@ this.AlarmService = {
               break;
             }
           }
           this._debugCurrentAlarm();
           return;
         }
 
         // The alarm to be removed is the current alarm reset the next alarm
-        // from queue if any.
+        // from the queue if any.
         if (alarmQueue.length) {
           this._currentAlarm = alarmQueue.shift();
           this._debugCurrentAlarm();
           return;
         }
 
         // No alarm waiting to be set in the queue.
         this._currentAlarm = null;
         this._debugCurrentAlarm();
-      }.bind(this)
-    );
+      }.bind(this));
   },
 
   observe: function(aSubject, aTopic, aData) {
+    debug("observe(): " + aTopic);
+
     switch (aTopic) {
       case "profile-change-teardown":
         this.uninit();
         break;
+
       case "webapps-clear-data":
         let params =
           aSubject.QueryInterface(Ci.mozIApplicationClearPrivateDataParams);
         if (!params) {
           debug("Error! Fail to remove alarms for an uninstalled app.");
           return;
         }
 
@@ -521,33 +516,32 @@ this.AlarmService = {
         }
 
         let manifestURL = appsService.getManifestURLByLocalId(params.appId);
         if (!manifestURL) {
           debug("Error! Fail to remove alarms for an uninstalled app.");
           return;
         }
 
-        this._db.getAll(
-          manifestURL,
+        this._db.getAll(manifestURL,
           function getAllSuccessCb(aAlarms) {
             aAlarms.forEach(function removeAlarm(aAlarm) {
               this.remove(aAlarm.id, manifestURL);
             }, this);
           }.bind(this),
           function getAllErrorCb(aErrorMsg) {
             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
-          }
-        );
+          });
         break;
     }
   },
 
   uninit: function uninit() {
     debug("uninit()");
+
     Services.obs.removeObserver(this, "profile-change-teardown");
     Services.obs.removeObserver(this, "webapps-clear-data");
 
     this._messages.forEach(function(aMsgName) {
       ppmm.removeMessageListener(aMsgName, this);
     }.bind(this));
     ppmm = null;
 
--- a/dom/alarm/AlarmsManager.js
+++ b/dom/alarm/AlarmsManager.js
@@ -13,23 +13,21 @@ function debug(aStr) {
 }
 
 const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
 
-function AlarmsManager()
-{
+function AlarmsManager() {
   debug("Constructor");
 }
 
 AlarmsManager.prototype = {
-
   __proto__: DOMRequestIpcHelper.prototype,
 
   contractID : "@mozilla.org/alarmsManager;1",
 
   classID : Components.ID("{fea1e884-9b05-11e1-9b64-87a7016c3860}"),
 
   QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer,
                                           Ci.nsISupportsWeakReference,
@@ -43,60 +41,56 @@ AlarmsManager.prototype = {
       throw Components.results.NS_ERROR_FAILURE;
     }
 
     if (!aDate) {
       throw Components.results.NS_ERROR_INVALID_ARG;
     }
 
     let isIgnoreTimezone = true;
+
     switch (aRespectTimezone) {
       case "honorTimezone":
         isIgnoreTimezone = false;
         break;
 
       case "ignoreTimezone":
         isIgnoreTimezone = true;
         break;
 
       default:
         throw Components.results.NS_ERROR_INVALID_ARG;
         break;
     }
 
     let request = this.createRequest();
-    this._cpmm.sendAsyncMessage(
-      "AlarmsManager:Add",
-      { requestId: this.getRequestId(request),
-        date: aDate,
-        ignoreTimezone: isIgnoreTimezone,
-        data: aData,
-        pageURL: this._pageURL,
-        manifestURL: this._manifestURL }
-    );
+    this._cpmm.sendAsyncMessage("AlarmsManager:Add",
+                                { requestId: this.getRequestId(request),
+                                  date: aDate,
+                                  ignoreTimezone: isIgnoreTimezone,
+                                  data: aData,
+                                  pageURL: this._pageURL,
+                                  manifestURL: this._manifestURL });
     return request;
   },
 
   remove: function remove(aId) {
     debug("remove()");
 
-    this._cpmm.sendAsyncMessage(
-      "AlarmsManager:Remove",
-      { id: aId, manifestURL: this._manifestURL }
-    );
+    this._cpmm.sendAsyncMessage("AlarmsManager:Remove",
+                                { id: aId, manifestURL: this._manifestURL });
   },
 
   getAll: function getAll() {
     debug("getAll()");
 
     let request = this.createRequest();
-    this._cpmm.sendAsyncMessage(
-      "AlarmsManager:GetAll",
-      { requestId: this.getRequestId(request), manifestURL: this._manifestURL }
-    );
+    this._cpmm.sendAsyncMessage("AlarmsManager:GetAll",
+                                { requestId: this.getRequestId(request),
+                                  manifestURL: this._manifestURL });
     return request;
   },
 
   receiveMessage: function receiveMessage(aMessage) {
     debug("receiveMessage(): " + aMessage.name);
 
     let json = aMessage.json;
     let request = this.getRequest(json.requestId);
@@ -110,39 +104,41 @@ AlarmsManager.prototype = {
       case "AlarmsManager:Add:Return:OK":
         Services.DOMRequest.fireSuccess(request, json.id);
         break;
 
       case "AlarmsManager:GetAll:Return:OK":
         // We don't need to expose everything to the web content.
         let alarms = [];
         json.alarms.forEach(function trimAlarmInfo(aAlarm) {
-          let alarm = { "id":              aAlarm.id,
-                        "date":            aAlarm.date,
+          let alarm = { "id": aAlarm.id,
+                        "date": aAlarm.date,
                         "respectTimezone": aAlarm.ignoreTimezone ?
                                              "ignoreTimezone" : "honorTimezone",
-                        "data":            aAlarm.data };
+                        "data": aAlarm.data };
           alarms.push(alarm);
         });
+
         Services.DOMRequest.fireSuccess(request,
                                         Cu.cloneInto(alarms, this._window));
         break;
 
       case "AlarmsManager:Add:Return:KO":
         Services.DOMRequest.fireError(request, json.errorMsg);
         break;
 
       case "AlarmsManager:GetAll:Return:KO":
         Services.DOMRequest.fireError(request, json.errorMsg);
         break;
 
       default:
         debug("Wrong message: " + aMessage.name);
         break;
     }
+
     this.removeRequest(json.requestId);
    },
 
   // nsIDOMGlobalPropertyInitializer implementation
   init: function init(aWindow) {
     debug("init()");
 
     this._cpmm = Cc["@mozilla.org/childprocessmessagemanager;1"]
--- a/dom/bindings/test/test_exceptions_from_jsimplemented.html
+++ b/dom/bindings/test/test_exceptions_from_jsimplemented.html
@@ -15,17 +15,17 @@ https://bugzilla.mozilla.org/show_bug.cg
     try {
       conn.createAnswer(function() {
           ok(false, "The call to createAnswer succeeded when it should have thrown");
         }, function() {
           ok(false, "The call to createAnswer failed when it should have thrown");
         }, { "mandatory": { "BOGUS": 5 } } )
       ok(false, "That call to createAnswer should have thrown");
     } catch (e) {
-      is(e.lineNumber, 20, "Exception should have been on line 20");
+      is(e.lineNumber, 16, "Exception should have been on line 16");
       is(e.message,
          "createAnswer passed invalid constraints - unknown mandatory constraint: BOGUS",
          "Should have the exception we expect");
     }
   } catch (e) {
     // b2g has no WebRTC, apparently
     todo(false, "No WebRTC on b2g yet");
   }
--- a/dom/bluetooth/BluetoothAdapter.cpp
+++ b/dom/bluetooth/BluetoothAdapter.cpp
@@ -1,27 +1,27 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
-#include "nsCxPusher.h"
 #include "nsDOMClassInfo.h"
 #include "nsTArrayHelpers.h"
 #include "DOMRequest.h"
 #include "nsThreadUtils.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothAdapterBinding.h"
 #include "mozilla/dom/BluetoothDeviceEvent.h"
 #include "mozilla/dom/BluetoothDiscoveryStateChangedEvent.h"
 #include "mozilla/dom/BluetoothStatusChangedEvent.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/LazyIdleThread.h"
 
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 
@@ -90,28 +90,25 @@ public:
       }
       nsRefPtr<BluetoothDevice> d =
         BluetoothDevice::Create(mAdapterPtr->GetOwner(),
                                 mAdapterPtr->GetPath(),
                                 properties);
       devices.AppendElement(d);
     }
 
-    nsresult rv;
-    nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
-    if (!sc) {
-      BT_WARNING("Cannot create script context!");
-      SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(mAdapterPtr->GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      SetError(NS_LITERAL_STRING("BluetoothAutoJSAPIInitError"));
       return false;
     }
-
-    AutoPushJSContext cx(sc->GetNativeContext());
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> JsDevices(cx);
-    rv = nsTArrayToJSArray(cx, devices, &JsDevices);
-    if (!JsDevices) {
+    if (NS_FAILED(nsTArrayToJSArray(cx, devices, &JsDevices))) {
       BT_WARNING("Cannot create JS array!");
       SetError(NS_LITERAL_STRING("BluetoothError"));
       return false;
     }
 
     aValue.setObject(*JsDevices);
     return true;
   }
@@ -248,38 +245,39 @@ BluetoothAdapter::SetPropertyByValue(con
   } else if (name.EqualsLiteral("PairableTimeout")) {
     mPairableTimeout = value.get_uint32_t();
   } else if (name.EqualsLiteral("DiscoverableTimeout")) {
     mDiscoverableTimeout = value.get_uint32_t();
   } else if (name.EqualsLiteral("Class")) {
     mClass = value.get_uint32_t();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> uuids(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
       BT_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     mJsUuids = uuids;
     Root();
   } else if (name.EqualsLiteral("Devices")) {
     mDeviceAddresses = value.get_ArrayOfnsString();
 
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
-
-    AutoPushJSContext cx(sc->GetNativeContext());
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> deviceAddresses(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses, &deviceAddresses))) {
       BT_WARNING("Cannot set JS Devices object!");
       return;
     }
     mJsDeviceAddresses = deviceAddresses;
     Root();
   } else {
--- a/dom/bluetooth/BluetoothDevice.cpp
+++ b/dom/bluetooth/BluetoothDevice.cpp
@@ -10,16 +10,17 @@
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 
 #include "nsDOMClassInfo.h"
 #include "nsTArrayHelpers.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothDeviceBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothDevice, BluetoothDevice)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
@@ -124,39 +125,39 @@ BluetoothDevice::SetPropertyByValue(cons
   } else if (name.EqualsLiteral("Icon")) {
     mIcon = value.get_nsString();
   } else if (name.EqualsLiteral("Connected")) {
     mConnected = value.get_bool();
   } else if (name.EqualsLiteral("Paired")) {
     mPaired = value.get_bool();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
-
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> uuids(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
       BT_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     mJsUuids = uuids;
     Root();
   } else if (name.EqualsLiteral("Services")) {
     mServices = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
-
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> services(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mServices, &services))) {
       BT_WARNING("Cannot set JS Services object!");
       return;
     }
     mJsServices = services;
     Root();
   } else {
--- a/dom/bluetooth/BluetoothManager.cpp
+++ b/dom/bluetooth/BluetoothManager.cpp
@@ -13,16 +13,17 @@
 
 #include "DOMRequest.h"
 #include "nsContentUtils.h"
 #include "nsDOMClassInfo.h"
 #include "nsIPermissionManager.h"
 #include "nsThreadUtils.h"
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothManagerBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Services.h"
 
 using namespace mozilla;
 
 USING_BLUETOOTH_NAMESPACE
 
 // QueryInterface implementation for BluetoothManager
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(BluetoothManager)
@@ -62,30 +63,24 @@ public:
       return false;
     }
 
     const InfallibleTArray<BluetoothNamedValue>& values =
       v.get_ArrayOfBluetoothNamedValue();
     nsRefPtr<BluetoothAdapter> adapter =
       BluetoothAdapter::Create(mManagerPtr->GetOwner(), values);
 
-    nsresult rv;
-    nsIScriptContext* sc = mManagerPtr->GetContextForEventHandlers(&rv);
-    if (!sc) {
-      BT_WARNING("Cannot create script context!");
-      SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
+    dom::AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(mManagerPtr->GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      SetError(NS_LITERAL_STRING("BluetoothAutoJSAPIInitError"));
       return false;
     }
-
-    AutoPushJSContext cx(sc->GetNativeContext());
-
-    JS::Rooted<JSObject*> scope(cx, sc->GetWindowProxy());
-    JSAutoCompartment ac(cx, scope);
-    rv = nsContentUtils::WrapNative(cx, adapter, aValue);
-    if (NS_FAILED(rv)) {
+    JSContext* cx = jsapi.cx();
+    if (NS_FAILED(nsContentUtils::WrapNative(cx, adapter, aValue))) {
       BT_WARNING("Cannot create native object!");
       SetError(NS_LITERAL_STRING("BluetoothNativeObjectError"));
       return false;
     }
 
     return true;
   }
 
--- a/dom/bluetooth2/BluetoothAdapter.cpp
+++ b/dom/bluetooth2/BluetoothAdapter.cpp
@@ -1,27 +1,27 @@
 /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "base/basictypes.h"
-#include "nsCxPusher.h"
 #include "nsDOMClassInfo.h"
 #include "nsTArrayHelpers.h"
 #include "DOMRequest.h"
 #include "nsThreadUtils.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothAdapter2Binding.h"
 #include "mozilla/dom/BluetoothAttributeEvent.h"
 #include "mozilla/dom/BluetoothDeviceEvent.h"
 #include "mozilla/dom/BluetoothStatusChangedEvent.h"
 #include "mozilla/dom/ContentChild.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/LazyIdleThread.h"
 
 #include "BluetoothAdapter.h"
 #include "BluetoothDevice.h"
 #include "BluetoothReplyRunnable.h"
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 
@@ -90,28 +90,25 @@ public:
       }
       nsRefPtr<BluetoothDevice> d =
         BluetoothDevice::Create(mAdapterPtr->GetOwner(),
                                 mAdapterPtr->GetPath(),
                                 properties);
       devices.AppendElement(d);
     }
 
-    nsresult rv;
-    nsIScriptContext* sc = mAdapterPtr->GetContextForEventHandlers(&rv);
-    if (!sc) {
-      BT_WARNING("Cannot create script context!");
-      SetError(NS_LITERAL_STRING("BluetoothScriptContextError"));
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(mAdapterPtr->GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      SetError(NS_LITERAL_STRING("BluetoothAutoJSAPIInitError"));
       return false;
     }
-
-    AutoPushJSContext cx(sc->GetNativeContext());
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> JsDevices(cx);
-    rv = nsTArrayToJSArray(cx, devices, &JsDevices);
-    if (!JsDevices) {
+    if (NS_FAILED(nsTArrayToJSArray(cx, devices, &JsDevices))) {
       BT_WARNING("Cannot create JS array!");
       SetError(NS_LITERAL_STRING("BluetoothError"));
       return false;
     }
 
     aValue.setObject(*JsDevices);
     return true;
   }
@@ -254,38 +251,39 @@ BluetoothAdapter::SetPropertyByValue(con
   } else if (name.EqualsLiteral("PairableTimeout")) {
     mPairableTimeout = value.get_uint32_t();
   } else if (name.EqualsLiteral("DiscoverableTimeout")) {
     mDiscoverableTimeout = value.get_uint32_t();
   } else if (name.EqualsLiteral("Class")) {
     mClass = value.get_uint32_t();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> uuids(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
       BT_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     mJsUuids = uuids;
     Root();
   } else if (name.EqualsLiteral("Devices")) {
     mDeviceAddresses = value.get_ArrayOfnsString();
 
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
-
-    AutoPushJSContext cx(sc->GetNativeContext());
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> deviceAddresses(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mDeviceAddresses, &deviceAddresses))) {
       BT_WARNING("Cannot set JS Devices object!");
       return;
     }
     mJsDeviceAddresses = deviceAddresses;
     Root();
   } else {
--- a/dom/bluetooth2/BluetoothDevice.cpp
+++ b/dom/bluetooth2/BluetoothDevice.cpp
@@ -10,16 +10,17 @@
 #include "BluetoothService.h"
 #include "BluetoothUtils.h"
 
 #include "nsDOMClassInfo.h"
 #include "nsTArrayHelpers.h"
 
 #include "mozilla/dom/bluetooth/BluetoothTypes.h"
 #include "mozilla/dom/BluetoothDevice2Binding.h"
+#include "mozilla/dom/ScriptSettings.h"
 
 USING_BLUETOOTH_NAMESPACE
 
 DOMCI_DATA(BluetoothDevice, BluetoothDevice)
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(BluetoothDevice)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(BluetoothDevice,
@@ -124,39 +125,39 @@ BluetoothDevice::SetPropertyByValue(cons
   } else if (name.EqualsLiteral("Icon")) {
     mIcon = value.get_nsString();
   } else if (name.EqualsLiteral("Connected")) {
     mConnected = value.get_bool();
   } else if (name.EqualsLiteral("Paired")) {
     mPaired = value.get_bool();
   } else if (name.EqualsLiteral("UUIDs")) {
     mUuids = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
-
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> uuids(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mUuids, &uuids))) {
       BT_WARNING("Cannot set JS UUIDs object!");
       return;
     }
     mJsUuids = uuids;
     Root();
   } else if (name.EqualsLiteral("Services")) {
     mServices = value.get_ArrayOfnsString();
-    nsresult rv;
-    nsIScriptContext* sc = GetContextForEventHandlers(&rv);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    NS_ENSURE_TRUE_VOID(sc);
 
-    AutoPushJSContext cx(sc->GetNativeContext());
-
+    AutoJSAPI jsapi;
+    if (!jsapi.InitUsingWin(GetOwner())) {
+      BT_WARNING("Failed to initialise AutoJSAPI!");
+      return;
+    }
+    JSContext* cx = jsapi.cx();
     JS::Rooted<JSObject*> services(cx);
     if (NS_FAILED(nsTArrayToJSArray(cx, mServices, &services))) {
       BT_WARNING("Cannot set JS Services object!");
       return;
     }
     mJsServices = services;
     Root();
   } else {
--- a/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
+++ b/dom/cellbroadcast/interfaces/nsIDOMMozCellBroadcastMessage.idl
@@ -6,20 +6,25 @@
 #include "nsISupports.idl"
 
 interface nsIDOMMozCellBroadcastEtwsInfo;
 
 /**
  * MozCellBroadcastMessage encapsulates Cell Broadcast short message service
  * (CBS) messages.
  */
-[scriptable, uuid(701e74a9-5fc4-4e2d-a324-9b7693395159)]
+[scriptable, uuid(dc729df4-f1d8-11e3-b00d-d3332542c557)]
 interface nsIDOMMozCellBroadcastMessage : nsISupports
 {
   /**
+   * The Service Id in the device where the message is received from.
+   */
+  readonly attribute unsigned long serviceId;
+
+  /**
    * Indication of the geographical area over which the Message Code is unique,
    * and the display mode.
    *
    * Possible values are: "cell-immediate", "plmn", "location-area" and "cell".
    */
   readonly attribute DOMString gsmGeographicalScope;
 
   /**
new file mode 100644
--- /dev/null
+++ b/dom/cellbroadcast/tests/marionette/head.js
@@ -0,0 +1,229 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const {Cc: Cc, Ci: Ci, Cr: Cr, Cu: Cu} = SpecialPowers;
+
+let Promise = Cu.import("resource://gre/modules/Promise.jsm").Promise;
+
+/**
+ * Push required permissions and test if |navigator.mozCellBroadcast| exists.
+ * Resolve if it does, reject otherwise.
+ *
+ * Fulfill params:
+ *   cbManager -- an reference to navigator.mozCellBroadcast.
+ *
+ * Reject params: (none)
+ *
+ * @return A deferred promise.
+ */
+let cbManager;
+function ensureCellBroadcast() {
+  let deferred = Promise.defer();
+
+  let permissions = [{
+    "type": "cellbroadcast",
+    "allow": 1,
+    "context": document,
+  }];
+  SpecialPowers.pushPermissions(permissions, function() {
+    ok(true, "permissions pushed: " + JSON.stringify(permissions));
+
+    cbManager = window.navigator.mozCellBroadcast;
+    if (cbManager) {
+      log("navigator.mozCellBroadcast is instance of " + cbManager.constructor);
+    } else {
+      log("navigator.mozCellBroadcast is undefined.");
+    }
+
+    if (cbManager instanceof window.MozCellBroadcast) {
+      deferred.resolve(cbManager);
+    } else {
+      deferred.reject();
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Send emulator command with safe guard.
+ *
+ * We should only call |finish()| after all emulator command transactions
+ * end, so here comes with the pending counter.  Resolve when the emulator
+ * gives positive response, and reject otherwise.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ *
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+let pendingEmulatorCmdCount = 0;
+function runEmulatorCmdSafe(aCommand) {
+  let deferred = Promise.defer();
+
+  ++pendingEmulatorCmdCount;
+  runEmulatorCmd(aCommand, function(aResult) {
+    --pendingEmulatorCmdCount;
+
+    ok(true, "Emulator response: " + JSON.stringify(aResult));
+    if (Array.isArray(aResult) && aResult[aResult.length - 1] === "OK") {
+      deferred.resolve(aResult);
+    } else {
+      deferred.reject(aResult);
+    }
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Send raw CBS PDU to emulator.
+ *
+ * @param: aPdu
+ *         A hex string representing the whole CBS PDU.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ *
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+function sendRawCbsToEmulator(aPdu) {
+  let command = "cbs pdu " + aPdu;
+  return runEmulatorCmdSafe(command);
+}
+
+/**
+ * Wait for one named Cellbroadcast event.
+ *
+ * Resolve if that named event occurs.  Never reject.
+ *
+ * Fulfill params: the DOMEvent passed.
+ *
+ * @param aEventName
+ *        A string event name.
+ *
+ * @return A deferred promise.
+ */
+function waitForManagerEvent(aEventName) {
+  let deferred = Promise.defer();
+
+  cbManager.addEventListener(aEventName, function onevent(aEvent) {
+    cbManager.removeEventListener(aEventName, onevent);
+
+    ok(true, "Cellbroadcast event '" + aEventName + "' got.");
+    deferred.resolve(aEvent);
+  });
+
+  return deferred.promise;
+}
+
+/**
+ * Send multiple raw CB PDU to emulator and wait
+ *
+ * @param: aPdus
+ *         A array of hex strings. Each represents a CB PDU.
+ *         These PDUs are expected to be concatenated into single CB Message.
+ *
+ * Fulfill params:
+ *   result -- array of resolved Promise, where
+ *             result[0].message representing the received message.
+ *             result[1-n] represents the response of sent emulator command.
+ *
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+function sendMultipleRawCbsToEmulatorAndWait(aPdus) {
+  let promises = [];
+
+  promises.push(waitForManagerEvent("received"));
+  for (let pdu of aPdus) {
+    promises.push(sendRawCbsToEmulator(pdu));
+  }
+
+  return Promise.all(promises);
+}
+
+/**
+ * Flush permission settings and call |finish()|.
+ */
+function cleanUp() {
+  waitFor(function() {
+    SpecialPowers.flushPermissions(function() {
+      // Use ok here so that we have at least one test run.
+      ok(true, "permissions flushed");
+
+      finish();
+    });
+  }, function() {
+    return pendingEmulatorCmdCount === 0;
+  });
+}
+
+/**
+ * Switch modem for receving upcoming emulator commands.
+ *
+ * @param: aServiceId
+ *         The id of the modem to be switched to.
+ *
+ * Fulfill params:
+ *   result -- an array of emulator response lines.
+ *
+ * Reject params:
+ *   result -- an array of emulator response lines.
+ *
+ * @return A deferred promise.
+ */
+function selectModem(aServiceId) {
+  let command = "mux modem " + aServiceId;
+  return runEmulatorCmdSafe(command);
+}
+
+/**
+ * Helper to run the test case only needed in Multi-SIM environment.
+ *
+ * @param  aTest
+ *         A function which will be invoked w/o parameter.
+ * @return a Promise object.
+ */
+function runIfMultiSIM(aTest) {
+  let numRIL;
+  try {
+    numRIL = SpecialPowers.getIntPref("ril.numRadioInterfaces");
+  } catch (ex) {
+    numRIL = 1;  // Pref not set.
+  }
+
+  if (numRIL > 1) {
+    return aTest();
+  } else {
+    log("Not a Multi-SIM environment. Test is skipped.");
+    return Promise.resolve();
+  }
+}
+
+/**
+ * Common test routine helper for cell broadcast tests.
+ *
+ * This function ensures global |cbManager| variable is available during the
+ * process and performs clean-ups as well.
+ *
+ * @param aTestCaseMain
+ *        A function that takes no parameter.
+ */
+function startTestCommon(aTestCaseMain) {
+  Promise.resolve()
+         .then(ensureCellBroadcast)
+         .then(aTestCaseMain)
+         .then(cleanUp, function() {
+           ok(false, 'promise rejects during test.');
+           cleanUp();
+         });
+}
--- a/dom/cellbroadcast/tests/marionette/manifest.ini
+++ b/dom/cellbroadcast/tests/marionette/manifest.ini
@@ -1,7 +1,8 @@
 [DEFAULT]
 b2g = true
 browser = false
 qemu = true
 
 [test_cellbroadcast_etws.js]
 [test_cellbroadcast_gsm.js]
+[test_cellbroadcast_multi_sim.js]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/cellbroadcast/tests/marionette/test_cellbroadcast_multi_sim.js
@@ -0,0 +1,34 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+MARIONETTE_TIMEOUT = 60000;
+MARIONETTE_HEAD_JS = 'head.js';
+
+const BODY_7BITS = "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+                 + "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
+                 + "@@@@@@@@@@@@@"; // 93 ascii chars.
+const CB_PDU_SIZE = 88;
+
+function testReceivingMultiSIM() {
+  let CB_PDU = "";
+  while (CB_PDU.length < CB_PDU_SIZE * 2) {
+    CB_PDU += "00";
+  }
+
+  let verifyCBMessage = (aMessage, aServiceId) => {
+    log("Verify CB message received from serviceId: " + aServiceId);
+    is(aMessage.body, BODY_7BITS, "Checking message body.");
+    is(aMessage.serviceId, aServiceId, "Checking serviceId.");
+  };
+
+  return selectModem(1)
+    .then(() => sendMultipleRawCbsToEmulatorAndWait([CB_PDU]))
+    .then((results) => verifyCBMessage(results[0].message, 1))
+    .then(() => selectModem(0))
+    .then(() => sendMultipleRawCbsToEmulatorAndWait([CB_PDU]))
+    .then((results) => verifyCBMessage(results[0].message, 0));
+}
+
+startTestCommon(function testCaseMain() {
+  return runIfMultiSIM(testReceivingMultiSIM);
+});
--- a/dom/events/test/test_error_events.html
+++ b/dom/events/test/test_error_events.html
@@ -32,18 +32,18 @@
     [ "Event filename", errorEvent.filename, location.href ],
     [ "Callback filename", file, location.href ],
     [ "Event line number", errorEvent.lineno, 27 ],
     [ "Callback line number", line, 27 ],
     [ "Event message", errorEvent.message, "Error: hello" ],
     [ "Callback message", msg, "Error: hello" ],
     [ "Event error-object", errorEvent.error, thrown],
     [ "Callback error-object", error, thrown ],
-    [ "Event column", errorEvent.colno, 6 ], // Sadly not correct right now
-    [ "Callback column", column, 6 ]
+    [ "Event column", errorEvent.colno, 15 ],
+    [ "Callback column", column, 15 ]
   ]);
 </script>
 <script>
   var workerLocation = location.protocol + "//" + location.host +
     location.pathname.replace("test_error_events.html", "error_event_worker.js");
   var eventFileTest = async_test("Worker event filename");
   var eventLineTest = async_test("Worker event line number");
   var eventMessageTest = async_test("Worker event message");
--- a/dom/inputmethod/MozKeyboard.js
+++ b/dom/inputmethod/MozKeyboard.js
@@ -569,17 +569,17 @@ MozInputContext.prototype = {
 
   setComposition: function ic_setComposition(text, cursor, clauses) {
     let self = this;
     return this._sendPromise(function(resolverId) {
       cpmm.sendAsyncMessage('Keyboard:SetComposition', {
         contextId: self._contextId,
         requestId: resolverId,
         text: text,
-        cursor: cursor || text.length,
+        cursor: (typeof cursor !== 'undefined') ? cursor : text.length,
         clauses: clauses || null
       });
     });
   },
 
   endComposition: function ic_endComposition(text) {
     let self = this;
     return this._sendPromise(function(resolverId) {
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -344,16 +344,25 @@ MediaElementChecker.prototype = {
    */
   checkForNoMediaFlow : function MEC_CheckForNoMediaFlow() {
     ok(this.element.readyState === HTMLMediaElement.HAVE_METADATA,
        'Media element has a ready state of HAVE_METADATA');
   }
 };
 
 /**
+ * Only calls info() if SimpleTest.info() is available
+ */
+function safeInfo(message) {
+  if (typeof(info) === "function") {
+    info(message);
+  }
+}
+
+/**
  * Query function for determining if any IP address is available for
  * generating SDP.
  *
  * @return false if required additional network setup.
  */
 function isNetworkReady() {
   // for gonk platform
   if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
@@ -369,26 +378,26 @@ function isNetworkReady() {
       var ips = {};
       var prefixLengths = {};
       var length = itfList.getInterface(i).getAddresses(ips, prefixLengths);
 
       for (var j = 0; j < length; j++) {
         var ip = ips.value[j];
         // skip IPv6 address until bug 797262 is implemented
         if (ip.indexOf(":") < 0) {
-          info("Network interface is ready with address: " + ip);
+          safeInfo("Network interface is ready with address: " + ip);
           return true;
         }
       }
     }
     // ip address is not available
-    info("Network interface is not ready, required additional network setup");
+    safeInfo("Network interface is not ready, required additional network setup");
     return false;
   }
-  info("Network setup is not required");
+  safeInfo("Network setup is not required");
   return true;
 }
 
 /**
  * Network setup utils for Gonk
  *
  * @return {object} providing functions for setup/teardown data connection
  */
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -300,17 +300,18 @@ MobileCallForwardingInfo.prototype = {
   __exposedProps__ : {active: 'r',
                       action: 'r',
                       reason: 'r',
                       number: 'r',
                       timeSeconds: 'r',
                       serviceClass: 'r'}
 };
 
-function CellBroadcastMessage(pdu) {
+function CellBroadcastMessage(clientId, pdu) {
+  this.serviceId = clientId;
   this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
   this.messageCode = pdu.messageCode;
   this.messageId = pdu.messageId;
   this.language = pdu.language;
   this.body = pdu.fullBody;
   this.messageClass = pdu.messageClass;
   this.timestamp = pdu.timestamp;
 
@@ -326,16 +327,17 @@ CellBroadcastMessage.prototype = {
   classInfo:      XPCOMUtils.generateCI({
     classID:          CELLBROADCASTMESSAGE_CID,
     classDescription: "CellBroadcastMessage",
     flags:            Ci.nsIClassInfo.DOM_OBJECT,
     interfaces:       [Ci.nsIDOMMozCellBroadcastMessage]
   }),
 
   // nsIDOMMozCellBroadcastMessage
+  serviceId: -1,
 
   gsmGeographicalScope: null,
   messageCode: null,
   messageId: null,
   language: null,
   body: null,
   messageClass: null,
   timestamp: null,
@@ -1539,23 +1541,27 @@ RILContentHelper.prototype = {
     // To follow the listener unregistration scheme, we add a dummy clientId 0.
     // All voicemail events are routed to listener for client id 0.
     // See |handleVoicemailNotification|.
     this.unregisterListener("_voicemailListeners", 0, listener);
   },
 
   registerCellBroadcastMsg: function(listener) {
     if (DEBUG) debug("Registering for Cell Broadcast related messages");
-    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
+    // Instead of registering multiple listeners for Multi-SIM, we reuse
+    // clientId 0 to route all CBS messages to single listener and provide the
+    // |clientId| info by |CellBroadcastMessage.serviceId|.
     this.registerListener("_cellBroadcastListeners", 0, listener);
     cpmm.sendAsyncMessage("RIL:RegisterCellBroadcastMsg");
   },
 
   unregisterCellBroadcastMsg: function(listener) {
-    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
+    // Instead of unregistering multiple listeners for Multi-SIM, we reuse
+    // clientId 0 to route all CBS messages to single listener and provide the
+    // |clientId| info by |CellBroadcastMessage.serviceId|.
     this.unregisterListener("_cellBroadcastListeners", 0, listener);
   },
 
   registerIccMsg: function(clientId, listener) {
     if (DEBUG) debug("Registering for ICC related messages");
     this.registerListener("_iccListeners", clientId, listener);
     cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
   },
@@ -1819,18 +1825,20 @@ RILContentHelper.prototype = {
         break;
       case "RIL:GetCallingLineIdRestriction":
         this.handleGetCallingLineIdRestriction(data);
         break;
       case "RIL:SetCallingLineIdRestriction":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
       case "RIL:CellBroadcastReceived": {
-        let message = new CellBroadcastMessage(data);
-        this._deliverEvent(clientId,
+        // All CBS messages are to routed the listener for clientId 0 and
+        // provide the |clientId| info by |CellBroadcastMessage.serviceId|.
+        let message = new CellBroadcastMessage(clientId, data);
+        this._deliverEvent(0, // route to clientId 0.
                            "_cellBroadcastListeners",
                            "notifyMessageReceived",
                            [message]);
         break;
       }
       case "RIL:SetRoamingPreference":
         this.handleSimpleRequest(data.requestId, data.errorMsg, null);
         break;
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -66,25 +66,25 @@ const kSmsSentObserverTopic             
 const kSmsFailedObserverTopic            = "sms-failed";
 const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
 const kSmsDeliveryErrorObserverTopic     = "sms-delivery-error";
 const kMozSettingsChangedObserverTopic   = "mozsettings-changed";
 const kSysMsgListenerReadyObserverTopic  = "system-message-listener-ready";
 const kSysClockChangeObserverTopic       = "system-clock-change";
 const kScreenStateChangedTopic           = "screen-state-changed";
 
+const kSettingsCellBroadcastDisabled = "ril.cellbroadcast.disabled";
 const kSettingsCellBroadcastSearchList = "ril.cellbroadcast.searchlist";
 const kSettingsClockAutoUpdateEnabled = "time.clock.automatic-update.enabled";
 const kSettingsClockAutoUpdateAvailable = "time.clock.automatic-update.available";
 const kSettingsTimezoneAutoUpdateEnabled = "time.timezone.automatic-update.enabled";
 const kSettingsTimezoneAutoUpdateAvailable = "time.timezone.automatic-update.available";
 
 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
 
-const kPrefCellBroadcastDisabled = "ril.cellbroadcast.disabled";
 const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
 
 const DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED = "received";
 const DOM_MOBILE_MESSAGE_DELIVERY_SENDING  = "sending";
 const DOM_MOBILE_MESSAGE_DELIVERY_SENT     = "sent";
 const DOM_MOBILE_MESSAGE_DELIVERY_ERROR    = "error";
 
@@ -1586,17 +1586,16 @@ WorkerMessenger.prototype = {
   token: 1,
 
   // Maps tokens we send out with messages to the message callback.
   tokenCallbackMap: null,
 
   init: function() {
     let options = {
       debug: DEBUG,
-      cellBroadcastDisabled: false,
       quirks: {
         callstateExtraUint32:
           libcutils.property_get("ro.moz.ril.callstate_extra_int", "false") === "true",
         v5Legacy:
           libcutils.property_get("ro.moz.ril.v5_legacy", "true") === "true",
         requestUseDialEmergencyCall:
           libcutils.property_get("ro.moz.ril.dial_emergency_call", "false") === "true",
         simAppStateExtraFields:
@@ -1609,21 +1608,16 @@ WorkerMessenger.prototype = {
           libcutils.property_get("ro.moz.ril.send_stk_profile_dl", "false") == "true",
         dataRegistrationOnDemand: RILQUIRKS_DATA_REGISTRATION_ON_DEMAND,
         subscriptionControl: RILQUIRKS_SUBSCRIPTION_CONTROL
       },
       rilEmergencyNumbers: libcutils.property_get("ril.ecclist") ||
                            libcutils.property_get("ro.ril.ecclist")
     };
 
-    try {
-      options.cellBroadcastDisabled =
-        Services.prefs.getBoolPref(kPrefCellBroadcastDisabled);
-    } catch(e) {}
-
     this.send(null, "setInitialOptions", options);
   },
 
   setDebugFlag: function(aDebug) {
     let options = { debug: aDebug };
     this.send(null, "setDebugFlag", options);
   },
 
@@ -1810,27 +1804,48 @@ function RadioInterface(aClientId, aWork
   lock.get(kSettingsTimezoneAutoUpdateEnabled, this);
 
   // Set "time.clock.automatic-update.available" to false when starting up.
   this.setClockAutoUpdateAvailable(false);
 
   // Set "time.timezone.automatic-update.available" to false when starting up.
   this.setTimezoneAutoUpdateAvailable(false);
 
-  // Read the Cell Broadcast Search List setting, string of integers or integer
-  // ranges separated by comma, to set listening channels.
+  /**
+  * Read the settings of the toggle of Cellbroadcast Service:
+  *
+  * Simple Format: Boolean
+  *   true if CBS is disabled. The value is applied to all RadioInterfaces.
+  * Enhanced Format: Array of Boolean
+  *   Each element represents the toggle of CBS per RadioInterface.
+  */
+  lock.get(kSettingsCellBroadcastDisabled, this);
+
+  /**
+   * Read the Cell Broadcast Search List setting to set listening channels:
+   *
+   * Simple Format:
+   *   String of integers or integer ranges separated by comma.
+   *   For example, "1, 2, 4-6"
+   * Enhanced Format:
+   *   Array of Objects with search lists specified in gsm/cdma network.
+   *   For example, [{'gsm' : "1, 2, 4-6", 'cdma' : "1, 50, 99"},
+   *                 {'cdma' : "3, 6, 8-9"}]
+   *   This provides the possibility to
+   *   1. set gsm/cdma search list individually for CDMA+LTE device.
+   *   2. set search list per RadioInterface.
+   */
   lock.get(kSettingsCellBroadcastSearchList, this);
 
   Services.obs.addObserver(this, kMozSettingsChangedObserverTopic, false);
   Services.obs.addObserver(this, kSysClockChangeObserverTopic, false);
   Services.obs.addObserver(this, kScreenStateChangedTopic, false);
 
   Services.obs.addObserver(this, kNetworkConnStateChangedTopic, false);
   Services.obs.addObserver(this, kNetworkActiveChangedTopic, false);
-  Services.prefs.addObserver(kPrefCellBroadcastDisabled, this, false);
 
   this.portAddressedSmsApps = {};
   this.portAddressedSmsApps[WAP.WDP_PORT_PUSH] = this.handleSmsWdpPortPush.bind(this);
 
   this._receivedSmsSegmentsMap = {};
 
   this._sntp = new Sntp(this.setClockBySntp.bind(this),
                         Services.prefs.getIntPref("network.sntp.maxRetryCount"),
@@ -2488,33 +2503,40 @@ RadioInterface.prototype = {
       this._selectingNetwork = null;
       target.sendAsyncMessage("RIL:SelectNetworkAuto", {
         clientId: this.clientId,
         data: response
       });
     }).bind(this));
   },
 
-  setCellBroadcastSearchList: function(newSearchList) {
-    if ((newSearchList == this._cellBroadcastSearchList) ||
-          (newSearchList && this._cellBroadcastSearchList &&
-            newSearchList.gsm == this._cellBroadcastSearchList.gsm &&
-            newSearchList.cdma == this._cellBroadcastSearchList.cdma)) {
+  setCellBroadcastSearchList: function(settings) {
+    let newSearchList =
+      Array.isArray(settings) ? settings[this.clientId] : settings;
+    let oldSearchList =
+      Array.isArray(this._cellBroadcastSearchList) ?
+        this._cellBroadcastSearchList[this.clientId] :
+        this._cellBroadcastSearchList;
+
+    if ((newSearchList == oldSearchList) ||
+          (newSearchList && oldSearchList &&
+            newSearchList.gsm == oldSearchList.gsm &&
+            newSearchList.cdma == oldSearchList.cdma)) {
       return;
     }
 
     this.workerMessenger.send("setCellBroadcastSearchList",
                               { searchList: newSearchList },
                               (function callback(response) {
       if (!response.success) {
         let lock = gSettingsService.createLock();
         lock.set(kSettingsCellBroadcastSearchList,
                  this._cellBroadcastSearchList, null);
       } else {
-        this._cellBroadcastSearchList = response.searchList;
+        this._cellBroadcastSearchList = settings;
       }
 
       return false;
     }).bind(this));
   },
 
   /**
    * Handle signal strength changes.
@@ -3299,26 +3321,16 @@ RadioInterface.prototype = {
   // nsIObserver
 
   observe: function(subject, topic, data) {
     switch (topic) {
       case kMozSettingsChangedObserverTopic:
         let setting = JSON.parse(data);
         this.handleSettingsChange(setting.key, setting.value, setting.message);
         break;
-      case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
-        if (data === kPrefCellBroadcastDisabled) {
-          let value = false;
-          try {
-            value = Services.prefs.getBoolPref(kPrefCellBroadcastDisabled);
-          } catch(e) {}
-          this.workerMessenger.send("setCellBroadcastDisabled",
-                                    { disabled: value });
-        }
-        break;
       case kSysClockChangeObserverTopic:
         let offset = parseInt(data, 10);
         if (this._lastNitzMessage) {
           this._lastNitzMessage.receiveTimeInMS += offset;
         }
         this._sntp.updateOffset(offset);
         break;
       case kNetworkConnStateChangedTopic:
@@ -3470,19 +3482,29 @@ RadioInterface.prototype = {
           }
         }
         break;
       case kSettingsCellBroadcastSearchList:
         if (DEBUG) {
           this.debug("'" + kSettingsCellBroadcastSearchList +
             "' is now " + JSON.stringify(aResult));
         }
-        // TODO: Set searchlist for Multi-SIM. See Bug 921326.
-        let result = Array.isArray(aResult) ? aResult[0] : aResult;
-        this.setCellBroadcastSearchList(result);
+
+        this.setCellBroadcastSearchList(aResult);
+        break;
+      case kSettingsCellBroadcastDisabled:
+        if (DEBUG) {
+          this.debug("'" + kSettingsCellBroadcastDisabled +
+            "' is now " + JSON.stringify(aResult));
+        }
+
+        let setCbsDisabled =
+          Array.isArray(aResult) ? aResult[this.clientId] : aResult;
+        this.workerMessenger.send("setCellBroadcastDisabled",
+                                  { disabled: setCbsDisabled });
         break;
     }
   },
 
   handleError: function(aErrorMessage) {
     if (DEBUG) {
       this.debug("There was an error while reading RIL settings.");
     }
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -47,17 +47,16 @@ let GLOBAL = this;
 
 if (!this.debug) {
   // Debugging stub that goes nowhere.
   this.debug = function debug(message) {
     dump("RIL Worker: " + message + "\n");
   };
 }
 
-let RIL_CELLBROADCAST_DISABLED;
 let RIL_EMERGENCY_NUMBERS;
 const DEFAULT_EMERGENCY_NUMBERS = ["112", "911"];
 
 // Timeout value for emergency callback mode.
 const EMERGENCY_CB_MODE_TIMEOUT_MS = 300000;  // 5 mins = 300000 ms.
 
 const ICC_MAX_LINEAR_FIXED_RECORDS = 0xfe;
 
@@ -348,17 +347,16 @@ function RilObject(aContext) {
   this.currentDataCalls = {};
   this._pendingSentSmsMap = {};
   this.pendingNetworkType = {};
   this._receivedSmsCbPagesMap = {};
   this._getCurrentCallsRetryCount = 0;
 
   // Init properties that are only initialized once.
   this.v5Legacy = RILQUIRKS_V5_LEGACY;
-  this.cellBroadcastDisabled = RIL_CELLBROADCAST_DISABLED;
 
   this.pendingMO = null;
 }
 RilObject.prototype = {
   context: null,
 
   v5Legacy: null,
 
@@ -6445,17 +6443,21 @@ RilObject.prototype[REQUEST_CDMA_SMS_ACK
 RilObject.prototype[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
 RilObject.prototype[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
   if (options.rilRequestError == ERROR_SUCCESS) {
     this.setSmsBroadcastActivation(true);
   }
 };
 RilObject.prototype[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
 RilObject.prototype[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
-RilObject.prototype[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = null;
+RilObject.prototype[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = function REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG(length, options) {
+  if (options.rilRequestError == ERROR_SUCCESS) {
+    this.setSmsBroadcastActivation(true);
+  }
+};
 RilObject.prototype[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
 RilObject.prototype[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let result = this.context.Buf.readStringList();
 
@@ -13929,18 +13931,18 @@ ICCUtilsHelperObject.prototype = {
               break;
             }
           }
           iccInfo.isDisplaySpnRequired = inHomeArea;
         }
       }
     } else {
       // GSM family display rule.
-      let operatorMnc = RIL.operator.mnc;
-      let operatorMcc = RIL.operator.mcc;
+      let operatorMnc = RIL.operator ? RIL.operator.mnc : -1;
+      let operatorMcc = RIL.operator ? RIL.operator.mcc : -1;
 
       // First detect if we are on HPLMN or one of the PLMN
       // specified by the SIM card.
       let isOnMatchingPlmn = false;
 
       // If the current network is the one defined as mcc/mnc
       // in SIM card, it's okay.
       if (iccInfo.mcc == operatorMcc && iccInfo.mnc == operatorMnc) {
@@ -14895,17 +14897,16 @@ let ContextPool = {
       return;
     }
     method.call(this, aMessage);
   },
 
   setInitialOptions: function(aOptions) {
     DEBUG = DEBUG_WORKER || aOptions.debug;
     RIL_EMERGENCY_NUMBERS = aOptions.rilEmergencyNumbers;
-    RIL_CELLBROADCAST_DISABLED = aOptions.cellBroadcastDisabled;
 
     let quirks = aOptions.quirks;
     RILQUIRKS_CALLSTATE_EXTRA_UINT32 = quirks.callstateExtraUint32;
     RILQUIRKS_V5_LEGACY = quirks.v5Legacy;
     RILQUIRKS_REQUEST_USE_DIAL_EMERGENCY_CALL = quirks.requestUseDialEmergencyCall;
     RILQUIRKS_SIM_APP_STATE_EXTRA_FIELDS = quirks.simAppStateExtraFields;
     RILQUIRKS_EXTRA_UINT32_2ND_CALL = quirks.extraUint2ndCall;
     RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
--- a/dom/system/gonk/tests/header_helpers.js
+++ b/dom/system/gonk/tests/header_helpers.js
@@ -74,16 +74,70 @@ function newWorker(custom_ns) {
 
   // Register at least one client.
   worker_ns.ContextPool.registerClient({ clientId: 0 });
 
   return worker_ns;
 }
 
 /**
+ * Create a buffered RIL worker.
+ *
+ * @return A worker object that stores sending octets in a internal buffer.
+ */
+function newUint8Worker() {
+  let worker = newWorker();
+  let index = 0; // index for read
+  let buf = [];
+
+  let context = worker.ContextPool._contexts[0];
+  context.Buf.writeUint8 = function(value) {
+    buf.push(value);
+  };
+
+  context.Buf.readUint8 = function() {
+    return buf[index++];
+  };
+
+  context.Buf.seekIncoming = function(offset) {
+    index += offset;
+  };
+
+  context.Buf.getReadAvailable = function() {
+    return buf.length - index;
+  };
+
+  worker.debug = do_print;
+
+  return worker;
+}
+
+/**
+ * Create a worker that keeps posted chrome message.
+ */
+function newInterceptWorker() {
+  let postedMessage;
+  let worker = newWorker({
+    postRILMessage: function(data) {
+    },
+    postMessage: function(message) {
+      postedMessage = message;
+    }
+  });
+  return {
+    get postedMessage() {
+      return postedMessage;
+    },
+    get worker() {
+      return worker;
+    }
+  };
+}
+
+/**
  * Create a parcel suitable for postRILMessage().
  *
  * @param fakeParcelSize
  *        Value to be written to parcel size field for testing
  *        incorrect/incomplete parcel reading. Replaced with correct
  *        one determined length of data if negative.
  * @param response
  *        Response code of the incoming parcel.
--- a/dom/system/gonk/tests/test_ril_worker_barring_password.js
+++ b/dom/system/gonk/tests/test_ril_worker_barring_password.js
@@ -5,42 +5,16 @@ subscriptLoader.loadSubScript("resource:
 
 function run_test() {
   run_next_test();
 }
 
 const PIN = "0000";
 const NEW_PIN = "1234";
 
-/**
- * Helper function.
- */
-function newUint8Worker() {
-  let worker = newWorker();
-  let context = worker.ContextPool._contexts[0];
-  let index = 0; // index for read
-  let buf = [];
-
-  context.Buf.writeUint8 = function(value) {
-    buf.push(value);
-  };
-
-  context.Buf.readUint8 = function() {
-    return buf[index++];
-  };
-
-  context.Buf.seekIncoming = function(offset) {
-    index += offset;
-  };
-
-  worker.debug = do_print;
-
-  return worker;
-}
-
 add_test(function test_change_call_barring_password() {
   let worker = newUint8Worker();
   let context = worker.ContextPool._contexts[0];
   let buf = context.Buf;
 
   function do_test(facility, pin, newPin) {
     buf.sendParcel = function fakeSendParcel () {
       // Request Type.
--- a/dom/system/gonk/tests/test_ril_worker_cf.js
+++ b/dom/system/gonk/tests/test_ril_worker_cf.js
@@ -47,37 +47,18 @@ add_test(function test_toaFromString_unk
 add_test(function test_toaFromString_international() {
   let retval = toaFromString("+34666222333");
 
   do_check_eq(retval, TOA_INTERNATIONAL);
 
   run_next_test();
 });
 
-function _getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    }
-  });
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 add_test(function test_setCallForward_unconditional() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCallForward = function fakeSetCallForward(options) {
     context.RIL[REQUEST_SET_CALL_FORWARD](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
@@ -94,17 +75,17 @@ add_test(function test_setCallForward_un
 
   do_check_eq(postedMessage.errorMsg, GECKO_ERROR_SUCCESS);
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_queryCallForwardStatus_unconditional() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCallForward = function fakeSetCallForward(options) {
     context.RIL[REQUEST_SET_CALL_FORWARD](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
--- a/dom/system/gonk/tests/test_ril_worker_clip.js
+++ b/dom/system/gonk/tests/test_ril_worker_clip.js
@@ -2,37 +2,18 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
 
 function run_test() {
   run_next_test();
 }
 
-function _getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    }
-  });
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 add_test(function test_queryCLIP_provisioned() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.queryCLIP = function fakeQueryCLIP(options) {
@@ -51,17 +32,17 @@ add_test(function test_queryCLIP_provisi
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.provisioned, 1);
   run_next_test();
 });
 
 add_test(function test_getCLIP_error_generic_failure_invalid_length() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.queryCLIP = function fakeQueryCLIP(options) {
--- a/dom/system/gonk/tests/test_ril_worker_clir.js
+++ b/dom/system/gonk/tests/test_ril_worker_clir.js
@@ -11,37 +11,18 @@ const CLIR_DEFAULT     = 0;
 const CLIR_INVOCATION  = 1;
 // Allows CLI presentation.
 const CLIR_SUPPRESSION = 2;
 
 function run_test() {
   run_next_test();
 }
 
-function _getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    }
-  });
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 add_test(function test_setCLIR_success() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCLIR = function fakeSetCLIR(options) {
     context.RIL[REQUEST_SET_CLIR](0, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_SUCCESS
     });
@@ -55,17 +36,17 @@ add_test(function test_setCLIR_success()
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_setCLIR_generic_failure() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCLIR = function fakeSetCLIR(options) {
     context.RIL[REQUEST_SET_CLIR](0, {
       rilMessageType: "setCLIR",
       rilRequestError: ERROR_GENERIC_FAILURE
     });
@@ -79,17 +60,17 @@ add_test(function test_setCLIR_generic_f
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_getCLIR_n0_m1() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.getCLIR = function fakeGetCLIR(options) {
@@ -112,17 +93,17 @@ add_test(function test_getCLIR_n0_m1() {
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.n, 0);
   do_check_eq(postedMessage.m, 1);
   run_next_test();
 });
 
 add_test(function test_getCLIR_error_generic_failure_invalid_length() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.getCLIR = function fakeGetCLIR(options) {
--- a/dom/system/gonk/tests/test_ril_worker_cw.js
+++ b/dom/system/gonk/tests/test_ril_worker_cw.js
@@ -2,37 +2,18 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
 
 function run_test() {
   run_next_test();
 }
 
-function _getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    }
-  });
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 add_test(function test_setCallWaiting_success() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
     context.RIL[REQUEST_SET_CALL_WAITING](0, {
       rilRequestError: ERROR_SUCCESS
     });
   };
@@ -45,17 +26,17 @@ add_test(function test_setCallWaiting_su
 
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_setCallWaiting_generic_failure() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL.setCallWaiting = function fakeSetCallWaiting(options) {
     context.RIL[REQUEST_SET_CALL_WAITING](0, {
       rilRequestError: ERROR_GENERIC_FAILURE
     });
   };
@@ -68,17 +49,17 @@ add_test(function test_setCallWaiting_ge
 
   do_check_eq(postedMessage.errorMsg, "GenericFailure");
   do_check_false(postedMessage.success);
 
   run_next_test();
 });
 
 add_test(function test_queryCallWaiting_success_enabled_true() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
@@ -99,17 +80,17 @@ add_test(function test_queryCallWaiting_
   do_check_eq(postedMessage.errorMsg, undefined);
   do_check_true(postedMessage.success);
   do_check_eq(postedMessage.length, 1);
   do_check_true(postedMessage.enabled);
   run_next_test();
 });
 
 add_test(function test_queryCallWaiting_success_enabled_false() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.Buf.readInt32 = function fakeReadUint32() {
     return context.Buf.int32Array.pop();
   };
 
   context.RIL.queryCallWaiting = function fakeQueryCallWaiting(options) {
--- a/dom/system/gonk/tests/test_ril_worker_ecm.js
+++ b/dom/system/gonk/tests/test_ril_worker_ecm.js
@@ -2,35 +2,16 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
 
 function run_test() {
   run_next_test();
 }
 
-function _getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    }
-  });
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 var timeoutCallback = null;
 var timeoutDelayMs = 0;
 const TIMER_ID = 1234;
 const TIMEOUT_VALUE = 300000;  // 5 mins.
 
 // No window in xpcshell-test. Create our own timer mechanism.
 
 function setTimeout(callback, timeoutMs) {
@@ -49,17 +30,17 @@ function fireTimeout() {
   do_check_neq(timeoutCallback, null);
   if (timeoutCallback) {
     timeoutCallback();
     timeoutCallback = null;
   }
 }
 
 add_test(function test_enter_emergencyCbMode() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   // Do it twice. Should always send the event.
   for (let i = 0; i < 2; ++i) {
     context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
     let postedMessage = workerHelper.postedMessage;
 
@@ -74,17 +55,17 @@ add_test(function test_enter_emergencyCb
     // Should start timer.
     do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
   }
 
   run_next_test();
 });
 
 add_test(function test_exit_emergencyCbMode() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
   context.RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE]();
   let postedMessage = workerHelper.postedMessage;
 
   // Should store the mode.
@@ -96,17 +77,17 @@ add_test(function test_exit_emergencyCbM
 
   // Should clear timer.
   do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, null);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_when_timeout() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
   do_check_eq(context.RIL._isInEmergencyCbMode, true);
   do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
@@ -122,17 +103,17 @@ add_test(function test_request_exit_emer
 
   // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
   do_check_neq(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_when_dial() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
   do_check_eq(context.RIL._isInEmergencyCbMode, true);
   do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
@@ -149,17 +130,17 @@ add_test(function test_request_exit_emer
 
   // Check indeed sent out REQUEST_EXIT_EMERGENCY_CALLBACK_MODE.
   do_check_neq(parcelTypes.indexOf(REQUEST_EXIT_EMERGENCY_CALLBACK_MODE), -1);
 
   run_next_test();
 });
 
 add_test(function test_request_exit_emergencyCbMode_explicitly() {
-  let workerHelper = _getWorker();
+  let workerHelper = newInterceptWorker();
   let worker = workerHelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   context.RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE]();
   do_check_eq(context.RIL._isInEmergencyCbMode, true);
   do_check_eq(context.RIL._exitEmergencyCbModeTimeoutID, TIMER_ID);
 
   let parcelTypes = [];
deleted file mode 100644
--- a/dom/system/gonk/tests/test_ril_worker_icc.js
+++ /dev/null
@@ -1,3198 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
-
-function run_test() {
-  run_next_test();
-}
-
-/**
- * Helper function.
- */
-function newUint8Worker() {
-  let worker = newWorker();
-  let index = 0; // index for read
-  let buf = [];
-
-  let context = worker.ContextPool._contexts[0];
-  context.Buf.writeUint8 = function(value) {
-    buf.push(value);
-  };
-
-  context.Buf.readUint8 = function() {
-    return buf[index++];
-  };
-
-  context.Buf.seekIncoming = function(offset) {
-    index += offset;
-  };
-
-  context.Buf.getReadAvailable = function() {
-    return buf.length - index;
-  };
-
-  worker.debug = do_print;
-
-  return worker;
-}
-
-/**
- * Verify ICCPDUHelper#readICCUCS2String()
- */
-add_test(function test_read_icc_ucs2_string() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-
-  // 0x80
-  let text = "TEST";
-  helper.writeUCS2String(text);
-  // Also write two unused octets.
-  let ffLen = 2;
-  for (let i = 0; i < ffLen; i++) {
-    helper.writeHexOctet(0xff);
-  }
-  do_check_eq(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
-
-  // 0x81
-  let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
-               0xff, 0xff];
-  let len = array.length;
-  for (let i = 0; i < len; i++) {
-    helper.writeHexOctet(array[i]);
-  }
-  do_check_eq(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
-
-  // 0x82
-  let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
-                0xca, 0xff, 0xff];
-  let len2 = array2.length;
-  for (let i = 0; i < len2; i++) {
-    helper.writeHexOctet(array2[i]);
-  }
-  do_check_eq(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#readDiallingNumber
- */
-add_test(function test_read_dialling_number() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  let str = "123456789";
-
-  helper.readHexOctet = function() {
-    return 0x81;
-  };
-
-  helper.readSwappedNibbleBcdString = function(len) {
-    return str.substring(0, len);
-  };
-
-  for (let i = 0; i < str.length; i++) {
-    do_check_eq(str.substring(0, i - 1), // -1 for the TON
-                iccHelper.readDiallingNumber(i));
-  }
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#read8BitUnpackedToString
- */
-add_test(function test_read_8bit_unpacked_to_string() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
-  // Test 1: Read GSM alphabets.
-  // Write alphabets before ESCAPE.
-  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
-    helper.writeHexOctet(i);
-  }
-
-  // Write two ESCAPEs to make it become ' '.
-  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
-  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
-
-  for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
-    helper.writeHexOctet(i);
-  }
-
-  // Also write two unused fields.
-  let ffLen = 2;
-  for (let i = 0; i < ffLen; i++) {
-    helper.writeHexOctet(0xff);
-  }
-
-  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
-              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
-  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
-  do_check_eq(iccHelper.read8BitUnpackedToString(langTable.length -
-                                              PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
-              langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
-  // Test 2: Read GSM extended alphabets.
-  for (let i = 0; i < langShiftTable.length; i++) {
-    helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
-    helper.writeHexOctet(i);
-  }
-
-  // Read string before RESERVED_CONTROL.
-  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL  * 2),
-              langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
-  // ESCAPE + RESERVED_CONTROL will become ' '.
-  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
-  // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
-  do_check_eq(iccHelper.read8BitUnpackedToString(
-                (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1)  * 2),
-              langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
-                                       PDU_NL_EXTENDED_ESCAPE));
-  // ESCAPE + ESCAPE will become ' '.
-  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
-  // Read remaining string.
-  do_check_eq(iccHelper.read8BitUnpackedToString(
-                (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1)  * 2),
-              langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
- *
- * Test writing GSM 8 bit alphabets.
- */
-add_test(function test_write_string_to_8bit_unpacked() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  // Length of trailing 0xff.
-  let ffLen = 2;
-  let str;
-
-  // Test 1, write GSM alphabets.
-  iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
-
-  for (let i = 0; i < langTable.length; i++) {
-    do_check_eq(helper.readHexOctet(), i);
-  }
-
-  for (let i = 0; i < ffLen; i++) {
-    do_check_eq(helper.readHexOctet(), 0xff);
-  }
-
-  // Test 2, write GSM extended alphabets.
-  str = "\u000c\u20ac";
-  iccHelper.writeStringTo8BitUnpacked(4, str);
-
-  do_check_eq(iccHelper.read8BitUnpackedToString(4), str);
-
-  // Test 3, write GSM and GSM extended alphabets.
-  // \u000c, \u20ac are from gsm extended alphabets.
-  // \u00a3 is from gsm alphabet.
-  str = "\u000c\u20ac\u00a3";
-
-  // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
-  // 1 octet for 1 gsm alphabet,
-  // 2 octes for trailing 0xff.
-  // "Totally 7 octets are to be written."
-  iccHelper.writeStringTo8BitUnpacked(7, str);
-
-  do_check_eq(iccHelper.read8BitUnpackedToString(7), str);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
- */
-add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
-  // The maximum of the number of octets that can be written is 3.
-  // Only 3 characters shall be written even the length of the string is 4.
-  iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
-  helper.writeHexOctet(0xff); // dummy octet.
-  for (let i = 0; i < 3; i++) {
-    do_check_eq(helper.readHexOctet(), i);
-  }
-  do_check_false(helper.readHexOctet() == 4);
-
-  // \u000c is GSM extended alphabet, 2 octets.
-  // \u00a3 is GSM alphabet, 1 octet.
-  let str = "\u000c\u00a3";
-  iccHelper.writeStringTo8BitUnpacked(3, str);
-  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
-
-  str = "\u00a3\u000c";
-  iccHelper.writeStringTo8BitUnpacked(3, str);
-  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
-
-  // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
-  // alphabet can be written.
-  str = "\u000c\u000c";
-  iccHelper.writeStringTo8BitUnpacked(3, str);
-  helper.writeHexOctet(0xff); // dummy octet.
-  do_check_eq(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdentifier
- */
-add_test(function test_read_alpha_identifier() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-
-  // UCS2: 0x80
-  let text = "TEST";
-  helper.writeHexOctet(0x80);
-  helper.writeUCS2String(text);
-  // Also write two unused octets.
-  let ffLen = 2;
-  for (let i = 0; i < ffLen; i++) {
-    helper.writeHexOctet(0xff);
-  }
-  do_check_eq(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
-
-  // UCS2: 0x81
-  let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
-  for (let i = 0; i < array.length; i++) {
-    helper.writeHexOctet(array[i]);
-  }
-  do_check_eq(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
-
-  // UCS2: 0x82
-  let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
-  for (let i = 0; i < array2.length; i++) {
-    helper.writeHexOctet(array2[i]);
-  }
-  do_check_eq(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
-
-  // GSM 8 Bit Unpacked
-  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
-    helper.writeHexOctet(i);
-  }
-  do_check_eq(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
-              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdentifier
- */
-add_test(function test_write_alpha_identifier() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  // Length of trailing 0xff.
-  let ffLen = 2;
-
-  // Removal
-  iccHelper.writeAlphaIdentifier(10, null);
-  do_check_eq(iccHelper.readAlphaIdentifier(10), "");
-
-  // GSM 8 bit
-  let str = "Mozilla";
-  iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
-  do_check_eq(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
-
-  // UCS2
-  str = "Mozilla\u694a";
-  iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
-  // * 2 for each character will be encoded to UCS2 alphabets.
-  do_check_eq(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
-
-  // Test with maximum octets written.
-  // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
-  str = "\u694a";
-  iccHelper.writeAlphaIdentifier(3, str);
-  do_check_eq(iccHelper.readAlphaIdentifier(3), str);
-
-  // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
-  // numOctets is limited to 4, so only 1 UCS2 character can be written.
-  str = "\u694a\u694a";
-  iccHelper.writeAlphaIdentifier(4, str);
-  helper.writeHexOctet(0xff); // dummy octet.
-  do_check_eq(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
-
-  // Write 0 octet.
-  iccHelper.writeAlphaIdentifier(0, "1");
-  helper.writeHexOctet(0xff); // dummy octet.
-  do_check_eq(iccHelper.readAlphaIdentifier(1), "");
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readAlphaIdDiallingNumber
- */
-add_test(function test_read_alpha_id_dialling_number() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  let buf = context.Buf;
-  const recordSize = 32;
-
-  function testReadAlphaIdDiallingNumber(contact) {
-    iccHelper.readAlphaIdentifier = function() {
-      return contact.alphaId;
-    };
-
-    iccHelper.readNumberWithLength = function() {
-      return contact.number;
-    };
-
-    let strLen = recordSize * 2;
-    buf.writeInt32(strLen);     // fake length
-    helper.writeHexOctet(0xff); // fake CCP
-    helper.writeHexOctet(0xff); // fake EXT1
-    buf.writeStringDelimiter(strLen);
-
-    let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
-    if (contact.alphaId == "" && contact.number == "") {
-      do_check_eq(contactR, null);
-    } else {
-      do_check_eq(contactR.alphaId, contact.alphaId);
-      do_check_eq(contactR.number, contact.number);
-    }
-  }
-
-  testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
-  testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
- */
-add_test(function test_write_alpha_id_dialling_number() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.ICCPDUHelper;
-  const recordSize = 32;
-
-  // Write a normal contact.
-  let contactW = {
-    alphaId: "Mozilla",
-    number: "1234567890"
-  };
-  helper.writeAlphaIdDiallingNumber(recordSize, contactW.alphaId,
-                                    contactW.number);
-
-  let contactR = helper.readAlphaIdDiallingNumber(recordSize);
-  do_check_eq(contactW.alphaId, contactR.alphaId);
-  do_check_eq(contactW.number, contactR.number);
-
-  // Write a contact with alphaId encoded in UCS2 and number has '+'.
-  let contactUCS2 = {
-    alphaId: "火狐",
-    number: "+1234567890"
-  };
-  helper.writeAlphaIdDiallingNumber(recordSize, contactUCS2.alphaId,
-                                    contactUCS2.number);
-  contactR = helper.readAlphaIdDiallingNumber(recordSize);
-  do_check_eq(contactUCS2.alphaId, contactR.alphaId);
-  do_check_eq(contactUCS2.number, contactR.number);
-
-  // Write a null contact (Removal).
-  helper.writeAlphaIdDiallingNumber(recordSize);
-  contactR = helper.readAlphaIdDiallingNumber(recordSize);
-  do_check_eq(contactR, null);
-
-  // Write a longer alphaId/dialling number
-  // Dialling Number : Maximum 20 digits(10 octets).
-  // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
-  //                   octet for TON/NPI, 1 for number length octet, and 2 for
-  //                   Ext) = Maximum 18 octets.
-  let longContact = {
-    alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
-    number: "123456789012345678901234567890",
-  };
-  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
-                                    longContact.number);
-  contactR = helper.readAlphaIdDiallingNumber(recordSize);
-  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
-  do_check_eq(contactR.number, "12345678901234567890");
-
-  // Add '+' to number and test again.
-  longContact.number = "+123456789012345678901234567890";
-  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
-                                    longContact.number);
-  contactR = helper.readAlphaIdDiallingNumber(recordSize);
-  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
-  do_check_eq(contactR.number, "+12345678901234567890");
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeDiallingNumber
- */
-add_test(function test_write_dialling_number() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.ICCPDUHelper;
-
-  // with +
-  let number = "+123456";
-  let len = 4;
-  helper.writeDiallingNumber(number);
-  do_check_eq(helper.readDiallingNumber(len), number);
-
-  // without +
-  number = "987654";
-  len = 4;
-  helper.writeDiallingNumber(number);
-  do_check_eq(helper.readDiallingNumber(len), number);
-
-  number = "9876543";
-  len = 5;
-  helper.writeDiallingNumber(number);
-  do_check_eq(helper.readDiallingNumber(len), number);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.readNumberWithLength
- */
-add_test(function test_read_number_with_length() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  let number = "123456789";
-
-  iccHelper.readDiallingNumber = function(numLen) {
-    return number.substring(0, numLen);
-  };
-
-  helper.writeHexOctet(number.length + 1);
-  helper.writeHexOctet(PDU_TOA_ISDN);
-  do_check_eq(iccHelper.readNumberWithLength(), number);
-
-  helper.writeHexOctet(0xff);
-  do_check_eq(iccHelper.readNumberWithLength(), null);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCPDUHelper.writeNumberWithLength
- */
-add_test(function test_write_number_with_length() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-
-  function test(number, expectedNumber) {
-    expectedNumber = expectedNumber || number;
-    iccHelper.writeNumberWithLength(number);
-    let numLen = helper.readHexOctet();
-    do_check_eq(expectedNumber, iccHelper.readDiallingNumber(numLen));
-    for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
-      do_check_eq(0xff, helper.readHexOctet());
-    }
-  }
-
-  // without +
-  test("123456789");
-
-  // with +
-  test("+987654321");
-
-  // extended BCD coding
-  test("1*2#3,4*5#6,");
-
-  // with + and extended BCD coding
-  test("+1*2#3,4*5#6,");
-
-  // non-supported characters should not be written.
-  test("(1)23-456+789", "123456789");
-
-  test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
-
-  // null
-  iccHelper.writeNumberWithLength(null);
-  for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
-    do_check_eq(0xff, helper.readHexOctet());
-  }
-
-  run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper.writeTimestamp
- */
-add_test(function test_write_timestamp() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-
-  // current date
-  let dateInput = new Date();
-  let dateOutput = new Date();
-  helper.writeTimestamp(dateInput);
-  dateOutput.setTime(helper.readTimestamp());
-
-  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
-  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
-  do_check_eq(dateInput.getDate(), dateOutput.getDate());
-  do_check_eq(dateInput.getHours(), dateOutput.getHours());
-  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
-  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
-  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
-  // 2034-01-23 12:34:56 -0800 GMT
-  let time = Date.UTC(2034, 1, 23, 12, 34, 56);
-  time = time - (8 * 60 * 60 * 1000);
-  dateInput.setTime(time);
-  helper.writeTimestamp(dateInput);
-  dateOutput.setTime(helper.readTimestamp());
-
-  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
-  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
-  do_check_eq(dateInput.getDate(), dateOutput.getDate());
-  do_check_eq(dateInput.getHours(), dateOutput.getHours());
-  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
-  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
-  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
-
-  run_next_test();
-});
-
-/**
- * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
- */
-add_test(function test_octect_BCD() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-
-  // 23
-  let number = 23;
-  let octet = helper.BCDToOctet(number);
-  do_check_eq(helper.octetToBCD(octet), number);
-
-  // 56
-  number = 56;
-  octet = helper.BCDToOctet(number);
-  do_check_eq(helper.octetToBCD(octet), number);
-
-  // 0x23
-  octet = 0x23;
-  number = helper.octetToBCD(octet);
-  do_check_eq(helper.BCDToOctet(number), octet);
-
-  // 0x56
-  octet = 0x56;
-  number = helper.octetToBCD(octet);
-  do_check_eq(helper.BCDToOctet(number), octet);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isICCServiceAvailable.
- */
-add_test(function test_is_icc_service_available() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ICCUtilsHelper = context.ICCUtilsHelper;
-  let RIL = context.RIL;
-
-  function test_table(sst, geckoService, simEnabled, usimEnabled) {
-    RIL.iccInfoPrivate.sst = sst;
-    RIL.appType = CARD_APPTYPE_SIM;
-    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
-    RIL.appType = CARD_APPTYPE_USIM;
-    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
-  }
-
-  test_table([0x08], "ADN", true, false);
-  test_table([0x08], "FDN", false, false);
-  test_table([0x08], "SDN", false, true);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.isGsm8BitAlphabet
- */
-add_test(function test_is_gsm_8bit_alphabet() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ICCUtilsHelper = context.ICCUtilsHelper;
-  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
-
-  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
-  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
-  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
-
-  run_next_test();
-});
-
-/**
- * Verify RIL.iccGetCardLockState("fdn")
- */
-add_test(function test_icc_get_card_lock_state_fdn() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-  let buf = context.Buf;
-
-  buf.sendParcel = function() {
-    // Request Type.
-    do_check_eq(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
-
-    // Token : we don't care.
-    this.readInt32();
-
-    // String Array Length.
-    do_check_eq(this.readInt32(), ril.v5Legacy ? 3 : 4);
-
-    // Facility.
-    do_check_eq(this.readString(), ICC_CB_FACILITY_FDN);
-
-    // Password.
-    do_check_eq(this.readString(), "");
-
-    // Service class.
-    do_check_eq(this.readString(), (ICC_SERVICE_CLASS_VOICE |
-                                    ICC_SERVICE_CLASS_DATA  |
-                                    ICC_SERVICE_CLASS_FAX).toString());
-
-    if (!ril.v5Legacy) {
-      // AID. Ignore because it's from modem.
-      this.readInt32();
-    }
-
-    run_next_test();
-  };
-
-  ril.iccGetCardLockState({lockType: "fdn"});
-});
-
-add_test(function test_get_network_name_from_icc() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let RIL = context.RIL;
-  let ICCUtilsHelper = context.ICCUtilsHelper;
-
-  function testGetNetworkNameFromICC(operatorData, expectedResult) {
-    let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
-                                                      operatorData.mnc,
-                                                      operatorData.lac);
-
-    if (expectedResult == null) {
-      do_check_eq(result, expectedResult);
-    } else {
-      do_check_eq(result.fullName, expectedResult.longName);
-      do_check_eq(result.shortName, expectedResult.shortName);
-    }
-  }
-
-  // Before EF_OPL and EF_PNN have been loaded.
-  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, null);
-  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x2000}, null);
-
-  // Set HPLMN
-  RIL.iccInfo.mcc = 123;
-  RIL.iccInfo.mnc = 456;
-
-  RIL.voiceRegistrationState = {
-    cell: {
-      gsmLocationAreaCode: 0x1000
-    }
-  };
-  RIL.operator = {};
-
-  // Set EF_PNN
-  RIL.iccInfoPrivate = {
-    PNN: [
-      {"fullName": "PNN1Long", "shortName": "PNN1Short"},
-      {"fullName": "PNN2Long", "shortName": "PNN2Short"},
-      {"fullName": "PNN3Long", "shortName": "PNN3Short"},
-      {"fullName": "PNN4Long", "shortName": "PNN4Short"}
-    ]
-  };
-
-  // EF_OPL isn't available and current isn't in HPLMN,
-  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, null);
-
-  // EF_OPL isn't available and current is in HPLMN,
-  // the first record of PNN should be returned.
-  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
-                            {longName: "PNN1Long", shortName: "PNN1Short"});
-
-  // Set EF_OPL
-  RIL.iccInfoPrivate.OPL = [
-    {
-      "mcc": 123,
-      "mnc": 456,
-      "lacTacStart": 0,
-      "lacTacEnd": 0xFFFE,
-      "pnnRecordId": 4
-    },
-    {
-      "mcc": 321,
-      "mnc": 654,
-      "lacTacStart": 0,
-      "lacTacEnd": 0x0010,
-      "pnnRecordId": 3
-    },
-    {
-      "mcc": 321,
-      "mnc": 654,
-      "lacTacStart": 0x0100,
-      "lacTacEnd": 0x1010,
-      "pnnRecordId": 2
-    }
-  ];
-
-  // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
-  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
-                            {longName: "PNN4Long", shortName: "PNN4Short"});
-
-  // Current PLMN is not HPLMN, and according to LAC, we should get
-  // the second PNN record.
-  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000},
-                            {longName: "PNN2Long", shortName: "PNN2Short"});
-
-  // Current PLMN is not HPLMN, and according to LAC, we should get
-  // the thrid PNN record.
-  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x0001},
-                            {longName: "PNN3Long", shortName: "PNN3Short"});
-
-  run_next_test();
-});
-
-add_test(function test_path_id_for_spid_and_spn() {
-  let worker = newWorker({
-    postRILMessage: function(data) {
-      // Do nothing
-    },
-    postMessage: function(message) {
-      // Do nothing
-    }});
-  let context = worker.ContextPool._contexts[0];
-  let RIL = context.RIL;
-  let ICCFileHelper = context.ICCFileHelper;
-
-  // Test SIM
-  RIL.appType = CARD_APPTYPE_SIM;
-  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
-              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
-  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPN),
-              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
-
-  // Test USIM
-  RIL.appType = CARD_APPTYPE_USIM;
-  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
-              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
-  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
-              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
-  run_next_test();
-});
-
-/**
- * Verify ICCUtilsHelper.parsePbrTlvs
- */
-add_test(function test_parse_pbr_tlvs() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let buf = context.Buf;
-
-  let pbrTlvs = [
-    {tag: ICC_USIM_TYPE1_TAG,
-     length: 0x0F,
-     value: [{tag: ICC_USIM_EFADN_TAG,
-              length: 0x03,
-              value: [0x4F, 0x3A, 0x02]},
-             {tag: ICC_USIM_EFIAP_TAG,
-              length: 0x03,
-              value: [0x4F, 0x25, 0x01]},
-             {tag: ICC_USIM_EFPBC_TAG,
-              length: 0x03,
-              value: [0x4F, 0x09, 0x04]}]
-    },
-    {tag: ICC_USIM_TYPE2_TAG,
-     length: 0x05,
-     value: [{tag: ICC_USIM_EFEMAIL_TAG,
-              length: 0x03,
-              value: [0x4F, 0x50, 0x0B]},
-             {tag: ICC_USIM_EFANR_TAG,
-              length: 0x03,
-              value: [0x4F, 0x11, 0x02]},
-             {tag: ICC_USIM_EFANR_TAG,
-              length: 0x03,
-              value: [0x4F, 0x12, 0x03]}]
-    },
-    {tag: ICC_USIM_TYPE3_TAG,
-     length: 0x0A,
-     value: [{tag: ICC_USIM_EFCCP1_TAG,
-              length: 0x03,
-              value: [0x4F, 0x3D, 0x0A]},
-             {tag: ICC_USIM_EFEXT1_TAG,
-              length: 0x03,
-              value: [0x4F, 0x4A, 0x03]}]
-    },
-  ];
-
-  let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
-  do_check_eq(pbr.adn.fileId, 0x4F3a);
-  do_check_eq(pbr.iap.fileId, 0x4F25);
-  do_check_eq(pbr.pbc.fileId, 0x4F09);
-  do_check_eq(pbr.email.fileId, 0x4F50);
-  do_check_eq(pbr.anr0.fileId, 0x4f11);
-  do_check_eq(pbr.anr1.fileId, 0x4f12);
-  do_check_eq(pbr.ccp1.fileId, 0x4F3D);
-  do_check_eq(pbr.ext1.fileId, 0x4F4A);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-  let io = context.ICCIOHelper;
-
-  io.getResponse = function fakeGetResponse(options) {
-    // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
-    do_check_true(false);
-    run_next_test();
-  };
-
-  ril.iccIO = function fakeIccIO(options) {
-    do_check_true(true);
-    run_next_test();
-  };
-
-  io.loadLinearFixedEF({recordSize: 0x20});
-});
-
-/**
- * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
- */
-add_test(function test_load_linear_fixed_ef() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-  let io = context.ICCIOHelper;
-
-  io.getResponse = function fakeGetResponse(options) {
-    do_check_true(true);
-    run_next_test();
-  };
-
-  ril.iccIO = function fakeIccIO(options) {
-    // When recordSize is not provided, loadLinearFixedEF should call getResponse.
-    do_check_true(false);
-    run_next_test();
-  };
-
-  io.loadLinearFixedEF({});
-});
-
-/**
- * Verify ICCRecordHelper.readPBR
- */
-add_test(function test_read_pbr() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let record = context.ICCRecordHelper;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
-    let pbr_1 = [
-      0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
-    ];
-
-    // Write data size
-    buf.writeInt32(pbr_1.length * 2);
-
-    // Write pbr
-    for (let i = 0; i < pbr_1.length; i++) {
-      helper.writeHexOctet(pbr_1[i]);
-    }
-
-    // Write string delimiter
-    buf.writeStringDelimiter(pbr_1.length * 2);
-
-    options.totalRecords = 2;
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  io.loadNextRecord = function fakeLoadNextRecord(options) {
-    let pbr_2 = [
-      0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-    ];
-
-    options.p1++;
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  let successCb = function successCb(pbrs) {
-    do_check_eq(pbrs[0].adn.fileId, 0x4f3a);
-    do_check_eq(pbrs.length, 1);
-  };
-
-  let errorCb = function errorCb(errorMsg) {
-    do_print("Reading EF_PBR failed, msg = " + errorMsg);
-    do_check_true(false);
-  };
-
-  record.readPBR(successCb, errorCb);
-
-  // Check cache pbrs when 2nd call
-  let ifLoadEF = false;
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
-    ifLoadEF = true;
-  }
-  record.readPBR(successCb, errorCb);
-  do_check_false(ifLoadEF);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.readEmail
- */
-add_test(function test_read_email() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let record = context.ICCRecordHelper;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-  let recordSize;
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
-    let email_1 = [
-      0x65, 0x6D, 0x61, 0x69, 0x6C,
-      0x00, 0x6D, 0x6F, 0x7A, 0x69,
-      0x6C, 0x6C, 0x61, 0x2E, 0x63,
-      0x6F, 0x6D, 0x02, 0x23];
-
-    // Write data size
-    buf.writeInt32(email_1.length * 2);
-
-    // Write email
-    for (let i = 0; i < email_1.length; i++) {
-      helper.writeHexOctet(email_1[i]);
-    }
-
-    // Write string delimiter
-    buf.writeStringDelimiter(email_1.length * 2);
-
-    recordSize = email_1.length;
-    options.recordSize = recordSize;
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  function doTestReadEmail(type, expectedResult) {
-    let fileId = 0x6a75;
-    let recordNumber = 1;
-
-    // fileId and recordNumber are dummy arguments.
-    record.readEmail(fileId, type, recordNumber, function(email) {
-      do_check_eq(email, expectedResult);
-    });
-  };
-
-  doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
-  doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
-  do_check_eq(record._emailRecordSize, recordSize);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateEmail
- */
-add_test(function test_update_email() {
-  const recordSize = 0x20;
-  const recordNumber = 1;
-  const fileId = 0x4f50;
-  const NUM_TESTS = 2;
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  let ril = context.RIL;
-  ril.appType = CARD_APPTYPE_USIM;
-  let recordHelper = context.ICCRecordHelper;
-  let buf = context.Buf;
-  let ioHelper = context.ICCIOHelper;
-  let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
-             adn: {sfi: 1}};
-  let count = 0;
-
-  // Override.
-  ioHelper.updateLinearFixedEF = function(options) {
-    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
-    options.command = ICC_COMMAND_UPDATE_RECORD;
-    options.p1 = options.recordNumber;
-    options.p2 = READ_RECORD_ABSOLUTE_MODE;
-    options.p3 = recordSize;
-    ril.iccIO(options);
-  };
-
-  function do_test(pbr, expectedEmail, expectedAdnRecordId) {
-    buf.sendParcel = function() {
-      count++;
-
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
-
-      // Token : we don't care
-      this.readInt32();
-
-      // command.
-      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
-      // fileId.
-      do_check_eq(this.readInt32(), fileId);
-
-      // pathId.
-      do_check_eq(this.readString(),
-                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
-      // p1.
-      do_check_eq(this.readInt32(), recordNumber);
-
-      // p2.
-      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
-      // p3.
-      do_check_eq(this.readInt32(), recordSize);
-
-      // data.
-      let strLen = this.readInt32();
-      let email;
-      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
-        email = iccHelper.read8BitUnpackedToString(recordSize);
-      } else {
-        email = iccHelper.read8BitUnpackedToString(recordSize - 2);
-        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
-        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
-      }
-      this.readStringDelimiter(strLen);
-      do_check_eq(email, expectedEmail);
-
-      // pin2.
-      do_check_eq(this.readString(), null);
-
-      if (!ril.v5Legacy) {
-        // AID. Ignore because it's from modem.
-        this.readInt32();
-      }
-
-      if (count == NUM_TESTS) {
-        run_next_test();
-      }
-    };
-    recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
-  }
-
-  do_test(pbr, "test@mail.com");
-  pbr.email.fileType = ICC_USIM_TYPE2_TAG;
-  do_test(pbr, "test@mail.com", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readANR
- */
-add_test(function test_read_anr() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let record = context.ICCRecordHelper;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-  let recordSize;
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
-    let anr_1 = [
-      0x01, 0x05, 0x81, 0x10, 0x32,
-      0x54, 0xF6, 0xFF, 0xFF];
-
-    // Write data size
-    buf.writeInt32(anr_1.length * 2);
-
-    // Write anr
-    for (let i = 0; i < anr_1.length; i++) {
-      helper.writeHexOctet(anr_1[i]);
-    }
-
-    // Write string delimiter
-    buf.writeStringDelimiter(anr_1.length * 2);
-
-    recordSize = anr_1.length;
-    options.recordSize = recordSize;
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  function doTestReadAnr(fileType, expectedResult) {
-    let fileId = 0x4f11;
-    let recordNumber = 1;
-
-    // fileId and recordNumber are dummy arguments.
-    record.readANR(fileId, fileType, recordNumber, function(anr) {
-      do_check_eq(anr, expectedResult);
-    });
-  };
-
-  doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
-  do_check_eq(record._anrRecordSize, recordSize);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCRecordHelper.updateANR
- */
-add_test(function test_update_anr() {
-  const recordSize = 0x20;
-  const recordNumber = 1;
-  const fileId = 0x4f11;
-  const NUM_TESTS = 2;
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let iccHelper = context.ICCPDUHelper;
-  let ril = context.RIL;
-  ril.appType = CARD_APPTYPE_USIM;
-  let recordHelper = context.ICCRecordHelper;
-  let buf = context.Buf;
-  let ioHelper = context.ICCIOHelper;
-  let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
-             adn: {sfi: 1}};
-  let count = 0;
-
-  // Override.
-  ioHelper.updateLinearFixedEF = function(options) {
-    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
-    options.command = ICC_COMMAND_UPDATE_RECORD;
-    options.p1 = options.recordNumber;
-    options.p2 = READ_RECORD_ABSOLUTE_MODE;
-    options.p3 = recordSize;
-    ril.iccIO(options);
-  };
-
-  function do_test(pbr, expectedANR, expectedAdnRecordId) {
-    buf.sendParcel = function() {
-      count++;
-
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
-
-      // Token : we don't care
-      this.readInt32();
-
-      // command.
-      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
-      // fileId.
-      do_check_eq(this.readInt32(), fileId);
-
-      // pathId.
-      do_check_eq(this.readString(),
-                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
-      // p1.
-      do_check_eq(this.readInt32(), recordNumber);
-
-      // p2.
-      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
-      // p3.
-      do_check_eq(this.readInt32(), recordSize);
-
-      // data.
-      let strLen = this.readInt32();
-      // EF_AAS, ignore.
-      pduHelper.readHexOctet();
-      do_check_eq(iccHelper.readNumberWithLength(), expectedANR);
-      // EF_CCP, ignore.
-      pduHelper.readHexOctet();
-      // EF_EXT1, ignore.
-      pduHelper.readHexOctet();
-      if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
-        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
-        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
-      }
-      this.readStringDelimiter(strLen);
-
-      // pin2.
-      do_check_eq(this.readString(), null);
-
-      if (!ril.v5Legacy) {
-        // AID. Ignore because it's from modem.
-        this.readInt32();
-      }
-
-      if (count == NUM_TESTS) {
-        run_next_test();
-      }
-    };
-    recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
-  }
-
-  do_test(pbr, "+123456789");
-  pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
-  do_test(pbr, "123456789", 1);
-});
-
-/**
- * Verify ICCRecordHelper.readIAP
- */
-add_test(function test_read_iap() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let record = context.ICCRecordHelper;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-  let recordSize;
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
-    let iap_1 = [0x01, 0x02];
-
-    // Write data size/
-    buf.writeInt32(iap_1.length * 2);
-
-    // Write iap.
-    for (let i = 0; i < iap_1.length; i++) {
-      helper.writeHexOctet(iap_1[i]);
-    }
-
-    // Write string delimiter.
-    buf.writeStringDelimiter(iap_1.length * 2);
-
-    recordSize = iap_1.length;
-    options.recordSize = recordSize;
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  function doTestReadIAP(expectedIAP) {
-    const fileId = 0x4f17;
-    const recordNumber = 1;
-
-    let successCb = function successCb(iap) {
-      for (let i = 0; i < iap.length; i++) {
-        do_check_eq(expectedIAP[i], iap[i]);
-      }
-      run_next_test();
-    }.bind(this);
-
-    let errorCb = function errorCb(errorMsg) {
-      do_print(errorMsg);
-      do_check_true(false);
-      run_next_test();
-    }.bind(this);
-
-    record.readIAP(fileId, recordNumber, successCb, errorCb);
-  };
-
-  doTestReadIAP([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.updateIAP
- */
-add_test(function test_update_iap() {
-  const recordSize = 2;
-  const recordNumber = 1;
-  const fileId = 0x4f17;
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let ril = context.RIL;
-  ril.appType = CARD_APPTYPE_USIM;
-  let recordHelper = context.ICCRecordHelper;
-  let buf = context.Buf;
-  let ioHelper = context.ICCIOHelper;
-  let count = 0;
-
-  // Override.
-  ioHelper.updateLinearFixedEF = function(options) {
-    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
-    options.command = ICC_COMMAND_UPDATE_RECORD;
-    options.p1 = options.recordNumber;
-    options.p2 = READ_RECORD_ABSOLUTE_MODE;
-    options.p3 = recordSize;
-    ril.iccIO(options);
-  };
-
-  function do_test(expectedIAP) {
-    buf.sendParcel = function() {
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
-
-      // Token : we don't care
-      this.readInt32();
-
-      // command.
-      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
-      // fileId.
-      do_check_eq(this.readInt32(), fileId);
-
-      // pathId.
-      do_check_eq(this.readString(),
-                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
-
-      // p1.
-      do_check_eq(this.readInt32(), recordNumber);
-
-      // p2.
-      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
-      // p3.
-      do_check_eq(this.readInt32(), recordSize);
-
-      // data.
-      let strLen = this.readInt32();
-      for (let i = 0; i < recordSize; i++) {
-        do_check_eq(expectedIAP[i], pduHelper.readHexOctet());
-      }
-      this.readStringDelimiter(strLen);
-
-      // pin2.
-      do_check_eq(this.readString(), null);
-
-      if (!ril.v5Legacy) {
-        // AID. Ignore because it's from modem.
-        this.readInt32();
-      }
-
-      run_next_test();
-    };
-    recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
-  }
-
-  do_test([1, 2]);
-});
-
-/**
- * Verify ICCRecordHelper.updateADNLike.
- */
-add_test(function test_update_adn_like() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-  let record = context.ICCRecordHelper;
-  let io = context.ICCIOHelper;
-  let pdu = context.ICCPDUHelper;
-  let buf = context.Buf;
-
-  ril.appType = CARD_APPTYPE_SIM;
-  const recordSize = 0x20;
-  let fileId;
-
-  // Override.
-  io.updateLinearFixedEF = function(options) {
-    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
-    options.command = ICC_COMMAND_UPDATE_RECORD;
-    options.p1 = options.recordNumber;
-    options.p2 = READ_RECORD_ABSOLUTE_MODE;
-    options.p3 = recordSize;
-    ril.iccIO(options);
-  };
-
-  buf.sendParcel = function() {
-    // Request Type.
-    do_check_eq(this.readInt32(), REQUEST_SIM_IO);
-
-    // Token : we don't care
-    this.readInt32();
-
-    // command.
-    do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
-    // fileId.
-    do_check_eq(this.readInt32(), fileId);
-
-    // pathId.
-    do_check_eq(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
-
-    // p1.
-    do_check_eq(this.readInt32(), 1);
-
-    // p2.
-    do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
-    // p3.
-    do_check_eq(this.readInt32(), 0x20);
-
-    // data.
-    let contact = pdu.readAlphaIdDiallingNumber(0x20);
-    do_check_eq(contact.alphaId, "test");
-    do_check_eq(contact.number, "123456");
-
-    // pin2.
-    if (fileId == ICC_EF_ADN) {
-      do_check_eq(this.readString(), null);
-    } else {
-      do_check_eq(this.readString(), "1111");
-    }
-
-    if (!ril.v5Legacy) {
-      // AID. Ignore because it's from modem.
-      this.readInt32();
-    }
-
-    if (fileId == ICC_EF_FDN) {
-      run_next_test();
-    }
-  };
-
-  fileId = ICC_EF_ADN;
-  record.updateADNLike(fileId,
-                       {recordId: 1, alphaId: "test", number: "123456"});
-
-  fileId = ICC_EF_FDN;
-  record.updateADNLike(fileId,
-                       {recordId: 1, alphaId: "test", number: "123456"},
-                       "1111");
-});
-
-/**
- * Verify ICCRecordHelper.findFreeRecordId.
- */
-add_test(function test_find_free_record_id() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let recordHelper = context.ICCRecordHelper;
-  let buf = context.Buf;
-  let io  = context.ICCIOHelper;
-
-  function writeRecord (record) {
-    // Write data size
-    buf.writeInt32(record.length * 2);
-
-    for (let i = 0; i < record.length; i++) {
-      pduHelper.writeHexOctet(record[i]);
-    }
-
-    // Write string delimiter
-    buf.writeStringDelimiter(record.length * 2);
-  }
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
-    // Some random data.
-    let record = [0x12, 0x34, 0x56, 0x78, 0x90];
-    options.p1 = 1;
-    options.totalRecords = 2;
-    writeRecord(record);
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  io.loadNextRecord = function fakeLoadNextRecord(options) {
-    // Unused bytes.
-    let record = [0xff, 0xff, 0xff, 0xff, 0xff];
-    options.p1++;
-    writeRecord(record);
-    if (options.callback) {
-      options.callback(options);
-    }
-  };
-
-  let fileId = 0x0000; // Dummy.
-  recordHelper.findFreeRecordId(
-    fileId,
-    function(recordId) {
-      do_check_eq(recordId, 2);
-      run_next_test();
-    }.bind(this),
-    function(errorMsg) {
-      do_print(errorMsg);
-      do_check_true(false);
-      run_next_test();
-    }.bind(this));
-});
-
-/**
- * Verify ICCContactHelper.readICCContacts
- */
-add_test(function test_read_icc_contacts() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let record = context.ICCRecordHelper;
-  let contactHelper = context.ICCContactHelper;
-  let ril = context.RIL;
-
-  function do_test(aSimType, aContactType, aExpectedContact, aEnhancedPhoneBook) {
-    ril.appType = aSimType;
-    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
-    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ?
-                                    [0x0, 0x0C, 0x0, 0x0, 0x0]:
-                                    [0x0, 0x00, 0x0, 0x0, 0x0];
-
-    // Override some functions to test.
-    contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
-      onsuccess(1);
-    };
-
-    record.readPBR = function readPBR(onsuccess, onerror) {
-      onsuccess([{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}]);
-    };
-
-    record.readADNLike = function readADNLike(fileId, onsuccess, onerror) {
-      onsuccess([{recordId: 1, alphaId: "name", number: "111111"}])
-    };
-
-    record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
-      onsuccess("hello@mail.com");
-    };
-
-    record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
-      onsuccess("123456");
-    };
-
-    let onsuccess = function onsuccess(contacts) {
-      let contact = contacts[0];
-      for (let key in contact) {
-        do_print("check " + key);
-        if (Array.isArray(contact[key])) {
-          do_check_eq(contact[key][0], aExpectedContact[key]);
-        } else {
-          do_check_eq(contact[key], aExpectedContact[key]);
-        }
-      }
-    };
-
-    let onerror = function onerror(errorMsg) {
-      do_print("readICCContacts failed: " + errorMsg);
-      do_check_true(false);
-    };
-
-    contactHelper.readICCContacts(aSimType, aContactType, onsuccess, onerror);
-  }
-
-  let expectedContact1 = {
-    pbrIndex: 0,
-    recordId: 1,
-    alphaId:  "name",
-    number:   "111111"
-  };
-
-  let expectedContact2 = {
-    pbrIndex: 0,
-    recordId: 1,
-    alphaId:  "name",
-    number:   "111111",
-    email:    "hello@mail.com",
-    anr:      "123456"
-  };
-
-  // SIM
-  do_print("Test read SIM adn contacts");
-  do_test(CARD_APPTYPE_SIM, "adn", expectedContact1);
-
-  do_print("Test read SIM fdn contacts");
-  do_test(CARD_APPTYPE_SIM, "fdn", expectedContact1);
-
-  // USIM
-  do_print("Test read USIM adn contacts");
-  do_test(CARD_APPTYPE_USIM, "adn", expectedContact2);
-
-  do_print("Test read USIM fdn contacts");
-  do_test(CARD_APPTYPE_USIM, "fdn", expectedContact1);
-
-  // RUIM
-  do_print("Test read RUIM adn contacts");
-  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact1);
-
-  do_print("Test read RUIM fdn contacts");
-  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1);
-
-  // RUIM with enhanced phone book
-  do_print("Test read RUIM adn contacts with enhanced phone book");
-  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact2, true);
-
-  do_print("Test read RUIM fdn contacts with enhanced phone book");
-  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1, true);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
- */
-add_test(function test_update_icc_contact() {
-  const ADN_RECORD_ID   = 100;
-  const ADN_SFI         = 1;
-  const IAP_FILE_ID     = 0x4f17;
-  const EMAIL_FILE_ID   = 0x4f50;
-  const EMAIL_RECORD_ID = 20;
-  const ANR0_FILE_ID    = 0x4f11;
-  const ANR0_RECORD_ID  = 30;
-
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let recordHelper = context.ICCRecordHelper;
-  let contactHelper = context.ICCContactHelper;
-  let ril = context.RIL;
-
-  function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
-    ril.appType = aSimType;
-    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
-    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x0, 0x0C, 0x0, 0x0, 0x0]
-                                                  : [0x0, 0x00, 0x0, 0x0, 0x0];
-
-    recordHelper.readPBR = function(onsuccess, onerror) {
-      if (aFileType === ICC_USIM_TYPE1_TAG) {
-        onsuccess([{
-          adn:   {fileId: ICC_EF_ADN},
-          email: {fileId: EMAIL_FILE_ID,
-                  fileType: ICC_USIM_TYPE1_TAG},
-          anr0:  {fileId: ANR0_FILE_ID,
-                  fileType: ICC_USIM_TYPE1_TAG}
-        }]);
-      } else if (aFileType === ICC_USIM_TYPE2_TAG) {
-        onsuccess([{
-          adn:   {fileId: ICC_EF_ADN,
-                  sfi: ADN_SFI},
-          iap:   {fileId: IAP_FILE_ID},
-          email: {fileId: EMAIL_FILE_ID,
-                  fileType: ICC_USIM_TYPE2_TAG,
-                  indexInIAP: 0},
-          anr0:  {fileId: ANR0_FILE_ID,
-                  fileType: ICC_USIM_TYPE2_TAG,
-                  indexInIAP: 1}
-        }]);
-      }
-    };
-
-    recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
-      if (aContactType === "fdn") {
-        do_check_eq(fileId, ICC_EF_FDN);
-      } else if (aContactType === "adn") {
-        do_check_eq(fileId, ICC_EF_ADN);
-      }
-      do_check_eq(pin2, aPin2);
-      do_check_eq(contact.alphaId, aContact.alphaId);
-      do_check_eq(contact.number, aContact.number);
-      onsuccess();
-    };
-
-    recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
-      do_check_eq(fileId, IAP_FILE_ID);
-      do_check_eq(recordNumber, ADN_RECORD_ID);
-      onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
-                                : [0xff, 0xff]);
-    };
-
-    recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
-      do_check_eq(fileId, IAP_FILE_ID);
-      do_check_eq(recordNumber, ADN_RECORD_ID);
-      onsuccess();
-    };
-
-    recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
-      do_check_eq(pbr.email.fileId, EMAIL_FILE_ID);
-      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
-        do_check_eq(recordNumber, ADN_RECORD_ID);
-      } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
-        do_check_eq(recordNumber, EMAIL_RECORD_ID);
-      }
-      do_check_eq(email, aContact.email);
-      onsuccess();
-    };
-
-    recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
-      do_check_eq(pbr.anr0.fileId, ANR0_FILE_ID);
-      if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
-        do_check_eq(recordNumber, ADN_RECORD_ID);
-      } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
-        do_check_eq(recordNumber, ANR0_RECORD_ID);
-      }
-      if (Array.isArray(aContact.anr)) {
-        do_check_eq(number, aContact.anr[0]);
-      }
-      onsuccess();
-    };
-
-    recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
-      let recordId = 0;
-      if (fileId === EMAIL_FILE_ID) {
-        recordId = EMAIL_RECORD_ID;
-      } else if (fileId === ANR0_FILE_ID) {
-        recordId = ANR0_RECORD_ID;
-      }
-      onsuccess(recordId);
-    };
-
-    let isSuccess = false;
-    let onsuccess = function onsuccess() {
-      do_print("updateICCContact success");
-      isSuccess = true;
-    };
-
-    let onerror = function onerror(errorMsg) {
-      do_print("updateICCContact failed: " + errorMsg);
-    };
-
-    contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
-    do_check_true(isSuccess);
-  }
-
-  let contacts = [
-    {
-      pbrIndex: 0,
-      recordId: ADN_RECORD_ID,
-      alphaId:  "test",
-      number:   "123456",
-      email:    "test@mail.com",
-      anr:      ["+654321"]
-    },
-    // a contact without email and anr.
-    {
-      pbrIndex: 0,
-      recordId: ADN_RECORD_ID,
-      alphaId:  "test2",
-      number:   "123456",
-    },
-    // a contact with email but no anr.
-    {
-      pbrIndex: 0,
-      recordId: ADN_RECORD_ID,
-      alphaId:  "test3",
-      number:   "123456",
-      email:    "test@mail.com"
-    },
-    // a contact with anr but no email.
-    {
-      pbrIndex: 0,
-      recordId: ADN_RECORD_ID,
-      alphaId:  "test4",
-      number:   "123456",
-      anr:      ["+654321"]
-    }];
-
-  for (let i = 0; i < contacts.length; i++) {
-    let contact = contacts[i];
-    // SIM
-    do_print("Test update SIM adn contacts");
-    do_test(CARD_APPTYPE_SIM, "adn", contact);
-
-    do_print("Test update SIM fdn contacts");
-    do_test(CARD_APPTYPE_SIM, "fdn", contact, "1234");
-
-    // USIM
-    do_print("Test update USIM adn contacts");
-    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE1_TAG);
-    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true);
-    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false);
-
-    do_print("Test update USIM fdn contacts");
-    do_test(CARD_APPTYPE_USIM, "fdn", contact, "1234");
-
-    // RUIM
-    do_print("Test update RUIM adn contacts");
-    do_test(CARD_APPTYPE_RUIM, "adn", contact);
-
-    do_print("Test update RUIM fdn contacts");
-    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234");
-
-    // RUIM with enhanced phone book
-    do_print("Test update RUIM adn contacts with enhanced phone book");
-    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE1_TAG, null, true);
-    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true, true);
-    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false, true);
-
-    do_print("Test update RUIM fdn contacts with enhanced phone book");
-    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234", null, true);
-  }
-
-  run_next_test();
-});
-
-/**
- * Verify updateICCContact with removal of anr and email with File Type 1.
- */
-add_test(function test_update_icc_contact_with_remove_type1_attr() {
-  const ADN_RECORD_ID   = 100;
-  const IAP_FILE_ID     = 0x4f17;
-  const EMAIL_FILE_ID   = 0x4f50;
-  const EMAIL_RECORD_ID = 20;
-  const ANR0_FILE_ID    = 0x4f11;
-  const ANR0_RECORD_ID  = 30;
-
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let recordHelper = context.ICCRecordHelper;
-  let contactHelper = context.ICCContactHelper;
-
-  recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
-    onsuccess();
-  };
-
-  let contact = {
-    pbrIndex: 0,
-    recordId: ADN_RECORD_ID,
-    alphaId:  "test2",
-    number:   "123456",
-  };
-
-  recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
-    onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
-  };
-
-  recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
-    do_check_true(email == null);
-    onsuccess();
-  };
-
-  recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
-    do_check_true(number == null);
-    onsuccess();
-  };
-
-  function do_test(type) {
-    recordHelper.readPBR = function(onsuccess, onerror) {
-      if (type == ICC_USIM_TYPE1_TAG) {
-        onsuccess([{
-          adn:   {fileId: ICC_EF_ADN},
-          email: {fileId: EMAIL_FILE_ID,
-                  fileType: ICC_USIM_TYPE1_TAG},
-          anr0:  {fileId: ANR0_FILE_ID,
-                  fileType: ICC_USIM_TYPE1_TAG}}]);
-      } else {
-        onsuccess([{
-          adn:   {fileId: ICC_EF_ADN},
-          iap:   {fileId: IAP_FILE_ID},
-          email: {fileId: EMAIL_FILE_ID,
-                  fileType: ICC_USIM_TYPE2_TAG,
-                  indexInIAP: 0},
-          anr0:  {fileId: ANR0_FILE_ID,
-                  fileType: ICC_USIM_TYPE2_TAG,
-                  indexInIAP: 1}}]);
-      }
-    };
-
-    let successCb = function() {
-      do_check_true(true);
-    };
-
-    let errorCb = function(errorMsg) {
-      do_print(errorMsg);
-      do_check_true(false);
-    };
-
-    contactHelper.updateICCContact(CARD_APPTYPE_USIM, "adn", contact, null, successCb, errorCb);
-  }
-
-  do_test(ICC_USIM_TYPE1_TAG);
-  do_test(ICC_USIM_TYPE2_TAG);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in SIM
- */
-add_test(function test_find_free_icc_contact_sim() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let recordHelper = context.ICCRecordHelper;
-  let contactHelper = context.ICCContactHelper;
-  // Correct record Id starts with 1, so put a null element at index 0.
-  let records = [null];
-  const MAX_RECORDS = 3;
-  const PBR_INDEX = 0;
-
-  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
-    if (records.length > MAX_RECORDS) {
-      onerror("No free record found.");
-      return;
-    }
-
-    onsuccess(records.length);
-  };
-
-  let successCb = function(pbrIndex, recordId) {
-    do_check_eq(pbrIndex, PBR_INDEX);
-    records[recordId] = {};
-  };
-
-  let errorCb = function(errorMsg) {
-    do_print(errorMsg);
-    do_check_true(false);
-  };
-
-  for (let i = 0; i < MAX_RECORDS; i++) {
-    contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
-  }
-  // The 1st element, records[0], is null.
-  do_check_eq(records.length - 1, MAX_RECORDS);
-
-  // Now the EF is full, so finding a free one should result failure.
-  successCb = function(pbrIndex, recordId) {
-    do_check_true(false);
-  };
-
-  errorCb = function(errorMsg) {
-    do_check_true(errorMsg === "No free record found.");
-  };
-  contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
-
-  run_next_test();
-});
-
-/**
- * Verify ICCContactHelper.findFreeICCContact in USIM
- */
-add_test(function test_find_free_icc_contact_usim() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let recordHelper = context.ICCRecordHelper;
-  let contactHelper = context.ICCContactHelper;
-  const ADN1_FILE_ID = 0x6f3a;
-  const ADN2_FILE_ID = 0x6f3b;
-  const MAX_RECORDS = 3;
-
-  // The adn in the first phonebook set has already two records, which means
-  // only 1 free record remained.
-  let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
-              {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
-
-  recordHelper.readPBR = function readPBR(onsuccess, onerror) {
-    onsuccess(pbrs);
-  };
-
-  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
-    let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
-    if (pbr.adn.records.length > MAX_RECORDS) {
-      onerror("No free record found.");
-      return;
-    }
-
-    onsuccess(pbr.adn.records.length);
-  };
-
-  let successCb = function(pbrIndex, recordId) {
-    do_check_eq(pbrIndex, 0);
-    pbrs[pbrIndex].adn.records[recordId] = {};
-  };
-
-  let errorCb = function(errorMsg) {
-    do_check_true(false);
-  };
-
-  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
-
-  // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
-  // will come from the 2nd phonebook set.
-  successCb = function(pbrIndex, recordId) {
-    do_check_eq(pbrIndex, 1);
-    do_check_eq(recordId, 1);
-  }
-  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
-
-  run_next_test();
-});
-
-/**
- * Test error message returned in onerror for readICCContacts.
- */
-add_test(function test_error_message_read_icc_contact () {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-
-  function do_test(options, expectedErrorMsg) {
-    ril.sendChromeMessage = function(message) {
-      do_check_eq(message.errorMsg, expectedErrorMsg);
-    }
-    ril.readICCContacts(options);
-  }
-
-  // Error 1, didn't specify correct contactType.
-  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
-  // Error 2, specifying a non-supported contactType.
-  ril.appType = CARD_APPTYPE_USIM;
-  do_test({contactType: "sdn"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
-  // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
-  // but forget to add implemenetations for it.
-  USIM_PBR_FIELDS.push("pbc");
-  do_test({contactType: "adn"}, CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
-  run_next_test();
-});
-
-/**
- * Test error message returned in onerror for updateICCContact.
- */
-add_test(function test_error_message_update_icc_contact() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-
-  const ICCID = "123456789";
-  ril.iccInfo.iccid = ICCID;
-
-  function do_test(options, expectedErrorMsg) {
-    ril.sendChromeMessage = function(message) {
-      do_check_eq(message.errorMsg, expectedErrorMsg);
-    }
-    ril.updateICCContact(options);
-  }
-
-  // Error 1, didn't specify correct contactType.
-  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
-  // Error 2, specifying a correct contactType, but without providing 'contact'.
-  do_test({contactType: "adn"}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
-
-  // Error 3, specifying a non-supported contactType.
-  ril.appType = CARD_APPTYPE_USIM;
-  do_test({contactType: "sdn", contact: {}}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
-
-  // Error 4, without supplying pin2.
-  do_test({contactType: "fdn", contact: {contactId: ICCID + "1"}}, GECKO_ERROR_SIM_PIN2);
-
-  // Error 5, No free record found in EF_ADN.
-  let record = context.ICCRecordHelper;
-  record.readPBR = function(onsuccess, onerror) {
-    onsuccess([{adn: {fileId: 0x4f3a}}]);
-  };
-
-  let io = context.ICCIOHelper;
-  io.loadLinearFixedEF = function(options) {
-    options.totalRecords = 1;
-    options.p1 = 1;
-    options.callback(options);
-  };
-
-  do_test({contactType: "adn", contact: {}}, CONTACT_ERR_NO_FREE_RECORD_FOUND);
-
-  // Error 6, ICC IO Error.
-  io.loadLinearFixedEF = function(options) {
-    ril[REQUEST_SIM_IO](0, {rilRequestError: ERROR_GENERIC_FAILURE});
-  };
-  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
-          GECKO_ERROR_GENERIC_FAILURE);
-
-  // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
-  // but forget to add implemenetations for it.
-  USIM_PBR_FIELDS.push("pbc");
-  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
-          CONTACT_ERR_FIELD_NOT_SUPPORTED);
-
-  // Error 8, EF_PBR doesn't exist.
-  record.readPBR = function(onsuccess, onerror) {
-    onsuccess([]);
-  };
-
-  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
-          CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
-
-  run_next_test();
-});
-
-add_test(function test_process_icc_io_error() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ioHelper = context.ICCIOHelper;
-
-  function do_test(errorCode, expectedErrorMsg) {
-    let called = false;
-    function errorCb(errorMsg) {
-      called = true;
-      do_check_eq(errorMsg, expectedErrorMsg);
-    }
-
-    ioHelper.processICCIOError({rilRequestError: errorCode,
-                                fileId: 0xffff,
-                                command: 0xff,
-                                sw1: 0xff,
-                                sw2: 0xff,
-                                onerror: errorCb});
-    do_check_true(called);
-  }
-
-  for (let i = 0; i < ERROR_REJECTED_BY_REMOTE + 1; i++) {
-    do_test(i, RIL_ERROR_TO_GECKO_ERROR[i]);
-  }
-
-  run_next_test();
-});
-
-add_test(function test_personalization_state() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-
-  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
-  function testPersonalization(isCdma, cardPersoState, geckoCardState) {
-    let iccStatus = {
-      cardState: CARD_STATE_PRESENT,
-      gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
-      cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
-      apps: [
-        {
-          app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
-          perso_substate: cardPersoState
-        }],
-    };
-
-    ril._isCdma = isCdma;
-    ril._processICCStatus(iccStatus);
-    do_check_eq(ril.cardState, geckoCardState);
-  }
-
-  // Test GSM personalization state.
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
-                      GECKO_CARDSTATE_NETWORK_LOCKED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
-                      GECKO_CARDSTATE_CORPORATE_LOCKED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
-                      GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
-                      GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
-                      GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
-                      GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
-  testPersonalization(false, CARD_PERSOSUBSTATE_READY,
-                      GECKO_CARDSTATE_PERSONALIZATION_READY);
-
-  // Test CDMA personalization state.
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
-                      GECKO_CARDSTATE_NETWORK1_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
-                      GECKO_CARDSTATE_NETWORK2_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
-                      GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
-                      GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
-                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
-                      GECKO_CARDSTATE_RUIM_LOCKED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
-                      GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
-                      GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
-                      GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
-                      GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
-                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
-  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
-                      GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
-
-  run_next_test();
-});
-
-/**
- * Verify SIM app_state in _processICCStatus
- */
-add_test(function test_card_app_state() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-
-  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
-  function testCardAppState(cardAppState, geckoCardState) {
-    let iccStatus = {
-      cardState: CARD_STATE_PRESENT,
-      gsmUmtsSubscriptionAppIndex: 0,
-      apps: [
-      {
-        app_state: cardAppState
-      }],
-    };
-
-    ril._processICCStatus(iccStatus);
-    do_check_eq(ril.cardState, geckoCardState);
-  }
-
-  testCardAppState(CARD_APPSTATE_ILLEGAL,
-                   GECKO_CARDSTATE_ILLEGAL);
-  testCardAppState(CARD_APPSTATE_PIN,
-                   GECKO_CARDSTATE_PIN_REQUIRED);
-  testCardAppState(CARD_APPSTATE_PUK,
-                   GECKO_CARDSTATE_PUK_REQUIRED);
-  testCardAppState(CARD_APPSTATE_READY,
-                   GECKO_CARDSTATE_READY);
-  testCardAppState(CARD_APPSTATE_UNKNOWN,
-                   GECKO_CARDSTATE_UNKNOWN);
-  testCardAppState(CARD_APPSTATE_DETECTED,
-                   GECKO_CARDSTATE_UNKNOWN);
-
-  run_next_test();
-});
-
-/**
- * Verify permanent blocked for ICC.
- */
-add_test(function test_icc_permanent_blocked() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-
-  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
-
-  function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
-    let iccStatus = {
-      cardState: CARD_STATE_PRESENT,
-      gsmUmtsSubscriptionAppIndex: 0,
-      universalPINState: universalPINState,
-      apps: [
-      {
-        pin1_replaced: pin1_replaced,
-        pin1: pin1
-      }]
-    };
-
-    ril._processICCStatus(iccStatus);
-    do_check_eq(ril.cardState, GECKO_CARDSTATE_PERMANENT_BLOCKED);
-  }
-
-  testPermanentBlocked(1,
-                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
-                       CARD_PINSTATE_UNKNOWN);
-  testPermanentBlocked(1,
-                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
-                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
-  testPermanentBlocked(0,
-                       CARD_PINSTATE_UNKNOWN,
-                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
-
-  run_next_test();
-});
-
-/**
- * Verify iccSetCardLock - Facility Lock.
- */
-add_test(function test_set_icc_card_lock_facility_lock() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let aid = "123456789";
-  let ril = context.RIL;
-  ril.aid = aid;
-  ril.v5Legacy = false;
-  let buf = context.Buf;
-
-  let GECKO_CARDLOCK_TO_FACILITIY_LOCK = {};
-  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
-  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
-
-  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_PIN] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_FDN] = "pin2";
-
-  const pin = "1234";
-  const pin2 = "4321";
-  let GECKO_CARDLOCK_TO_PASSWORD = {};
-  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_PIN] = pin;
-  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_FDN] = pin2;
-
-  const serviceClass = ICC_SERVICE_CLASS_VOICE |
-                       ICC_SERVICE_CLASS_DATA  |
-                       ICC_SERVICE_CLASS_FAX;
-
-  function do_test(aLock, aPassword, aEnabled) {
-    buf.sendParcel = function fakeSendParcel () {
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
-
-      // Token : we don't care
-      this.readInt32();
-
-      let parcel = this.readStringList();
-      do_check_eq(parcel.length, 5);
-      do_check_eq(parcel[0], GECKO_CARDLOCK_TO_FACILITIY_LOCK[aLock]);
-      do_check_eq(parcel[1], aEnabled ? "1" : "0");
-      do_check_eq(parcel[2], GECKO_CARDLOCK_TO_PASSWORD[aLock]);
-      do_check_eq(parcel[3], serviceClass.toString());
-      do_check_eq(parcel[4], aid);
-    };
-
-    let lock = {lockType: aLock,
-                enabled: aEnabled};
-    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
-
-    ril.iccSetCardLock(lock);
-  }
-
-  do_test(GECKO_CARDLOCK_PIN, pin, true);
-  do_test(GECKO_CARDLOCK_PIN, pin, false);
-  do_test(GECKO_CARDLOCK_FDN, pin2, true);
-  do_test(GECKO_CARDLOCK_FDN, pin2, false);
-
-  run_next_test();
-});
-
-/**
- * Verify iccUnlockCardLock.
- */
-add_test(function test_unlock_card_lock_corporateLocked() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let ril = context.RIL;
-  let buf = context.Buf;
-  const pin = "12345678";
-  const puk = "12345678";
-
-  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK] = "pin";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK_PUK] = "puk";
-  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK_PUK] = "puk";
-
-  function do_test(aLock, aPassword) {
-    buf.sendParcel = function fakeSendParcel () {
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
-
-      // Token : we don't care
-      this.readInt32();
-
-      let lockType = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock];
-      // Lock Type
-      do_check_eq(this.readInt32(), lockType);
-
-      // Pin/Puk.
-      do_check_eq(this.readString(), aPassword);
-    };
-
-    let lock = {lockType: aLock};
-    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
-    ril.iccUnlockCardLock(lock);
-  }
-
-  do_test(GECKO_CARDLOCK_NCK, pin);
-  do_test(GECKO_CARDLOCK_NCK1, pin);
-  do_test(GECKO_CARDLOCK_NCK2, pin);
-  do_test(GECKO_CARDLOCK_HNCK, pin);
-  do_test(GECKO_CARDLOCK_CCK, pin);
-  do_test(GECKO_CARDLOCK_SPCK, pin);
-  do_test(GECKO_CARDLOCK_RCCK, pin);
-  do_test(GECKO_CARDLOCK_RSPCK, pin);
-  do_test(GECKO_CARDLOCK_NCK_PUK, puk);
-  do_test(GECKO_CARDLOCK_NCK1_PUK, puk);
-  do_test(GECKO_CARDLOCK_NCK2_PUK, puk);
-  do_test(GECKO_CARDLOCK_HNCK_PUK, puk);
-  do_test(GECKO_CARDLOCK_CCK_PUK, puk);
-  do_test(GECKO_CARDLOCK_SPCK_PUK, puk);
-  do_test(GECKO_CARDLOCK_RCCK_PUK, puk);
-  do_test(GECKO_CARDLOCK_RSPCK_PUK, puk);
-
-  run_next_test();
-});
-
-/**
- * Verify MCC and MNC parsing
- */
-add_test(function test_mcc_mnc_parsing() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.ICCUtilsHelper;
-
-  function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
-    let result = helper.parseMccMncFromImsi(imsi, mncLength);
-
-    if (!imsi) {
-      do_check_eq(result, null);
-      return;
-    }
-
-    do_check_eq(result.mcc, expectedMcc);
-    do_check_eq(result.mnc, expectedMnc);
-  }
-
-  // Test the imsi is null.
-  do_test(null, null, null, null);
-
-  // Test MCC is Taiwan
-  do_test("466923202422409", 0x02, "466", "92");
-  do_test("466923202422409", 0x03, "466", "923");
-  do_test("466923202422409", null, "466", "92");
-
-  // Test MCC is US
-  do_test("310260542718417", 0x02, "310", "26");
-  do_test("310260542718417", 0x03, "310", "260");
-  do_test("310260542718417", null, "310", "260");
-
-  run_next_test();
- });
-
- /**
-  * Verify reading EF_AD and parsing MCC/MNC
-  */
-add_test(function test_reading_ad_and_parsing_mcc_mnc() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let record = context.SimRecordHelper;
-  let helper = context.GsmPDUHelper;
-  let ril    = context.RIL;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-
-  function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
-    ril.iccInfoPrivate.imsi = imsi;
-
-    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
-      let ad = [0x00, 0x00, 0x00];
-      if (typeof mncLengthInEf === 'number') {
-        ad.push(mncLengthInEf);
-      }
-
-      // Write data size
-      buf.writeInt32(ad.length * 2);
-
-      // Write data
-      for (let i = 0; i < ad.length; i++) {
-        helper.writeHexOctet(ad[i]);
-      }
-
-      // Write string delimiter
-      buf.writeStringDelimiter(ad.length * 2);
-
-      if (options.callback) {
-        options.callback(options);
-      }
-    };
-
-    record.readAD();
-
-    do_check_eq(ril.iccInfo.mcc, expectedMcc);
-    do_check_eq(ril.iccInfo.mnc, expectedMnc);
-  }
-
-  do_test(undefined, "466923202422409", "466", "92" );
-  do_test(0x00,      "466923202422409", "466", "92" );
-  do_test(0x01,      "466923202422409", "466", "92" );
-  do_test(0x02,      "466923202422409", "466", "92" );
-  do_test(0x03,      "466923202422409", "466", "923");
-  do_test(0x04,      "466923202422409", "466", "92" );
-  do_test(0xff,      "466923202422409", "466", "92" );
-
-  do_test(undefined, "310260542718417", "310", "260");
-  do_test(0x00,      "310260542718417", "310", "260");
-  do_test(0x01,      "310260542718417", "310", "260");
-  do_test(0x02,      "310260542718417", "310", "26" );
-  do_test(0x03,      "310260542718417", "310", "260");
-  do_test(0x04,      "310260542718417", "310", "260");
-  do_test(0xff,      "310260542718417", "310", "260");
-
-  run_next_test();
-});
-
-add_test(function test_reading_optional_efs() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let record = context.SimRecordHelper;
-  let gsmPdu = context.GsmPDUHelper;
-  let ril    = context.RIL;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-
-  function buildSST(supportedEf) {
-    let sst = [];
-    let len = supportedEf.length;
-    for (let i = 0; i < len; i++) {
-      let index, bitmask, iccService;
-      if (ril.appType === CARD_APPTYPE_SIM) {
-        iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
-        iccService -= 1;
-        index = Math.floor(iccService / 4);
-        bitmask = 2 << ((iccService % 4) << 1);
-      } else if (ril.appType === CARD_APPTYPE_USIM){
-        iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
-        iccService -= 1;
-        index = Math.floor(iccService / 8);
-        bitmask = 1 << ((iccService % 8) << 0);
-      }
-
-      if (sst) {
-        sst[index] |= bitmask;
-      }
-    }
-    return sst;
-  }
-
-  ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
-    // Ignore updateCellBroadcastConfig after reading SST
-  };
-
-  function do_test(sst, supportedEf) {
-    // Clone supportedEf to local array for testing
-    let testEf = supportedEf.slice(0);
-
-    record.readMSISDN = function fakeReadMSISDN() {
-      testEf.splice(testEf.indexOf("MSISDN"), 1);
-    };
-
-    record.readMBDN = function fakeReadMBDN() {
-      testEf.splice(testEf.indexOf("MDN"), 1);
-    };
-
-    record.readMWIS = function fakeReadMWIS() {
-      testEf.splice(testEf.indexOf("MWIS"), 1);
-    };
-
-    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
-      // Write data size
-      buf.writeInt32(sst.length * 2);
-
-      // Write data
-      for (let i = 0; i < sst.length; i++) {
-         gsmPdu.writeHexOctet(sst[i] || 0);
-      }
-
-      // Write string delimiter
-      buf.writeStringDelimiter(sst.length * 2);
-
-      if (options.callback) {
-        options.callback(options);
-      }
-
-      if (testEf.length !== 0) {
-        do_print("Un-handled EF: " + JSON.stringify(testEf));
-        do_check_true(false);
-      }
-    };
-
-    record.readSST();
-  }
-
-  // TODO: Add all necessary optional EFs eventually
-  let supportedEf = ["MSISDN", "MDN", "MWIS"];
-  ril.appType = CARD_APPTYPE_SIM;
-  do_test(buildSST(supportedEf), supportedEf);
-  ril.appType = CARD_APPTYPE_USIM;
-  do_test(buildSST(supportedEf), supportedEf);
-
-  run_next_test();
-});
-
-/**
- * Verify fetchSimRecords.
- */
-add_test(function test_fetch_sim_recodes() {
-  let worker = newWorker();
-  let context = worker.ContextPool._contexts[0];
-  let RIL = context.RIL;
-  let iccRecord = context.ICCRecordHelper;
-  let simRecord = context.SimRecordHelper;
-
-  function testFetchSimRecordes(expectCalled) {
-    let ifCalled = [];
-
-    RIL.getIMSI = function() {
-      ifCalled.push("getIMSI");
-    };
-
-    simRecord.readAD = function() {
-      ifCalled.push("readAD");
-    };
-
-    simRecord.readSST = function() {
-      ifCalled.push("readSST");
-    };
-
-    simRecord.fetchSimRecords();
-
-    for (let i = 0; i < expectCalled.length; i++ ) {
-      if (ifCalled[i] != expectCalled[i]) {
-        do_print(expectCalled[i] + " is not called.");
-        do_check_true(false);
-      }
-    }
-  }
-
-  let expectCalled = ["getIMSI", "readAD", "readSST"];
-  testFetchSimRecordes(expectCalled);
-
-  run_next_test();
-});
-
-add_test(function test_fetch_icc_recodes() {
-  let worker = newWorker();
-  let context = worker.ContextPool._contexts[0];
-  let RIL = context.RIL;
-  let iccRecord = context.ICCRecordHelper;
-  let simRecord = context.SimRecordHelper;
-  let ruimRecord = context.RuimRecordHelper;
-  let fetchTag = 0x00;
-
-  simRecord.fetchSimRecords = function() {
-    fetchTag = 0x01;
-  };
-
-  ruimRecord.fetchRuimRecords = function() {
-    fetchTag = 0x02;
-  };
-
-  RIL.appType = CARD_APPTYPE_SIM;
-  iccRecord.fetchICCRecords();
-  do_check_eq(fetchTag, 0x01);
-
-  RIL.appType = CARD_APPTYPE_RUIM;
-  iccRecord.fetchICCRecords();
-  do_check_eq(fetchTag, 0x02);
-
-  RIL.appType = CARD_APPTYPE_USIM;
-  iccRecord.fetchICCRecords();
-  do_check_eq(fetchTag, 0x01);
-
-  run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.readMWIS
- */
-add_test(function test_read_mwis() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let helper = context.GsmPDUHelper;
-  let recordHelper = context.SimRecordHelper;
-  let buf    = context.Buf;
-  let io     = context.ICCIOHelper;
-  let mwisData;
-  let postedMessage;
-
-  worker.postMessage = function fakePostMessage(message) {
-    postedMessage = message;
-  };
-
-  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
-    if (mwisData) {
-      // Write data size
-      buf.writeInt32(mwisData.length * 2);
-
-      // Write MWIS
-      for (let i = 0; i < mwisData.length; i++) {
-        helper.writeHexOctet(mwisData[i]);
-      }
-
-      // Write string delimiter
-      buf.writeStringDelimiter(mwisData.length * 2);
-
-      options.recordSize = mwisData.length;
-      if (options.callback) {
-        options.callback(options);
-      }
-    } else {
-      do_print("mwisData[] is not set.");
-    }
-  };
-
-  function buildMwisData(isActive, msgCount) {
-    if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
-      msgCount = 0;
-    } else if (msgCount > 255) {
-      msgCount = 255;
-    }
-
-    mwisData =  [ (isActive) ? 0x01 : 0x00,
-                  msgCount,
-                  0xFF, 0xFF, 0xFF ];
-  }
-
-  function do_test(isActive, msgCount) {
-    buildMwisData(isActive, msgCount);
-    recordHelper.readMWIS();
-
-    do_check_eq("iccmwis", postedMessage.rilMessageType);
-    do_check_eq(isActive, postedMessage.mwi.active);
-    do_check_eq((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
-  }
-
-  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
-  do_test(true, 1);
-  do_test(true, 255);
-
-  do_test(false, 0);
-  do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
-
-  run_next_test();
-});
-
-/**
- * Verify SimRecordHelper.updateMWIS
- */
-add_test(function test_update_mwis() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let ril = context.RIL;
-  ril.appType = CARD_APPTYPE_USIM;
-  ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
-  let recordHelper = context.SimRecordHelper;
-  let buf = context.Buf;
-  let ioHelper = context.ICCIOHelper;
-  let recordSize = ril.iccInfoPrivate.mwis.length;
-  let recordNum = 1;
-
-  ioHelper.updateLinearFixedEF = function(options) {
-    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
-    options.command = ICC_COMMAND_UPDATE_RECORD;
-    options.p1 = options.recordNumber;
-    options.p2 = READ_RECORD_ABSOLUTE_MODE;
-    options.p3 = recordSize;
-    ril.iccIO(options);
-  };
-
-  function do_test(isActive, count) {
-    let mwis = ril.iccInfoPrivate.mwis;
-    let isUpdated = false;
-
-    function buildMwisData() {
-      let result = mwis.slice(0);
-      result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
-      result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
-
-      return result;
-    }
-
-    buf.sendParcel = function() {
-      isUpdated = true;
-
-      // Request Type.
-      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
-
-      // Token : we don't care
-      this.readInt32();
-
-      // command.
-      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
-
-      // fileId.
-      do_check_eq(this.readInt32(), ICC_EF_MWIS);
-
-      // pathId.
-      do_check_eq(this.readString(),
-                  EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
-
-      // p1.
-      do_check_eq(this.readInt32(), recordNum);
-
-      // p2.
-      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
-
-      // p3.
-      do_check_eq(this.readInt32(), recordSize);
-
-      // data.
-      let strLen = this.readInt32();
-      do_check_eq(recordSize * 2, strLen);
-      let expectedMwis = buildMwisData();
-      for (let i = 0; i < recordSize; i++) {
-        do_check_eq(expectedMwis[i], pduHelper.readHexOctet());
-      }
-      this.readStringDelimiter(strLen);
-
-      // pin2.
-      do_check_eq(this.readString(), null);
-
-      if (!ril.v5Legacy) {
-        // AID. Ignore because it's from modem.
-        this.readInt32();
-      }
-    };
-
-    do_check_false(isUpdated);
-
-    recordHelper.updateMWIS({ active: isActive,
-                              msgCount: count });
-
-    do_check_true((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
-  }
-
-  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
-  do_test(true, 1);
-  do_test(true, 255);
-
-  do_test(false, 0);
-
-  // Test if Path ID is correct for SIM.
-  ril.appType = CARD_APPTYPE_SIM;
-  do_test(false, 0);
-
-  // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
-  // EF_MWIS is not loaded/available.
-  delete ril.iccInfoPrivate.mwis;
-  do_test(false, 0);
-
-  run_next_test();
-});
-
-/**
- * Verify the call flow of receiving Class 2 SMS stored in SIM:
- * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
- * 2. SimRecordHelper.readSMS().
- * 3. sendChromeMessage() with rilMessageType == "sms-received".
- */
-add_test(function test_read_new_sms_on_sim() {
-  // Instead of reusing newUint8Worker defined in this file,
-  // we define our own worker to fake the methods in WorkerBuffer dynamically.
-  function newSmsOnSimWorkerHelper() {
-    let _postedMessage;
-    let _worker = newWorker({
-      postRILMessage: function(data) {
-      },
-      postMessage: function(message) {
-        _postedMessage = message;
-      }
-    });
-
-    _worker.debug = do_print;
-
-    return {
-      get postedMessage() {
-        return _postedMessage;
-      },
-      get worker() {
-        return _worker;
-      },
-      fakeWokerBuffer: function() {
-        let context = _worker.ContextPool._contexts[0];
-        let index = 0; // index for read
-        let buf = [];
-        context.Buf.writeUint8 = function(value) {
-          buf.push(value);
-        };
-        context.Buf.readUint8 = function() {
-          return buf[index++];
-        };
-        context.Buf.seekIncoming = function(offset) {
-          index += offset;
-        };
-        context.Buf.getReadAvailable = function() {
-          return buf.length - index;
-        };
-      }
-    };
-  }
-
-  let workerHelper = newSmsOnSimWorkerHelper();
-  let worker = workerHelper.worker;
-  let context = worker.ContextPool._contexts[0];
-
-  context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
-      // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
-      let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
-                       // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
-                       // 1. Record length == 176 bytes.
-                       // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
-                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
-                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
-
-      workerHelper.fakeWokerBuffer();
-
-      context.Buf.writeString(SimSmsPduHex);
-
-      options.recordSize = 176; // Record length is fixed to 176 bytes.
-      if (options.callback) {
-        options.callback(options);
-      }
-  };
-
-  function newSmsOnSimParcel() {
-    let data = new Uint8Array(4 + 4); // Int32List with 1 element.
-    let offset = 0;
-
-    function writeInt(value) {
-      data[offset++] = value & 0xFF;
-      data[offset++] = (value >>  8) & 0xFF;
-      data[offset++] = (value >> 16) & 0xFF;
-      data[offset++] = (value >> 24) & 0xFF;
-    }
-
-    writeInt(1); // Length of Int32List
-    writeInt(1); // RecordNum = 1.
-
-    return newIncomingParcel(-1,
-                             RESPONSE_TYPE_UNSOLICITED,
-                             UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
-                             data);
-  }
-
-  function do_test() {
-    worker.onRILMessage(0, newSmsOnSimParcel());
-
-    let postedMessage = workerHelper.postedMessage;
-
-    do_check_eq("sms-received", postedMessage.rilMessageType);
-    do_check_eq("+0123456789", postedMessage.SMSC);
-    do_check_eq("+9876543210", postedMessage.sender);
-    do_check_eq("How are you?", postedMessage.body);
-  }
-
-  do_test();
-
-  run_next_test();
-});
-
-// Test ICC_COMMAND_GET_RESPONSE with FCP template format.
-/**
- * Verify transparent structure with FCP template format.
- */
-add_test(function test_fcp_template_for_transparent_structure() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let berHelper = context.BerTlvHelper;
-
-  let tag_test = [
-    0x62,
-    0x22,
-    0x82, 0x02, 0x41, 0x21,
-    0x83, 0x02, 0x2F, 0xE2,
-    0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
-    0x8A, 0x01, 0x05,
-    0x8B, 0x03, 0x2F, 0x06, 0x0B,
-    0x80, 0x02, 0x00, 0x0A,
-    0x88, 0x01, 0x10];
-
-  for (let i = 0; i < tag_test.length; i++) {
-    pduHelper.writeHexOctet(tag_test[i]);
-  }
-
-  let berTlv = berHelper.decode(tag_test.length);
-  let iter = Iterator(berTlv.value);
-  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
-  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_TRANSPARENT]);
-
-  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
-  do_check_eq(tlv.value.fileId, 0x2FE2);
-
-  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
-  do_check_eq(tlv.value.fileSizeData, 0x0A);
-
-  run_next_test();
-});
-
-/**
- * Verify linear fixed structure with FCP template format.
- */
-add_test(function test_fcp_template_for_linear_fixed_structure() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let pduHelper = context.GsmPDUHelper;
-  let berHelper = context.BerTlvHelper;
-
-  let tag_test = [
-    0x62,
-    0x1E,
-    0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
-    0x83, 0x02, 0x6F, 0x40,
-    0xA5, 0x03, 0x92, 0x01, 0x00,
-    0x8A, 0x01, 0x07,
-    0x8B, 0x03, 0x6F, 0x06, 0x02,
-    0x80, 0x02, 0x00, 0x1A,
-    0x88, 0x00];
-
-  for (let i = 0; i < tag_test.length; i++) {
-    pduHelper.writeHexOctet(tag_test[i]);
-  }
-
-  let berTlv = berHelper.decode(tag_test.length);
-  let iter = Iterator(berTlv.value);
-  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
-  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED]);
-  do_check_eq(tlv.value.recordLength, 0x1A);
-  do_check_eq(tlv.value.numOfRecords, 0x01);
-
-  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
-  do_check_eq(tlv.value.fileId, 0x6F40);
-
-  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
-  do_check_eq(tlv.value.fileSizeData, 0x1A);
-
-  run_next_test();
-});
-
-add_test(function test_icc_io_get_response_for_transparent_structure() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let buf = context.Buf;
-  let iccioHelper = context.ICCIOHelper;
-  let pduHelper = context.GsmPDUHelper;
-
-  let responseArray = [
-    // SIM response.
-    [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
-     0x02, 0x00, 0x00],
-    // USIM response.
-    [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
-     0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
-     0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
-  ];
-
-  for (let i = 0; i < responseArray.length; i++) {
-    let strLen = responseArray[i].length * 2;
-    buf.writeInt32(strLen);
-    for (let j = 0; j < responseArray[i].length; j++) {
-      pduHelper.writeHexOctet(responseArray[i][j]);
-    }
-    buf.writeStringDelimiter(strLen);
-
-    let options = {fileId: ICC_EF_ICCID,
-                   type: EF_TYPE_TRANSPARENT};
-    iccioHelper.processICCIOGetResponse(options);
-
-    do_check_eq(options.fileSize, 0x0A);
-  }
-
-  run_next_test();
-});
-
-add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let buf = context.Buf;
-  let iccioHelper = context.ICCIOHelper;
-  let pduHelper = context.GsmPDUHelper;
-
-  let responseArray = [
-    // SIM response.
-    [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
-     0x02, 0x01, 0x1A],
-    // USIM response.
-    [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
-     0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
-     0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
-  ];
-
-  for (let i = 0; i < responseArray.length; i++) {
-    let strLen = responseArray[i].length * 2;
-    buf.writeInt32(strLen);
-    for (let j = 0; j < responseArray[i].length; j++) {
-      pduHelper.writeHexOctet(responseArray[i][j]);
-    }
-    buf.writeStringDelimiter(strLen);
-
-    let options = {fileId: ICC_EF_MSISDN,
-                   type: EF_TYPE_LINEAR_FIXED};
-    iccioHelper.processICCIOGetResponse(options);
-
-    do_check_eq(options.fileSize, 0x1A);
-    do_check_eq(options.recordSize, 0x1A);
-    do_check_eq(options.totalRecords, 0x01);
-  }
-
-  run_next_test();
-});
-
-/**
- * Verify reading EF_ICCID.
- */
-add_test(function test_handling_iccid() {
-  let worker = newUint8Worker();
-  let context = worker.ContextPool._contexts[0];
-  let record = context.ICCRecordHelper;
-  let helper = context.GsmPDUHelper;
-  let ril = context.RIL;
-  let buf = context.Buf;
-  let io = context.ICCIOHelper;
-
-  ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
-  };
-
-  function do_test(rawICCID, expectedICCID) {
-    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
-      // Write data size
-      buf.writeInt32(rawICCID.length);
-
-      // Write data
-      for (let i = 0; i < rawICCID.length; i += 2) {
-        helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
-      }
-
-      // Write string delimiter
-      buf.writeStringDelimiter(rawICCID.length);
-
-      if (options.callback) {
-        options.callback(options);
-      }
-    };
-
-    record.readICCID();
-
-    do_check_eq(ril.iccInfo.iccid, expectedICCID);
-  }
-
-  // Invalid char at high nibbile + low nibbile contains 0xF.
-  do_test("9868002E90909F001519", "89860020909");
-  // Invalid char at low nibbile.
-  do_test("986800E2909090001519", "8986002090909005191");
-  // Valid ICCID.
-  do_test("98101430121181157002", "89014103211118510720");
-
-  run_next_test();
-});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_BerTlvHelper.js
@@ -0,0 +1,87 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+// Test ICC_COMMAND_GET_RESPONSE with FCP template format.
+/**
+ * Verify transparent structure with FCP template format.
+ */
+add_test(function test_fcp_template_for_transparent_structure() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let berHelper = context.BerTlvHelper;
+
+  let tag_test = [
+    0x62,
+    0x22,
+    0x82, 0x02, 0x41, 0x21,
+    0x83, 0x02, 0x2F, 0xE2,
+    0xA5, 0x09, 0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00,
+    0x8A, 0x01, 0x05,
+    0x8B, 0x03, 0x2F, 0x06, 0x0B,
+    0x80, 0x02, 0x00, 0x0A,
+    0x88, 0x01, 0x10];
+
+  for (let i = 0; i < tag_test.length; i++) {
+    pduHelper.writeHexOctet(tag_test[i]);
+  }
+
+  let berTlv = berHelper.decode(tag_test.length);
+  let iter = Iterator(berTlv.value);
+  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
+  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_TRANSPARENT]);
+
+  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
+  do_check_eq(tlv.value.fileId, 0x2FE2);
+
+  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
+  do_check_eq(tlv.value.fileSizeData, 0x0A);
+
+  run_next_test();
+});
+
+/**
+ * Verify linear fixed structure with FCP template format.
+ */
+add_test(function test_fcp_template_for_linear_fixed_structure() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let berHelper = context.BerTlvHelper;
+
+  let tag_test = [
+    0x62,
+    0x1E,
+    0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01,
+    0x83, 0x02, 0x6F, 0x40,
+    0xA5, 0x03, 0x92, 0x01, 0x00,
+    0x8A, 0x01, 0x07,
+    0x8B, 0x03, 0x6F, 0x06, 0x02,
+    0x80, 0x02, 0x00, 0x1A,
+    0x88, 0x00];
+
+  for (let i = 0; i < tag_test.length; i++) {
+    pduHelper.writeHexOctet(tag_test[i]);
+  }
+
+  let berTlv = berHelper.decode(tag_test.length);
+  let iter = Iterator(berTlv.value);
+  let tlv = berHelper.searchForNextTag(BER_FCP_FILE_DESCRIPTOR_TAG, iter);
+  do_check_eq(tlv.value.fileStructure, UICC_EF_STRUCTURE[EF_TYPE_LINEAR_FIXED]);
+  do_check_eq(tlv.value.recordLength, 0x1A);
+  do_check_eq(tlv.value.numOfRecords, 0x01);
+
+  tlv = berHelper.searchForNextTag(BER_FCP_FILE_IDENTIFIER_TAG, iter);
+  do_check_eq(tlv.value.fileId, 0x6F40);
+
+  tlv = berHelper.searchForNextTag(BER_FCP_FILE_SIZE_DATA_TAG, iter);
+  do_check_eq(tlv.value.fileSizeData, 0x1A);
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_CardLock.js
@@ -0,0 +1,357 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify RIL.iccGetCardLockState("fdn")
+ */
+add_test(function test_icc_get_card_lock_state_fdn() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+  let buf = context.Buf;
+
+  buf.sendParcel = function() {
+    // Request Type.
+    do_check_eq(this.readInt32(), REQUEST_QUERY_FACILITY_LOCK)
+
+    // Token : we don't care.
+    this.readInt32();
+
+    // String Array Length.
+    do_check_eq(this.readInt32(), ril.v5Legacy ? 3 : 4);
+
+    // Facility.
+    do_check_eq(this.readString(), ICC_CB_FACILITY_FDN);
+
+    // Password.
+    do_check_eq(this.readString(), "");
+
+    // Service class.
+    do_check_eq(this.readString(), (ICC_SERVICE_CLASS_VOICE |
+                                    ICC_SERVICE_CLASS_DATA  |
+                                    ICC_SERVICE_CLASS_FAX).toString());
+
+    if (!ril.v5Legacy) {
+      // AID. Ignore because it's from modem.
+      this.readInt32();
+    }
+
+    run_next_test();
+  };
+
+  ril.iccGetCardLockState({lockType: "fdn"});
+});
+
+add_test(function test_path_id_for_spid_and_spn() {
+  let worker = newWorker({
+    postRILMessage: function(data) {
+      // Do nothing
+    },
+    postMessage: function(message) {
+      // Do nothing
+    }});
+  let context = worker.ContextPool._contexts[0];
+  let RIL = context.RIL;
+  let ICCFileHelper = context.ICCFileHelper;
+
+  // Test SIM
+  RIL.appType = CARD_APPTYPE_SIM;
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
+              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPN),
+              EF_PATH_MF_SIM + EF_PATH_DF_GSM);
+
+  // Test USIM
+  RIL.appType = CARD_APPTYPE_USIM;
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
+              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
+  do_check_eq(ICCFileHelper.getEFPath(ICC_EF_SPDI),
+              EF_PATH_MF_SIM + EF_PATH_ADF_USIM);
+  run_next_test();
+});
+
+add_test(function test_personalization_state() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+
+  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
+
+  function testPersonalization(isCdma, cardPersoState, geckoCardState) {
+    let iccStatus = {
+      cardState: CARD_STATE_PRESENT,
+      gsmUmtsSubscriptionAppIndex: (!isCdma) ? 0 : -1,
+      cdmaSubscriptionAppIndex: (isCdma) ? 0 : -1,
+      apps: [
+        {
+          app_state: CARD_APPSTATE_SUBSCRIPTION_PERSO,
+          perso_substate: cardPersoState
+        }],
+    };
+
+    ril._isCdma = isCdma;
+    ril._processICCStatus(iccStatus);
+    do_check_eq(ril.cardState, geckoCardState);
+  }
+
+  // Test GSM personalization state.
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK,
+                      GECKO_CARDSTATE_NETWORK_LOCKED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
+                      GECKO_CARDSTATE_CORPORATE_LOCKED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
+                      GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
+                      GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
+                      GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
+                      GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_READY,
+                      GECKO_CARDSTATE_PERSONALIZATION_READY);
+
+  // Test CDMA personalization state.
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
+                      GECKO_CARDSTATE_NETWORK1_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
+                      GECKO_CARDSTATE_NETWORK2_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
+                      GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
+                      GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
+                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
+                      GECKO_CARDSTATE_RUIM_LOCKED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
+                      GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
+                      GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
+                      GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
+                      GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
+                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
+  testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
+                      GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
+
+  run_next_test();
+});
+
+/**
+ * Verify SIM app_state in _processICCStatus
+ */
+add_test(function test_card_app_state() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+
+  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
+
+  function testCardAppState(cardAppState, geckoCardState) {
+    let iccStatus = {
+      cardState: CARD_STATE_PRESENT,
+      gsmUmtsSubscriptionAppIndex: 0,
+      apps: [
+      {
+        app_state: cardAppState
+      }],
+    };
+
+    ril._processICCStatus(iccStatus);
+    do_check_eq(ril.cardState, geckoCardState);
+  }
+
+  testCardAppState(CARD_APPSTATE_ILLEGAL,
+                   GECKO_CARDSTATE_ILLEGAL);
+  testCardAppState(CARD_APPSTATE_PIN,
+                   GECKO_CARDSTATE_PIN_REQUIRED);
+  testCardAppState(CARD_APPSTATE_PUK,
+                   GECKO_CARDSTATE_PUK_REQUIRED);
+  testCardAppState(CARD_APPSTATE_READY,
+                   GECKO_CARDSTATE_READY);
+  testCardAppState(CARD_APPSTATE_UNKNOWN,
+                   GECKO_CARDSTATE_UNKNOWN);
+  testCardAppState(CARD_APPSTATE_DETECTED,
+                   GECKO_CARDSTATE_UNKNOWN);
+
+  run_next_test();
+});
+
+/**
+ * Verify permanent blocked for ICC.
+ */
+add_test(function test_icc_permanent_blocked() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+
+  context.ICCRecordHelper.readICCID = function fakeReadICCID() {};
+
+  function testPermanentBlocked(pin1_replaced, universalPINState, pin1) {
+    let iccStatus = {
+      cardState: CARD_STATE_PRESENT,
+      gsmUmtsSubscriptionAppIndex: 0,
+      universalPINState: universalPINState,
+      apps: [
+      {
+        pin1_replaced: pin1_replaced,
+        pin1: pin1
+      }]
+    };
+
+    ril._processICCStatus(iccStatus);
+    do_check_eq(ril.cardState, GECKO_CARDSTATE_PERMANENT_BLOCKED);
+  }
+
+  testPermanentBlocked(1,
+                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
+                       CARD_PINSTATE_UNKNOWN);
+  testPermanentBlocked(1,
+                       CARD_PINSTATE_ENABLED_PERM_BLOCKED,
+                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
+  testPermanentBlocked(0,
+                       CARD_PINSTATE_UNKNOWN,
+                       CARD_PINSTATE_ENABLED_PERM_BLOCKED);
+
+  run_next_test();
+});
+
+/**
+ * Verify iccSetCardLock - Facility Lock.
+ */
+add_test(function test_set_icc_card_lock_facility_lock() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let aid = "123456789";
+  let ril = context.RIL;
+  ril.aid = aid;
+  ril.v5Legacy = false;
+  let buf = context.Buf;
+
+  let GECKO_CARDLOCK_TO_FACILITIY_LOCK = {};
+  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_PIN] = ICC_CB_FACILITY_SIM;
+  GECKO_CARDLOCK_TO_FACILITIY_LOCK[GECKO_CARDLOCK_FDN] = ICC_CB_FACILITY_FDN;
+
+  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_PIN] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_FDN] = "pin2";
+
+  const pin = "1234";
+  const pin2 = "4321";
+  let GECKO_CARDLOCK_TO_PASSWORD = {};
+  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_PIN] = pin;
+  GECKO_CARDLOCK_TO_PASSWORD[GECKO_CARDLOCK_FDN] = pin2;
+
+  const serviceClass = ICC_SERVICE_CLASS_VOICE |
+                       ICC_SERVICE_CLASS_DATA  |
+                       ICC_SERVICE_CLASS_FAX;
+
+  function do_test(aLock, aPassword, aEnabled) {
+    buf.sendParcel = function fakeSendParcel () {
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_SET_FACILITY_LOCK);
+
+      // Token : we don't care
+      this.readInt32();
+
+      let parcel = this.readStringList();
+      do_check_eq(parcel.length, 5);
+      do_check_eq(parcel[0], GECKO_CARDLOCK_TO_FACILITIY_LOCK[aLock]);
+      do_check_eq(parcel[1], aEnabled ? "1" : "0");
+      do_check_eq(parcel[2], GECKO_CARDLOCK_TO_PASSWORD[aLock]);
+      do_check_eq(parcel[3], serviceClass.toString());
+      do_check_eq(parcel[4], aid);
+    };
+
+    let lock = {lockType: aLock,
+                enabled: aEnabled};
+    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
+
+    ril.iccSetCardLock(lock);
+  }
+
+  do_test(GECKO_CARDLOCK_PIN, pin, true);
+  do_test(GECKO_CARDLOCK_PIN, pin, false);
+  do_test(GECKO_CARDLOCK_FDN, pin2, true);
+  do_test(GECKO_CARDLOCK_FDN, pin2, false);
+
+  run_next_test();
+});
+
+/**
+ * Verify iccUnlockCardLock.
+ */
+add_test(function test_unlock_card_lock_corporateLocked() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+  let buf = context.Buf;
+  const pin = "12345678";
+  const puk = "12345678";
+
+  let GECKO_CARDLOCK_TO_PASSWORD_TYPE = {};
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK] = "pin";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK1_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_NCK2_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_HNCK_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_CCK_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_SPCK_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RCCK_PUK] = "puk";
+  GECKO_CARDLOCK_TO_PASSWORD_TYPE[GECKO_CARDLOCK_RSPCK_PUK] = "puk";
+
+  function do_test(aLock, aPassword) {
+    buf.sendParcel = function fakeSendParcel () {
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE);
+
+      // Token : we don't care
+      this.readInt32();
+
+      let lockType = GECKO_PERSO_LOCK_TO_CARD_PERSO_LOCK[aLock];
+      // Lock Type
+      do_check_eq(this.readInt32(), lockType);
+
+      // Pin/Puk.
+      do_check_eq(this.readString(), aPassword);
+    };
+
+    let lock = {lockType: aLock};
+    lock[GECKO_CARDLOCK_TO_PASSWORD_TYPE[aLock]] = aPassword;
+    ril.iccUnlockCardLock(lock);
+  }
+
+  do_test(GECKO_CARDLOCK_NCK, pin);
+  do_test(GECKO_CARDLOCK_NCK1, pin);
+  do_test(GECKO_CARDLOCK_NCK2, pin);
+  do_test(GECKO_CARDLOCK_HNCK, pin);
+  do_test(GECKO_CARDLOCK_CCK, pin);
+  do_test(GECKO_CARDLOCK_SPCK, pin);
+  do_test(GECKO_CARDLOCK_RCCK, pin);
+  do_test(GECKO_CARDLOCK_RSPCK, pin);
+  do_test(GECKO_CARDLOCK_NCK_PUK, puk);
+  do_test(GECKO_CARDLOCK_NCK1_PUK, puk);
+  do_test(GECKO_CARDLOCK_NCK2_PUK, puk);
+  do_test(GECKO_CARDLOCK_HNCK_PUK, puk);
+  do_test(GECKO_CARDLOCK_CCK_PUK, puk);
+  do_test(GECKO_CARDLOCK_SPCK_PUK, puk);
+  do_test(GECKO_CARDLOCK_RCCK_PUK, puk);
+  do_test(GECKO_CARDLOCK_RSPCK_PUK, puk);
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_GsmPDUHelper.js
@@ -0,0 +1,79 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify GsmPDUHelper.writeTimestamp
+ */
+add_test(function test_write_timestamp() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+
+  // current date
+  let dateInput = new Date();
+  let dateOutput = new Date();
+  helper.writeTimestamp(dateInput);
+  dateOutput.setTime(helper.readTimestamp());
+
+  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
+  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
+  do_check_eq(dateInput.getDate(), dateOutput.getDate());
+  do_check_eq(dateInput.getHours(), dateOutput.getHours());
+  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
+  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
+  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
+
+  // 2034-01-23 12:34:56 -0800 GMT
+  let time = Date.UTC(2034, 1, 23, 12, 34, 56);
+  time = time - (8 * 60 * 60 * 1000);
+  dateInput.setTime(time);
+  helper.writeTimestamp(dateInput);
+  dateOutput.setTime(helper.readTimestamp());
+
+  do_check_eq(dateInput.getFullYear(), dateOutput.getFullYear());
+  do_check_eq(dateInput.getMonth(), dateOutput.getMonth());
+  do_check_eq(dateInput.getDate(), dateOutput.getDate());
+  do_check_eq(dateInput.getHours(), dateOutput.getHours());
+  do_check_eq(dateInput.getMinutes(), dateOutput.getMinutes());
+  do_check_eq(dateInput.getSeconds(), dateOutput.getSeconds());
+  do_check_eq(dateInput.getTimezoneOffset(), dateOutput.getTimezoneOffset());
+
+  run_next_test();
+});
+
+/**
+ * Verify GsmPDUHelper.octectToBCD and GsmPDUHelper.BCDToOctet
+ */
+add_test(function test_octect_BCD() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+
+  // 23
+  let number = 23;
+  let octet = helper.BCDToOctet(number);
+  do_check_eq(helper.octetToBCD(octet), number);
+
+  // 56
+  number = 56;
+  octet = helper.BCDToOctet(number);
+  do_check_eq(helper.octetToBCD(octet), number);
+
+  // 0x23
+  octet = 0x23;
+  number = helper.octetToBCD(octet);
+  do_check_eq(helper.BCDToOctet(number), octet);
+
+  // 0x56
+  octet = 0x56;
+  number = helper.octetToBCD(octet);
+  do_check_eq(helper.BCDToOctet(number), octet);
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCContactHelper.js
@@ -0,0 +1,590 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Test error message returned in onerror for readICCContacts.
+ */
+add_test(function test_error_message_read_icc_contact () {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+
+  function do_test(options, expectedErrorMsg) {
+    ril.sendChromeMessage = function(message) {
+      do_check_eq(message.errorMsg, expectedErrorMsg);
+    }
+    ril.readICCContacts(options);
+  }
+
+  // Error 1, didn't specify correct contactType.
+  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
+
+  // Error 2, specifying a non-supported contactType.
+  ril.appType = CARD_APPTYPE_USIM;
+  do_test({contactType: "sdn"}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
+
+  // Error 3, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
+  // but forget to add implemenetations for it.
+  USIM_PBR_FIELDS.push("pbc");
+  do_test({contactType: "adn"}, CONTACT_ERR_FIELD_NOT_SUPPORTED);
+
+  run_next_test();
+});
+
+/**
+ * Test error message returned in onerror for updateICCContact.
+ */
+add_test(function test_error_message_update_icc_contact() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+
+  const ICCID = "123456789";
+  ril.iccInfo.iccid = ICCID;
+
+  function do_test(options, expectedErrorMsg) {
+    ril.sendChromeMessage = function(message) {
+      do_check_eq(message.errorMsg, expectedErrorMsg);
+    }
+    ril.updateICCContact(options);
+  }
+
+  // Error 1, didn't specify correct contactType.
+  do_test({}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
+
+  // Error 2, specifying a correct contactType, but without providing 'contact'.
+  do_test({contactType: "adn"}, CONTACT_ERR_REQUEST_NOT_SUPPORTED);
+
+  // Error 3, specifying a non-supported contactType.
+  ril.appType = CARD_APPTYPE_USIM;
+  do_test({contactType: "sdn", contact: {}}, CONTACT_ERR_CONTACT_TYPE_NOT_SUPPORTED);
+
+  // Error 4, without supplying pin2.
+  do_test({contactType: "fdn", contact: {contactId: ICCID + "1"}}, GECKO_ERROR_SIM_PIN2);
+
+  // Error 5, No free record found in EF_ADN.
+  let record = context.ICCRecordHelper;
+  record.readPBR = function(onsuccess, onerror) {
+    onsuccess([{adn: {fileId: 0x4f3a}}]);
+  };
+
+  let io = context.ICCIOHelper;
+  io.loadLinearFixedEF = function(options) {
+    options.totalRecords = 1;
+    options.p1 = 1;
+    options.callback(options);
+  };
+
+  do_test({contactType: "adn", contact: {}}, CONTACT_ERR_NO_FREE_RECORD_FOUND);
+
+  // Error 6, ICC IO Error.
+  io.loadLinearFixedEF = function(options) {
+    ril[REQUEST_SIM_IO](0, {rilRequestError: ERROR_GENERIC_FAILURE});
+  };
+  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
+          GECKO_ERROR_GENERIC_FAILURE);
+
+  // Error 7, suppose we update the supported PBR fields in USIM_PBR_FIELDS,
+  // but forget to add implemenetations for it.
+  USIM_PBR_FIELDS.push("pbc");
+  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
+          CONTACT_ERR_FIELD_NOT_SUPPORTED);
+
+  // Error 8, EF_PBR doesn't exist.
+  record.readPBR = function(onsuccess, onerror) {
+    onsuccess([]);
+  };
+
+  do_test({contactType: "adn", contact: {contactId: ICCID + "1"}},
+          CONTACT_ERR_CANNOT_ACCESS_PHONEBOOK);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCContactHelper.readICCContacts
+ */
+add_test(function test_read_icc_contacts() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let record = context.ICCRecordHelper;
+  let contactHelper = context.ICCContactHelper;
+  let ril = context.RIL;
+
+  function do_test(aSimType, aContactType, aExpectedContact, aEnhancedPhoneBook) {
+    ril.appType = aSimType;
+    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
+    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ?
+                                    [0x0, 0x0C, 0x0, 0x0, 0x0]:
+                                    [0x0, 0x00, 0x0, 0x0, 0x0];
+
+    // Override some functions to test.
+    contactHelper.getContactFieldRecordId = function(pbr, contact, field, onsuccess, onerror) {
+      onsuccess(1);
+    };
+
+    record.readPBR = function readPBR(onsuccess, onerror) {
+      onsuccess([{adn:{fileId: 0x6f3a}, email: {}, anr0: {}}]);
+    };
+
+    record.readADNLike = function readADNLike(fileId, onsuccess, onerror) {
+      onsuccess([{recordId: 1, alphaId: "name", number: "111111"}])
+    };
+
+    record.readEmail = function readEmail(fileId, fileType, recordNumber, onsuccess, onerror) {
+      onsuccess("hello@mail.com");
+    };
+
+    record.readANR = function readANR(fileId, fileType, recordNumber, onsuccess, onerror) {
+      onsuccess("123456");
+    };
+
+    let onsuccess = function onsuccess(contacts) {
+      let contact = contacts[0];
+      for (let key in contact) {
+        do_print("check " + key);
+        if (Array.isArray(contact[key])) {
+          do_check_eq(contact[key][0], aExpectedContact[key]);
+        } else {
+          do_check_eq(contact[key], aExpectedContact[key]);
+        }
+      }
+    };
+
+    let onerror = function onerror(errorMsg) {
+      do_print("readICCContacts failed: " + errorMsg);
+      do_check_true(false);
+    };
+
+    contactHelper.readICCContacts(aSimType, aContactType, onsuccess, onerror);
+  }
+
+  let expectedContact1 = {
+    pbrIndex: 0,
+    recordId: 1,
+    alphaId:  "name",
+    number:   "111111"
+  };
+
+  let expectedContact2 = {
+    pbrIndex: 0,
+    recordId: 1,
+    alphaId:  "name",
+    number:   "111111",
+    email:    "hello@mail.com",
+    anr:      "123456"
+  };
+
+  // SIM
+  do_print("Test read SIM adn contacts");
+  do_test(CARD_APPTYPE_SIM, "adn", expectedContact1);
+
+  do_print("Test read SIM fdn contacts");
+  do_test(CARD_APPTYPE_SIM, "fdn", expectedContact1);
+
+  // USIM
+  do_print("Test read USIM adn contacts");
+  do_test(CARD_APPTYPE_USIM, "adn", expectedContact2);
+
+  do_print("Test read USIM fdn contacts");
+  do_test(CARD_APPTYPE_USIM, "fdn", expectedContact1);
+
+  // RUIM
+  do_print("Test read RUIM adn contacts");
+  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact1);
+
+  do_print("Test read RUIM fdn contacts");
+  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1);
+
+  // RUIM with enhanced phone book
+  do_print("Test read RUIM adn contacts with enhanced phone book");
+  do_test(CARD_APPTYPE_RUIM, "adn", expectedContact2, true);
+
+  do_print("Test read RUIM fdn contacts with enhanced phone book");
+  do_test(CARD_APPTYPE_RUIM, "fdn", expectedContact1, true);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCContactHelper.updateICCContact with appType is CARD_APPTYPE_USIM.
+ */
+add_test(function test_update_icc_contact() {
+  const ADN_RECORD_ID   = 100;
+  const ADN_SFI         = 1;
+  const IAP_FILE_ID     = 0x4f17;
+  const EMAIL_FILE_ID   = 0x4f50;
+  const EMAIL_RECORD_ID = 20;
+  const ANR0_FILE_ID    = 0x4f11;
+  const ANR0_RECORD_ID  = 30;
+
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let recordHelper = context.ICCRecordHelper;
+  let contactHelper = context.ICCContactHelper;
+  let ril = context.RIL;
+
+  function do_test(aSimType, aContactType, aContact, aPin2, aFileType, aHaveIapIndex, aEnhancedPhoneBook) {
+    ril.appType = aSimType;
+    ril._isCdma = (aSimType === CARD_APPTYPE_RUIM);
+    ril.iccInfoPrivate.cst = (aEnhancedPhoneBook) ? [0x0, 0x0C, 0x0, 0x0, 0x0]
+                                                  : [0x0, 0x00, 0x0, 0x0, 0x0];
+
+    recordHelper.readPBR = function(onsuccess, onerror) {
+      if (aFileType === ICC_USIM_TYPE1_TAG) {
+        onsuccess([{
+          adn:   {fileId: ICC_EF_ADN},
+          email: {fileId: EMAIL_FILE_ID,
+                  fileType: ICC_USIM_TYPE1_TAG},
+          anr0:  {fileId: ANR0_FILE_ID,
+                  fileType: ICC_USIM_TYPE1_TAG}
+        }]);
+      } else if (aFileType === ICC_USIM_TYPE2_TAG) {
+        onsuccess([{
+          adn:   {fileId: ICC_EF_ADN,
+                  sfi: ADN_SFI},
+          iap:   {fileId: IAP_FILE_ID},
+          email: {fileId: EMAIL_FILE_ID,
+                  fileType: ICC_USIM_TYPE2_TAG,
+                  indexInIAP: 0},
+          anr0:  {fileId: ANR0_FILE_ID,
+                  fileType: ICC_USIM_TYPE2_TAG,
+                  indexInIAP: 1}
+        }]);
+      }
+    };
+
+    recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
+      if (aContactType === "fdn") {
+        do_check_eq(fileId, ICC_EF_FDN);
+      } else if (aContactType === "adn") {
+        do_check_eq(fileId, ICC_EF_ADN);
+      }
+      do_check_eq(pin2, aPin2);
+      do_check_eq(contact.alphaId, aContact.alphaId);
+      do_check_eq(contact.number, aContact.number);
+      onsuccess();
+    };
+
+    recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
+      do_check_eq(fileId, IAP_FILE_ID);
+      do_check_eq(recordNumber, ADN_RECORD_ID);
+      onsuccess((aHaveIapIndex) ? [EMAIL_RECORD_ID, ANR0_RECORD_ID]
+                                : [0xff, 0xff]);
+    };
+
+    recordHelper.updateIAP = function(fileId, recordNumber, iap, onsuccess, onerror) {
+      do_check_eq(fileId, IAP_FILE_ID);
+      do_check_eq(recordNumber, ADN_RECORD_ID);
+      onsuccess();
+    };
+
+    recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
+      do_check_eq(pbr.email.fileId, EMAIL_FILE_ID);
+      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
+        do_check_eq(recordNumber, ADN_RECORD_ID);
+      } else if (pbr.email.fileType === ICC_USIM_TYPE2_TAG) {
+        do_check_eq(recordNumber, EMAIL_RECORD_ID);
+      }
+      do_check_eq(email, aContact.email);
+      onsuccess();
+    };
+
+    recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
+      do_check_eq(pbr.anr0.fileId, ANR0_FILE_ID);
+      if (pbr.anr0.fileType === ICC_USIM_TYPE1_TAG) {
+        do_check_eq(recordNumber, ADN_RECORD_ID);
+      } else if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
+        do_check_eq(recordNumber, ANR0_RECORD_ID);
+      }
+      if (Array.isArray(aContact.anr)) {
+        do_check_eq(number, aContact.anr[0]);
+      }
+      onsuccess();
+    };
+
+    recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
+      let recordId = 0;
+      if (fileId === EMAIL_FILE_ID) {
+        recordId = EMAIL_RECORD_ID;
+      } else if (fileId === ANR0_FILE_ID) {
+        recordId = ANR0_RECORD_ID;
+      }
+      onsuccess(recordId);
+    };
+
+    let isSuccess = false;
+    let onsuccess = function onsuccess() {
+      do_print("updateICCContact success");
+      isSuccess = true;
+    };
+
+    let onerror = function onerror(errorMsg) {
+      do_print("updateICCContact failed: " + errorMsg);
+    };
+
+    contactHelper.updateICCContact(aSimType, aContactType, aContact, aPin2, onsuccess, onerror);
+    do_check_true(isSuccess);
+  }
+
+  let contacts = [
+    {
+      pbrIndex: 0,
+      recordId: ADN_RECORD_ID,
+      alphaId:  "test",
+      number:   "123456",
+      email:    "test@mail.com",
+      anr:      ["+654321"]
+    },
+    // a contact without email and anr.
+    {
+      pbrIndex: 0,
+      recordId: ADN_RECORD_ID,
+      alphaId:  "test2",
+      number:   "123456",
+    },
+    // a contact with email but no anr.
+    {
+      pbrIndex: 0,
+      recordId: ADN_RECORD_ID,
+      alphaId:  "test3",
+      number:   "123456",
+      email:    "test@mail.com"
+    },
+    // a contact with anr but no email.
+    {
+      pbrIndex: 0,
+      recordId: ADN_RECORD_ID,
+      alphaId:  "test4",
+      number:   "123456",
+      anr:      ["+654321"]
+    }];
+
+  for (let i = 0; i < contacts.length; i++) {
+    let contact = contacts[i];
+    // SIM
+    do_print("Test update SIM adn contacts");
+    do_test(CARD_APPTYPE_SIM, "adn", contact);
+
+    do_print("Test update SIM fdn contacts");
+    do_test(CARD_APPTYPE_SIM, "fdn", contact, "1234");
+
+    // USIM
+    do_print("Test update USIM adn contacts");
+    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE1_TAG);
+    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true);
+    do_test(CARD_APPTYPE_USIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false);
+
+    do_print("Test update USIM fdn contacts");
+    do_test(CARD_APPTYPE_USIM, "fdn", contact, "1234");
+
+    // RUIM
+    do_print("Test update RUIM adn contacts");
+    do_test(CARD_APPTYPE_RUIM, "adn", contact);
+
+    do_print("Test update RUIM fdn contacts");
+    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234");
+
+    // RUIM with enhanced phone book
+    do_print("Test update RUIM adn contacts with enhanced phone book");
+    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE1_TAG, null, true);
+    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, true, true);
+    do_test(CARD_APPTYPE_RUIM, "adn", contact, null, ICC_USIM_TYPE2_TAG, false, true);
+
+    do_print("Test update RUIM fdn contacts with enhanced phone book");
+    do_test(CARD_APPTYPE_RUIM, "fdn", contact, "1234", null, true);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify updateICCContact with removal of anr and email with File Type 1.
+ */
+add_test(function test_update_icc_contact_with_remove_type1_attr() {
+  const ADN_RECORD_ID   = 100;
+  const IAP_FILE_ID     = 0x4f17;
+  const EMAIL_FILE_ID   = 0x4f50;
+  const EMAIL_RECORD_ID = 20;
+  const ANR0_FILE_ID    = 0x4f11;
+  const ANR0_RECORD_ID  = 30;
+
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let recordHelper = context.ICCRecordHelper;
+  let contactHelper = context.ICCContactHelper;
+
+  recordHelper.updateADNLike = function(fileId, contact, pin2, onsuccess, onerror) {
+    onsuccess();
+  };
+
+  let contact = {
+    pbrIndex: 0,
+    recordId: ADN_RECORD_ID,
+    alphaId:  "test2",
+    number:   "123456",
+  };
+
+  recordHelper.readIAP = function(fileId, recordNumber, onsuccess, onerror) {
+    onsuccess([EMAIL_RECORD_ID, ANR0_RECORD_ID]);
+  };
+
+  recordHelper.updateEmail = function(pbr, recordNumber, email, adnRecordId, onsuccess, onerror) {
+    do_check_true(email == null);
+    onsuccess();
+  };
+
+  recordHelper.updateANR = function(pbr, recordNumber, number, adnRecordId, onsuccess, onerror) {
+    do_check_true(number == null);
+    onsuccess();
+  };
+
+  function do_test(type) {
+    recordHelper.readPBR = function(onsuccess, onerror) {
+      if (type == ICC_USIM_TYPE1_TAG) {
+        onsuccess([{
+          adn:   {fileId: ICC_EF_ADN},
+          email: {fileId: EMAIL_FILE_ID,
+                  fileType: ICC_USIM_TYPE1_TAG},
+          anr0:  {fileId: ANR0_FILE_ID,
+                  fileType: ICC_USIM_TYPE1_TAG}}]);
+      } else {
+        onsuccess([{
+          adn:   {fileId: ICC_EF_ADN},
+          iap:   {fileId: IAP_FILE_ID},
+          email: {fileId: EMAIL_FILE_ID,
+                  fileType: ICC_USIM_TYPE2_TAG,
+                  indexInIAP: 0},
+          anr0:  {fileId: ANR0_FILE_ID,
+                  fileType: ICC_USIM_TYPE2_TAG,
+                  indexInIAP: 1}}]);
+      }
+    };
+
+    let successCb = function() {
+      do_check_true(true);
+    };
+
+    let errorCb = function(errorMsg) {
+      do_print(errorMsg);
+      do_check_true(false);
+    };
+
+    contactHelper.updateICCContact(CARD_APPTYPE_USIM, "adn", contact, null, successCb, errorCb);
+  }
+
+  do_test(ICC_USIM_TYPE1_TAG);
+  do_test(ICC_USIM_TYPE2_TAG);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCContactHelper.findFreeICCContact in SIM
+ */
+add_test(function test_find_free_icc_contact_sim() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let recordHelper = context.ICCRecordHelper;
+  let contactHelper = context.ICCContactHelper;
+  // Correct record Id starts with 1, so put a null element at index 0.
+  let records = [null];
+  const MAX_RECORDS = 3;
+  const PBR_INDEX = 0;
+
+  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
+    if (records.length > MAX_RECORDS) {
+      onerror("No free record found.");
+      return;
+    }
+
+    onsuccess(records.length);
+  };
+
+  let successCb = function(pbrIndex, recordId) {
+    do_check_eq(pbrIndex, PBR_INDEX);
+    records[recordId] = {};
+  };
+
+  let errorCb = function(errorMsg) {
+    do_print(errorMsg);
+    do_check_true(false);
+  };
+
+  for (let i = 0; i < MAX_RECORDS; i++) {
+    contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
+  }
+  // The 1st element, records[0], is null.
+  do_check_eq(records.length - 1, MAX_RECORDS);
+
+  // Now the EF is full, so finding a free one should result failure.
+  successCb = function(pbrIndex, recordId) {
+    do_check_true(false);
+  };
+
+  errorCb = function(errorMsg) {
+    do_check_true(errorMsg === "No free record found.");
+  };
+  contactHelper.findFreeICCContact(CARD_APPTYPE_SIM, "adn", successCb, errorCb);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCContactHelper.findFreeICCContact in USIM
+ */
+add_test(function test_find_free_icc_contact_usim() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let recordHelper = context.ICCRecordHelper;
+  let contactHelper = context.ICCContactHelper;
+  const ADN1_FILE_ID = 0x6f3a;
+  const ADN2_FILE_ID = 0x6f3b;
+  const MAX_RECORDS = 3;
+
+  // The adn in the first phonebook set has already two records, which means
+  // only 1 free record remained.
+  let pbrs = [{adn: {fileId: ADN1_FILE_ID, records: [null, {}, {}]}},
+              {adn: {fileId: ADN2_FILE_ID, records: [null]}}];
+
+  recordHelper.readPBR = function readPBR(onsuccess, onerror) {
+    onsuccess(pbrs);
+  };
+
+  recordHelper.findFreeRecordId = function(fileId, onsuccess, onerror) {
+    let pbr = (fileId == ADN1_FILE_ID ? pbrs[0]: pbrs[1]);
+    if (pbr.adn.records.length > MAX_RECORDS) {
+      onerror("No free record found.");
+      return;
+    }
+
+    onsuccess(pbr.adn.records.length);
+  };
+
+  let successCb = function(pbrIndex, recordId) {
+    do_check_eq(pbrIndex, 0);
+    pbrs[pbrIndex].adn.records[recordId] = {};
+  };
+
+  let errorCb = function(errorMsg) {
+    do_check_true(false);
+  };
+
+  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
+
+  // Now the EF_ADN in the 1st phonebook set is full, so the next free contact
+  // will come from the 2nd phonebook set.
+  successCb = function(pbrIndex, recordId) {
+    do_check_eq(pbrIndex, 1);
+    do_check_eq(recordId, 1);
+  }
+  contactHelper.findFreeICCContact(CARD_APPTYPE_USIM, "adn", successCb, errorCb);
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCIOHelper.js
@@ -0,0 +1,164 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify ICCIOHelper.loadLinearFixedEF with recordSize.
+ */
+add_test(function test_load_linear_fixed_ef() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+  let io = context.ICCIOHelper;
+
+  io.getResponse = function fakeGetResponse(options) {
+    // When recordSize is provided, loadLinearFixedEF should call iccIO directly.
+    do_check_true(false);
+    run_next_test();
+  };
+
+  ril.iccIO = function fakeIccIO(options) {
+    do_check_true(true);
+    run_next_test();
+  };
+
+  io.loadLinearFixedEF({recordSize: 0x20});
+});
+
+/**
+ * Verify ICCIOHelper.loadLinearFixedEF without recordSize.
+ */
+add_test(function test_load_linear_fixed_ef() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+  let io = context.ICCIOHelper;
+
+  io.getResponse = function fakeGetResponse(options) {
+    do_check_true(true);
+    run_next_test();
+  };
+
+  ril.iccIO = function fakeIccIO(options) {
+    // When recordSize is not provided, loadLinearFixedEF should call getResponse.
+    do_check_true(false);
+    run_next_test();
+  };
+
+  io.loadLinearFixedEF({});
+});
+
+/**
+ * Verify ICCIOHelper.processICCIOError.
+ */
+add_test(function test_process_icc_io_error() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ioHelper = context.ICCIOHelper;
+
+  function do_test(errorCode, expectedErrorMsg) {
+    let called = false;
+    function errorCb(errorMsg) {
+      called = true;
+      do_check_eq(errorMsg, expectedErrorMsg);
+    }
+
+    ioHelper.processICCIOError({rilRequestError: errorCode,
+                                fileId: 0xffff,
+                                command: 0xff,
+                                sw1: 0xff,
+                                sw2: 0xff,
+                                onerror: errorCb});
+    do_check_true(called);
+  }
+
+  for (let i = 0; i < ERROR_REJECTED_BY_REMOTE + 1; i++) {
+    do_test(i, RIL_ERROR_TO_GECKO_ERROR[i]);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_TRANSPARENT.
+ */
+add_test(function test_icc_io_get_response_for_transparent_structure() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let buf = context.Buf;
+  let iccioHelper = context.ICCIOHelper;
+  let pduHelper = context.GsmPDUHelper;
+
+  let responseArray = [
+    // SIM response.
+    [0x00, 0x00, 0x00, 0x0A, 0x2F, 0xE2, 0x04, 0x00, 0x0A, 0xA0, 0xAA, 0x00,
+     0x02, 0x00, 0x00],
+    // USIM response.
+    [0x62, 0x22, 0x82, 0x02, 0x41, 0x21, 0x83, 0x02, 0x2F, 0xE2, 0xA5, 0x09,
+     0xC1, 0x04, 0x40, 0x0F, 0xF5, 0x55, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x05,
+     0x8B, 0x03, 0x2F, 0x06, 0x0B, 0x80, 0x02, 0x00, 0x0A, 0x88, 0x01, 0x10]
+  ];
+
+  for (let i = 0; i < responseArray.length; i++) {
+    let strLen = responseArray[i].length * 2;
+    buf.writeInt32(strLen);
+    for (let j = 0; j < responseArray[i].length; j++) {
+      pduHelper.writeHexOctet(responseArray[i][j]);
+    }
+    buf.writeStringDelimiter(strLen);
+
+    let options = {fileId: ICC_EF_ICCID,
+                   type: EF_TYPE_TRANSPARENT};
+    iccioHelper.processICCIOGetResponse(options);
+
+    do_check_eq(options.fileSize, 0x0A);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCIOHelper.processICCIOGetResponse for EF_TYPE_LINEAR_FIXED.
+ */
+add_test(function test_icc_io_get_response_for_linear_fixed_structure() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let buf = context.Buf;
+  let iccioHelper = context.ICCIOHelper;
+  let pduHelper = context.GsmPDUHelper;
+
+  let responseArray = [
+    // SIM response.
+    [0x00, 0x00, 0x00, 0x1A, 0x6F, 0x40, 0x04, 0x00, 0x11, 0xA0, 0xAA, 0x00,
+     0x02, 0x01, 0x1A],
+    // USIM response.
+    [0x62, 0x1E, 0x82, 0x05, 0x42, 0x21, 0x00, 0x1A, 0x01, 0x83, 0x02, 0x6F,
+     0x40, 0xA5, 0x03, 0x92, 0x01, 0x00, 0x8A, 0x01, 0x07, 0x8B, 0x03, 0x6F,
+     0x06, 0x02, 0x80, 0x02, 0x00, 0x1A, 0x88, 0x00]
+  ];
+
+  for (let i = 0; i < responseArray.length; i++) {
+    let strLen = responseArray[i].length * 2;
+    buf.writeInt32(strLen);
+    for (let j = 0; j < responseArray[i].length; j++) {
+      pduHelper.writeHexOctet(responseArray[i][j]);
+    }
+    buf.writeStringDelimiter(strLen);
+
+    let options = {fileId: ICC_EF_MSISDN,
+                   type: EF_TYPE_LINEAR_FIXED};
+    iccioHelper.processICCIOGetResponse(options);
+
+    do_check_eq(options.fileSize, 0x1A);
+    do_check_eq(options.recordSize, 0x1A);
+    do_check_eq(options.totalRecords, 0x01);
+  }
+
+  run_next_test();
+});
+
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
@@ -0,0 +1,520 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify ICCPDUHelper#readICCUCS2String()
+ */
+add_test(function test_read_icc_ucs2_string() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+
+  // 0x80
+  let text = "TEST";
+  helper.writeUCS2String(text);
+  // Also write two unused octets.
+  let ffLen = 2;
+  for (let i = 0; i < ffLen; i++) {
+    helper.writeHexOctet(0xff);
+  }
+  do_check_eq(iccHelper.readICCUCS2String(0x80, (2 * text.length) + ffLen), text);
+
+  // 0x81
+  let array = [0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca,
+               0xff, 0xff];
+  let len = array.length;
+  for (let i = 0; i < len; i++) {
+    helper.writeHexOctet(array[i]);
+  }
+  do_check_eq(iccHelper.readICCUCS2String(0x81, len), "Mozilla\u694a");
+
+  // 0x82
+  let array2 = [0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61,
+                0xca, 0xff, 0xff];
+  let len2 = array2.length;
+  for (let i = 0; i < len2; i++) {
+    helper.writeHexOctet(array2[i]);
+  }
+  do_check_eq(iccHelper.readICCUCS2String(0x82, len2), "Mozilla\u694a");
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper#readDiallingNumber
+ */
+add_test(function test_read_dialling_number() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  let str = "123456789";
+
+  helper.readHexOctet = function() {
+    return 0x81;
+  };
+
+  helper.readSwappedNibbleBcdString = function(len) {
+    return str.substring(0, len);
+  };
+
+  for (let i = 0; i < str.length; i++) {
+    do_check_eq(str.substring(0, i - 1), // -1 for the TON
+                iccHelper.readDiallingNumber(i));
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper#read8BitUnpackedToString
+ */
+add_test(function test_read_8bit_unpacked_to_string() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+
+  // Test 1: Read GSM alphabets.
+  // Write alphabets before ESCAPE.
+  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
+    helper.writeHexOctet(i);
+  }
+
+  // Write two ESCAPEs to make it become ' '.
+  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
+  helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
+
+  for (let i = PDU_NL_EXTENDED_ESCAPE + 1; i < langTable.length; i++) {
+    helper.writeHexOctet(i);
+  }
+
+  // Also write two unused fields.
+  let ffLen = 2;
+  for (let i = 0; i < ffLen; i++) {
+    helper.writeHexOctet(0xff);
+  }
+
+  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_EXTENDED_ESCAPE),
+              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
+  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
+  do_check_eq(iccHelper.read8BitUnpackedToString(langTable.length -
+                                              PDU_NL_EXTENDED_ESCAPE - 1 + ffLen),
+              langTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
+
+  // Test 2: Read GSM extended alphabets.
+  for (let i = 0; i < langShiftTable.length; i++) {
+    helper.writeHexOctet(PDU_NL_EXTENDED_ESCAPE);
+    helper.writeHexOctet(i);
+  }
+
+  // Read string before RESERVED_CONTROL.
+  do_check_eq(iccHelper.read8BitUnpackedToString(PDU_NL_RESERVED_CONTROL  * 2),
+              langShiftTable.substring(0, PDU_NL_RESERVED_CONTROL));
+  // ESCAPE + RESERVED_CONTROL will become ' '.
+  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
+  // Read string between RESERVED_CONTROL and EXTENDED_ESCAPE.
+  do_check_eq(iccHelper.read8BitUnpackedToString(
+                (PDU_NL_EXTENDED_ESCAPE - PDU_NL_RESERVED_CONTROL - 1)  * 2),
+              langShiftTable.substring(PDU_NL_RESERVED_CONTROL + 1,
+                                       PDU_NL_EXTENDED_ESCAPE));
+  // ESCAPE + ESCAPE will become ' '.
+  do_check_eq(iccHelper.read8BitUnpackedToString(2), " ");
+  // Read remaining string.
+  do_check_eq(iccHelper.read8BitUnpackedToString(
+                (langShiftTable.length - PDU_NL_EXTENDED_ESCAPE - 1)  * 2),
+              langShiftTable.substring(PDU_NL_EXTENDED_ESCAPE + 1));
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper#writeStringTo8BitUnpacked.
+ *
+ * Test writing GSM 8 bit alphabets.
+ */
+add_test(function test_write_string_to_8bit_unpacked() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  // Length of trailing 0xff.
+  let ffLen = 2;
+  let str;
+
+  // Test 1, write GSM alphabets.
+  iccHelper.writeStringTo8BitUnpacked(langTable.length + ffLen, langTable);
+
+  for (let i = 0; i < langTable.length; i++) {
+    do_check_eq(helper.readHexOctet(), i);
+  }
+
+  for (let i = 0; i < ffLen; i++) {
+    do_check_eq(helper.readHexOctet(), 0xff);
+  }
+
+  // Test 2, write GSM extended alphabets.
+  str = "\u000c\u20ac";
+  iccHelper.writeStringTo8BitUnpacked(4, str);
+
+  do_check_eq(iccHelper.read8BitUnpackedToString(4), str);
+
+  // Test 3, write GSM and GSM extended alphabets.
+  // \u000c, \u20ac are from gsm extended alphabets.
+  // \u00a3 is from gsm alphabet.
+  str = "\u000c\u20ac\u00a3";
+
+  // 2 octets * 2 = 4 octets for 2 gsm extended alphabets,
+  // 1 octet for 1 gsm alphabet,
+  // 2 octes for trailing 0xff.
+  // "Totally 7 octets are to be written."
+  iccHelper.writeStringTo8BitUnpacked(7, str);
+
+  do_check_eq(iccHelper.read8BitUnpackedToString(7), str);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper#writeStringTo8BitUnpacked with maximum octets written.
+ */
+add_test(function test_write_string_to_8bit_unpacked_with_max_octets_written() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+
+  // The maximum of the number of octets that can be written is 3.
+  // Only 3 characters shall be written even the length of the string is 4.
+  iccHelper.writeStringTo8BitUnpacked(3, langTable.substring(0, 4));
+  helper.writeHexOctet(0xff); // dummy octet.
+  for (let i = 0; i < 3; i++) {
+    do_check_eq(helper.readHexOctet(), i);
+  }
+  do_check_false(helper.readHexOctet() == 4);
+
+  // \u000c is GSM extended alphabet, 2 octets.
+  // \u00a3 is GSM alphabet, 1 octet.
+  let str = "\u000c\u00a3";
+  iccHelper.writeStringTo8BitUnpacked(3, str);
+  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
+
+  str = "\u00a3\u000c";
+  iccHelper.writeStringTo8BitUnpacked(3, str);
+  do_check_eq(iccHelper.read8BitUnpackedToString(3), str);
+
+  // 2 GSM extended alphabets cost 4 octets, but maximum is 3, so only the 1st
+  // alphabet can be written.
+  str = "\u000c\u000c";
+  iccHelper.writeStringTo8BitUnpacked(3, str);
+  helper.writeHexOctet(0xff); // dummy octet.
+  do_check_eq(iccHelper.read8BitUnpackedToString(4), str.substring(0, 1));
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.readAlphaIdentifier
+ */
+add_test(function test_read_alpha_identifier() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+
+  // UCS2: 0x80
+  let text = "TEST";
+  helper.writeHexOctet(0x80);
+  helper.writeUCS2String(text);
+  // Also write two unused octets.
+  let ffLen = 2;
+  for (let i = 0; i < ffLen; i++) {
+    helper.writeHexOctet(0xff);
+  }
+  do_check_eq(iccHelper.readAlphaIdentifier(1 + (2 * text.length) + ffLen), text);
+
+  // UCS2: 0x81
+  let array = [0x81, 0x08, 0xd2, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
+  for (let i = 0; i < array.length; i++) {
+    helper.writeHexOctet(array[i]);
+  }
+  do_check_eq(iccHelper.readAlphaIdentifier(array.length), "Mozilla\u694a");
+
+  // UCS2: 0x82
+  let array2 = [0x82, 0x08, 0x69, 0x00, 0x4d, 0x6f, 0x7a, 0x69, 0x6c, 0x6c, 0x61, 0xca, 0xff, 0xff];
+  for (let i = 0; i < array2.length; i++) {
+    helper.writeHexOctet(array2[i]);
+  }
+  do_check_eq(iccHelper.readAlphaIdentifier(array2.length), "Mozilla\u694a");
+
+  // GSM 8 Bit Unpacked
+  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  for (let i = 0; i < PDU_NL_EXTENDED_ESCAPE; i++) {
+    helper.writeHexOctet(i);
+  }
+  do_check_eq(iccHelper.readAlphaIdentifier(PDU_NL_EXTENDED_ESCAPE),
+              langTable.substring(0, PDU_NL_EXTENDED_ESCAPE));
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.writeAlphaIdentifier
+ */
+add_test(function test_write_alpha_identifier() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  // Length of trailing 0xff.
+  let ffLen = 2;
+
+  // Removal
+  iccHelper.writeAlphaIdentifier(10, null);
+  do_check_eq(iccHelper.readAlphaIdentifier(10), "");
+
+  // GSM 8 bit
+  let str = "Mozilla";
+  iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
+  do_check_eq(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
+
+  // UCS2
+  str = "Mozilla\u694a";
+  iccHelper.writeAlphaIdentifier(str.length * 2 + ffLen, str);
+  // * 2 for each character will be encoded to UCS2 alphabets.
+  do_check_eq(iccHelper.readAlphaIdentifier(str.length * 2 + ffLen), str);
+
+  // Test with maximum octets written.
+  // 1 coding scheme (0x80) and 1 UCS2 character, total 3 octets.
+  str = "\u694a";
+  iccHelper.writeAlphaIdentifier(3, str);
+  do_check_eq(iccHelper.readAlphaIdentifier(3), str);
+
+  // 1 coding scheme (0x80) and 2 UCS2 characters, total 5 octets.
+  // numOctets is limited to 4, so only 1 UCS2 character can be written.
+  str = "\u694a\u694a";
+  iccHelper.writeAlphaIdentifier(4, str);
+  helper.writeHexOctet(0xff); // dummy octet.
+  do_check_eq(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
+
+  // Write 0 octet.
+  iccHelper.writeAlphaIdentifier(0, "1");
+  helper.writeHexOctet(0xff); // dummy octet.
+  do_check_eq(iccHelper.readAlphaIdentifier(1), "");
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.readAlphaIdDiallingNumber
+ */
+add_test(function test_read_alpha_id_dialling_number() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  let buf = context.Buf;
+  const recordSize = 32;
+
+  function testReadAlphaIdDiallingNumber(contact) {
+    iccHelper.readAlphaIdentifier = function() {
+      return contact.alphaId;
+    };
+
+    iccHelper.readNumberWithLength = function() {
+      return contact.number;
+    };
+
+    let strLen = recordSize * 2;
+    buf.writeInt32(strLen);     // fake length
+    helper.writeHexOctet(0xff); // fake CCP
+    helper.writeHexOctet(0xff); // fake EXT1
+    buf.writeStringDelimiter(strLen);
+
+    let contactR = iccHelper.readAlphaIdDiallingNumber(recordSize);
+    if (contact.alphaId == "" && contact.number == "") {
+      do_check_eq(contactR, null);
+    } else {
+      do_check_eq(contactR.alphaId, contact.alphaId);
+      do_check_eq(contactR.number, contact.number);
+    }
+  }
+
+  testReadAlphaIdDiallingNumber({alphaId: "AlphaId", number: "0987654321"});
+  testReadAlphaIdDiallingNumber({alphaId: "", number: ""});
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.writeAlphaIdDiallingNumber
+ */
+add_test(function test_write_alpha_id_dialling_number() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.ICCPDUHelper;
+  const recordSize = 32;
+
+  // Write a normal contact.
+  let contactW = {
+    alphaId: "Mozilla",
+    number: "1234567890"
+  };
+  helper.writeAlphaIdDiallingNumber(recordSize, contactW.alphaId,
+                                    contactW.number);
+
+  let contactR = helper.readAlphaIdDiallingNumber(recordSize);
+  do_check_eq(contactW.alphaId, contactR.alphaId);
+  do_check_eq(contactW.number, contactR.number);
+
+  // Write a contact with alphaId encoded in UCS2 and number has '+'.
+  let contactUCS2 = {
+    alphaId: "火狐",
+    number: "+1234567890"
+  };
+  helper.writeAlphaIdDiallingNumber(recordSize, contactUCS2.alphaId,
+                                    contactUCS2.number);
+  contactR = helper.readAlphaIdDiallingNumber(recordSize);
+  do_check_eq(contactUCS2.alphaId, contactR.alphaId);
+  do_check_eq(contactUCS2.number, contactR.number);
+
+  // Write a null contact (Removal).
+  helper.writeAlphaIdDiallingNumber(recordSize);
+  contactR = helper.readAlphaIdDiallingNumber(recordSize);
+  do_check_eq(contactR, null);
+
+  // Write a longer alphaId/dialling number
+  // Dialling Number : Maximum 20 digits(10 octets).
+  // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
+  //                   octet for TON/NPI, 1 for number length octet, and 2 for
+  //                   Ext) = Maximum 18 octets.
+  let longContact = {
+    alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
+    number: "123456789012345678901234567890",
+  };
+  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
+                                    longContact.number);
+  contactR = helper.readAlphaIdDiallingNumber(recordSize);
+  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
+  do_check_eq(contactR.number, "12345678901234567890");
+
+  // Add '+' to number and test again.
+  longContact.number = "+123456789012345678901234567890";
+  helper.writeAlphaIdDiallingNumber(recordSize, longContact.alphaId,
+                                    longContact.number);
+  contactR = helper.readAlphaIdDiallingNumber(recordSize);
+  do_check_eq(contactR.alphaId, "AAAAAAAAABBBBBBBBB");
+  do_check_eq(contactR.number, "+12345678901234567890");
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.writeDiallingNumber
+ */
+add_test(function test_write_dialling_number() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.ICCPDUHelper;
+
+  // with +
+  let number = "+123456";
+  let len = 4;
+  helper.writeDiallingNumber(number);
+  do_check_eq(helper.readDiallingNumber(len), number);
+
+  // without +
+  number = "987654";
+  len = 4;
+  helper.writeDiallingNumber(number);
+  do_check_eq(helper.readDiallingNumber(len), number);
+
+  number = "9876543";
+  len = 5;
+  helper.writeDiallingNumber(number);
+  do_check_eq(helper.readDiallingNumber(len), number);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.readNumberWithLength
+ */
+add_test(function test_read_number_with_length() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  let number = "123456789";
+
+  iccHelper.readDiallingNumber = function(numLen) {
+    return number.substring(0, numLen);
+  };
+
+  helper.writeHexOctet(number.length + 1);
+  helper.writeHexOctet(PDU_TOA_ISDN);
+  do_check_eq(iccHelper.readNumberWithLength(), number);
+
+  helper.writeHexOctet(0xff);
+  do_check_eq(iccHelper.readNumberWithLength(), null);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCPDUHelper.writeNumberWithLength
+ */
+add_test(function test_write_number_with_length() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+
+  function test(number, expectedNumber) {
+    expectedNumber = expectedNumber || number;
+    iccHelper.writeNumberWithLength(number);
+    let numLen = helper.readHexOctet();
+    do_check_eq(expectedNumber, iccHelper.readDiallingNumber(numLen));
+    for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES - numLen); i++) {
+      do_check_eq(0xff, helper.readHexOctet());
+    }
+  }
+
+  // without +
+  test("123456789");
+
+  // with +
+  test("+987654321");
+
+  // extended BCD coding
+  test("1*2#3,4*5#6,");
+
+  // with + and extended BCD coding
+  test("+1*2#3,4*5#6,");
+
+  // non-supported characters should not be written.
+  test("(1)23-456+789", "123456789");
+
+  test("++(01)2*3-4#5,6+7(8)9*0#1,", "+012*34#5,6789*0#1,");
+
+  // null
+  iccHelper.writeNumberWithLength(null);
+  for (let i = 0; i < (ADN_MAX_BCD_NUMBER_BYTES + 1); i++) {
+    do_check_eq(0xff, helper.readHexOctet());
+  }
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCRecordHelper.js
@@ -0,0 +1,725 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify ICCRecordHelper.readPBR
+ */
+add_test(function test_read_pbr() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let record = context.ICCRecordHelper;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+    let pbr_1 = [
+      0xa8, 0x05, 0xc0, 0x03, 0x4f, 0x3a, 0x01
+    ];
+
+    // Write data size
+    buf.writeInt32(pbr_1.length * 2);
+
+    // Write pbr
+    for (let i = 0; i < pbr_1.length; i++) {
+      helper.writeHexOctet(pbr_1[i]);
+    }
+
+    // Write string delimiter
+    buf.writeStringDelimiter(pbr_1.length * 2);
+
+    options.totalRecords = 2;
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  io.loadNextRecord = function fakeLoadNextRecord(options) {
+    let pbr_2 = [
+      0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+    ];
+
+    options.p1++;
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  let successCb = function successCb(pbrs) {
+    do_check_eq(pbrs[0].adn.fileId, 0x4f3a);
+    do_check_eq(pbrs.length, 1);
+  };
+
+  let errorCb = function errorCb(errorMsg) {
+    do_print("Reading EF_PBR failed, msg = " + errorMsg);
+    do_check_true(false);
+  };
+
+  record.readPBR(successCb, errorCb);
+
+  // Check cache pbrs when 2nd call
+  let ifLoadEF = false;
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    ifLoadEF = true;
+  }
+  record.readPBR(successCb, errorCb);
+  do_check_false(ifLoadEF);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCRecordHelper.readEmail
+ */
+add_test(function test_read_email() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let record = context.ICCRecordHelper;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+  let recordSize;
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    let email_1 = [
+      0x65, 0x6D, 0x61, 0x69, 0x6C,
+      0x00, 0x6D, 0x6F, 0x7A, 0x69,
+      0x6C, 0x6C, 0x61, 0x2E, 0x63,
+      0x6F, 0x6D, 0x02, 0x23];
+
+    // Write data size
+    buf.writeInt32(email_1.length * 2);
+
+    // Write email
+    for (let i = 0; i < email_1.length; i++) {
+      helper.writeHexOctet(email_1[i]);
+    }
+
+    // Write string delimiter
+    buf.writeStringDelimiter(email_1.length * 2);
+
+    recordSize = email_1.length;
+    options.recordSize = recordSize;
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  function doTestReadEmail(type, expectedResult) {
+    let fileId = 0x6a75;
+    let recordNumber = 1;
+
+    // fileId and recordNumber are dummy arguments.
+    record.readEmail(fileId, type, recordNumber, function(email) {
+      do_check_eq(email, expectedResult);
+    });
+  };
+
+  doTestReadEmail(ICC_USIM_TYPE1_TAG, "email@mozilla.com$#");
+  doTestReadEmail(ICC_USIM_TYPE2_TAG, "email@mozilla.com");
+  do_check_eq(record._emailRecordSize, recordSize);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCRecordHelper.updateEmail
+ */
+add_test(function test_update_email() {
+  const recordSize = 0x20;
+  const recordNumber = 1;
+  const fileId = 0x4f50;
+  const NUM_TESTS = 2;
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  let ril = context.RIL;
+  ril.appType = CARD_APPTYPE_USIM;
+  let recordHelper = context.ICCRecordHelper;
+  let buf = context.Buf;
+  let ioHelper = context.ICCIOHelper;
+  let pbr = {email: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
+             adn: {sfi: 1}};
+  let count = 0;
+
+  // Override.
+  ioHelper.updateLinearFixedEF = function(options) {
+    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
+    options.command = ICC_COMMAND_UPDATE_RECORD;
+    options.p1 = options.recordNumber;
+    options.p2 = READ_RECORD_ABSOLUTE_MODE;
+    options.p3 = recordSize;
+    ril.iccIO(options);
+  };
+
+  function do_test(pbr, expectedEmail, expectedAdnRecordId) {
+    buf.sendParcel = function() {
+      count++;
+
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
+
+      // Token : we don't care
+      this.readInt32();
+
+      // command.
+      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
+
+      // fileId.
+      do_check_eq(this.readInt32(), fileId);
+
+      // pathId.
+      do_check_eq(this.readString(),
+                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
+
+      // p1.
+      do_check_eq(this.readInt32(), recordNumber);
+
+      // p2.
+      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
+
+      // p3.
+      do_check_eq(this.readInt32(), recordSize);
+
+      // data.
+      let strLen = this.readInt32();
+      let email;
+      if (pbr.email.fileType === ICC_USIM_TYPE1_TAG) {
+        email = iccHelper.read8BitUnpackedToString(recordSize);
+      } else {
+        email = iccHelper.read8BitUnpackedToString(recordSize - 2);
+        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
+        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
+      }
+      this.readStringDelimiter(strLen);
+      do_check_eq(email, expectedEmail);
+
+      // pin2.
+      do_check_eq(this.readString(), null);
+
+      if (!ril.v5Legacy) {
+        // AID. Ignore because it's from modem.
+        this.readInt32();
+      }
+
+      if (count == NUM_TESTS) {
+        run_next_test();
+      }
+    };
+    recordHelper.updateEmail(pbr, recordNumber, expectedEmail, expectedAdnRecordId);
+  }
+
+  do_test(pbr, "test@mail.com");
+  pbr.email.fileType = ICC_USIM_TYPE2_TAG;
+  do_test(pbr, "test@mail.com", 1);
+});
+
+/**
+ * Verify ICCRecordHelper.readANR
+ */
+add_test(function test_read_anr() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let record = context.ICCRecordHelper;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+  let recordSize;
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    let anr_1 = [
+      0x01, 0x05, 0x81, 0x10, 0x32,
+      0x54, 0xF6, 0xFF, 0xFF];
+
+    // Write data size
+    buf.writeInt32(anr_1.length * 2);
+
+    // Write anr
+    for (let i = 0; i < anr_1.length; i++) {
+      helper.writeHexOctet(anr_1[i]);
+    }
+
+    // Write string delimiter
+    buf.writeStringDelimiter(anr_1.length * 2);
+
+    recordSize = anr_1.length;
+    options.recordSize = recordSize;
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  function doTestReadAnr(fileType, expectedResult) {
+    let fileId = 0x4f11;
+    let recordNumber = 1;
+
+    // fileId and recordNumber are dummy arguments.
+    record.readANR(fileId, fileType, recordNumber, function(anr) {
+      do_check_eq(anr, expectedResult);
+    });
+  };
+
+  doTestReadAnr(ICC_USIM_TYPE1_TAG, "0123456");
+  do_check_eq(record._anrRecordSize, recordSize);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCRecordHelper.updateANR
+ */
+add_test(function test_update_anr() {
+  const recordSize = 0x20;
+  const recordNumber = 1;
+  const fileId = 0x4f11;
+  const NUM_TESTS = 2;
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let iccHelper = context.ICCPDUHelper;
+  let ril = context.RIL;
+  ril.appType = CARD_APPTYPE_USIM;
+  let recordHelper = context.ICCRecordHelper;
+  let buf = context.Buf;
+  let ioHelper = context.ICCIOHelper;
+  let pbr = {anr0: {fileId: fileId, fileType: ICC_USIM_TYPE1_TAG},
+             adn: {sfi: 1}};
+  let count = 0;
+
+  // Override.
+  ioHelper.updateLinearFixedEF = function(options) {
+    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
+    options.command = ICC_COMMAND_UPDATE_RECORD;
+    options.p1 = options.recordNumber;
+    options.p2 = READ_RECORD_ABSOLUTE_MODE;
+    options.p3 = recordSize;
+    ril.iccIO(options);
+  };
+
+  function do_test(pbr, expectedANR, expectedAdnRecordId) {
+    buf.sendParcel = function() {
+      count++;
+
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
+
+      // Token : we don't care
+      this.readInt32();
+
+      // command.
+      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
+
+      // fileId.
+      do_check_eq(this.readInt32(), fileId);
+
+      // pathId.
+      do_check_eq(this.readString(),
+                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
+
+      // p1.
+      do_check_eq(this.readInt32(), recordNumber);
+
+      // p2.
+      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
+
+      // p3.
+      do_check_eq(this.readInt32(), recordSize);
+
+      // data.
+      let strLen = this.readInt32();
+      // EF_AAS, ignore.
+      pduHelper.readHexOctet();
+      do_check_eq(iccHelper.readNumberWithLength(), expectedANR);
+      // EF_CCP, ignore.
+      pduHelper.readHexOctet();
+      // EF_EXT1, ignore.
+      pduHelper.readHexOctet();
+      if (pbr.anr0.fileType === ICC_USIM_TYPE2_TAG) {
+        do_check_eq(pduHelper.readHexOctet(), pbr.adn.sfi);
+        do_check_eq(pduHelper.readHexOctet(), expectedAdnRecordId);
+      }
+      this.readStringDelimiter(strLen);
+
+      // pin2.
+      do_check_eq(this.readString(), null);
+
+      if (!ril.v5Legacy) {
+        // AID. Ignore because it's from modem.
+        this.readInt32();
+      }
+
+      if (count == NUM_TESTS) {
+        run_next_test();
+      }
+    };
+    recordHelper.updateANR(pbr, recordNumber, expectedANR, expectedAdnRecordId);
+  }
+
+  do_test(pbr, "+123456789");
+  pbr.anr0.fileType = ICC_USIM_TYPE2_TAG;
+  do_test(pbr, "123456789", 1);
+});
+
+/**
+ * Verify ICCRecordHelper.readIAP
+ */
+add_test(function test_read_iap() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let record = context.ICCRecordHelper;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+  let recordSize;
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    let iap_1 = [0x01, 0x02];
+
+    // Write data size/
+    buf.writeInt32(iap_1.length * 2);
+
+    // Write iap.
+    for (let i = 0; i < iap_1.length; i++) {
+      helper.writeHexOctet(iap_1[i]);
+    }
+
+    // Write string delimiter.
+    buf.writeStringDelimiter(iap_1.length * 2);
+
+    recordSize = iap_1.length;
+    options.recordSize = recordSize;
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  function doTestReadIAP(expectedIAP) {
+    const fileId = 0x4f17;
+    const recordNumber = 1;
+
+    let successCb = function successCb(iap) {
+      for (let i = 0; i < iap.length; i++) {
+        do_check_eq(expectedIAP[i], iap[i]);
+      }
+      run_next_test();
+    }.bind(this);
+
+    let errorCb = function errorCb(errorMsg) {
+      do_print(errorMsg);
+      do_check_true(false);
+      run_next_test();
+    }.bind(this);
+
+    record.readIAP(fileId, recordNumber, successCb, errorCb);
+  };
+
+  doTestReadIAP([1, 2]);
+});
+
+/**
+ * Verify ICCRecordHelper.updateIAP
+ */
+add_test(function test_update_iap() {
+  const recordSize = 2;
+  const recordNumber = 1;
+  const fileId = 0x4f17;
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let ril = context.RIL;
+  ril.appType = CARD_APPTYPE_USIM;
+  let recordHelper = context.ICCRecordHelper;
+  let buf = context.Buf;
+  let ioHelper = context.ICCIOHelper;
+  let count = 0;
+
+  // Override.
+  ioHelper.updateLinearFixedEF = function(options) {
+    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
+    options.command = ICC_COMMAND_UPDATE_RECORD;
+    options.p1 = options.recordNumber;
+    options.p2 = READ_RECORD_ABSOLUTE_MODE;
+    options.p3 = recordSize;
+    ril.iccIO(options);
+  };
+
+  function do_test(expectedIAP) {
+    buf.sendParcel = function() {
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
+
+      // Token : we don't care
+      this.readInt32();
+
+      // command.
+      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
+
+      // fileId.
+      do_check_eq(this.readInt32(), fileId);
+
+      // pathId.
+      do_check_eq(this.readString(),
+                  EF_PATH_MF_SIM + EF_PATH_DF_TELECOM + EF_PATH_DF_PHONEBOOK);
+
+      // p1.
+      do_check_eq(this.readInt32(), recordNumber);
+
+      // p2.
+      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
+
+      // p3.
+      do_check_eq(this.readInt32(), recordSize);
+
+      // data.
+      let strLen = this.readInt32();
+      for (let i = 0; i < recordSize; i++) {
+        do_check_eq(expectedIAP[i], pduHelper.readHexOctet());
+      }
+      this.readStringDelimiter(strLen);
+
+      // pin2.
+      do_check_eq(this.readString(), null);
+
+      if (!ril.v5Legacy) {
+        // AID. Ignore because it's from modem.
+        this.readInt32();
+      }
+
+      run_next_test();
+    };
+    recordHelper.updateIAP(fileId, recordNumber, expectedIAP);
+  }
+
+  do_test([1, 2]);
+});
+
+/**
+ * Verify ICCRecordHelper.updateADNLike.
+ */
+add_test(function test_update_adn_like() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ril = context.RIL;
+  let record = context.ICCRecordHelper;
+  let io = context.ICCIOHelper;
+  let pdu = context.ICCPDUHelper;
+  let buf = context.Buf;
+
+  ril.appType = CARD_APPTYPE_SIM;
+  const recordSize = 0x20;
+  let fileId;
+
+  // Override.
+  io.updateLinearFixedEF = function(options) {
+    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
+    options.command = ICC_COMMAND_UPDATE_RECORD;
+    options.p1 = options.recordNumber;
+    options.p2 = READ_RECORD_ABSOLUTE_MODE;
+    options.p3 = recordSize;
+    ril.iccIO(options);
+  };
+
+  buf.sendParcel = function() {
+    // Request Type.
+    do_check_eq(this.readInt32(), REQUEST_SIM_IO);
+
+    // Token : we don't care
+    this.readInt32();
+
+    // command.
+    do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
+
+    // fileId.
+    do_check_eq(this.readInt32(), fileId);
+
+    // pathId.
+    do_check_eq(this.readString(), EF_PATH_MF_SIM + EF_PATH_DF_TELECOM);
+
+    // p1.
+    do_check_eq(this.readInt32(), 1);
+
+    // p2.
+    do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
+
+    // p3.
+    do_check_eq(this.readInt32(), 0x20);
+
+    // data.
+    let contact = pdu.readAlphaIdDiallingNumber(0x20);
+    do_check_eq(contact.alphaId, "test");
+    do_check_eq(contact.number, "123456");
+
+    // pin2.
+    if (fileId == ICC_EF_ADN) {
+      do_check_eq(this.readString(), null);
+    } else {
+      do_check_eq(this.readString(), "1111");
+    }
+
+    if (!ril.v5Legacy) {
+      // AID. Ignore because it's from modem.
+      this.readInt32();
+    }
+
+    if (fileId == ICC_EF_FDN) {
+      run_next_test();
+    }
+  };
+
+  fileId = ICC_EF_ADN;
+  record.updateADNLike(fileId,
+                       {recordId: 1, alphaId: "test", number: "123456"});
+
+  fileId = ICC_EF_FDN;
+  record.updateADNLike(fileId,
+                       {recordId: 1, alphaId: "test", number: "123456"},
+                       "1111");
+});
+
+/**
+ * Verify ICCRecordHelper.findFreeRecordId.
+ */
+add_test(function test_find_free_record_id() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let recordHelper = context.ICCRecordHelper;
+  let buf = context.Buf;
+  let io  = context.ICCIOHelper;
+
+  function writeRecord (record) {
+    // Write data size
+    buf.writeInt32(record.length * 2);
+
+    for (let i = 0; i < record.length; i++) {
+      pduHelper.writeHexOctet(record[i]);
+    }
+
+    // Write string delimiter
+    buf.writeStringDelimiter(record.length * 2);
+  }
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options)  {
+    // Some random data.
+    let record = [0x12, 0x34, 0x56, 0x78, 0x90];
+    options.p1 = 1;
+    options.totalRecords = 2;
+    writeRecord(record);
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  io.loadNextRecord = function fakeLoadNextRecord(options) {
+    // Unused bytes.
+    let record = [0xff, 0xff, 0xff, 0xff, 0xff];
+    options.p1++;
+    writeRecord(record);
+    if (options.callback) {
+      options.callback(options);
+    }
+  };
+
+  let fileId = 0x0000; // Dummy.
+  recordHelper.findFreeRecordId(
+    fileId,
+    function(recordId) {
+      do_check_eq(recordId, 2);
+      run_next_test();
+    }.bind(this),
+    function(errorMsg) {
+      do_print(errorMsg);
+      do_check_true(false);
+      run_next_test();
+    }.bind(this));
+});
+
+/**
+ * Verify ICCRecordHelper.fetchICCRecords.
+ */
+add_test(function test_fetch_icc_recodes() {
+  let worker = newWorker();
+  let context = worker.ContextPool._contexts[0];
+  let RIL = context.RIL;
+  let iccRecord = context.ICCRecordHelper;
+  let simRecord = context.SimRecordHelper;
+  let ruimRecord = context.RuimRecordHelper;
+  let fetchTag = 0x00;
+
+  simRecord.fetchSimRecords = function() {
+    fetchTag = 0x01;
+  };
+
+  ruimRecord.fetchRuimRecords = function() {
+    fetchTag = 0x02;
+  };
+
+  RIL.appType = CARD_APPTYPE_SIM;
+  iccRecord.fetchICCRecords();
+  do_check_eq(fetchTag, 0x01);
+
+  RIL.appType = CARD_APPTYPE_RUIM;
+  iccRecord.fetchICCRecords();
+  do_check_eq(fetchTag, 0x02);
+
+  RIL.appType = CARD_APPTYPE_USIM;
+  iccRecord.fetchICCRecords();
+  do_check_eq(fetchTag, 0x01);
+
+  run_next_test();
+});
+
+/**
+ * Verify reading EF_ICCID.
+ */
+add_test(function test_handling_iccid() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let record = context.ICCRecordHelper;
+  let helper = context.GsmPDUHelper;
+  let ril = context.RIL;
+  let buf = context.Buf;
+  let io = context.ICCIOHelper;
+
+  ril.reportStkServiceIsRunning = function fakeReportStkServiceIsRunning() {
+  };
+
+  function do_test(rawICCID, expectedICCID) {
+    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+      // Write data size
+      buf.writeInt32(rawICCID.length);
+
+      // Write data
+      for (let i = 0; i < rawICCID.length; i += 2) {
+        helper.writeHexOctet(parseInt(rawICCID.substr(i, 2), 16));
+      }
+
+      // Write string delimiter
+      buf.writeStringDelimiter(rawICCID.length);
+
+      if (options.callback) {
+        options.callback(options);
+      }
+    };
+
+    record.readICCID();
+
+    do_check_eq(ril.iccInfo.iccid, expectedICCID);
+  }
+
+  // Invalid char at high nibbile + low nibbile contains 0xF.
+  do_test("9868002E90909F001519", "89860020909");
+  // Invalid char at low nibbile.
+  do_test("986800E2909090001519", "8986002090909005191");
+  // Valid ICCID.
+  do_test("98101430121181157002", "89014103211118510720");
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCUtilsHelper.js
@@ -0,0 +1,236 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify ICCUtilsHelper.isICCServiceAvailable.
+ */
+add_test(function test_is_icc_service_available() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ICCUtilsHelper = context.ICCUtilsHelper;
+  let RIL = context.RIL;
+
+  function test_table(sst, geckoService, simEnabled, usimEnabled) {
+    RIL.iccInfoPrivate.sst = sst;
+    RIL.appType = CARD_APPTYPE_SIM;
+    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), simEnabled);
+    RIL.appType = CARD_APPTYPE_USIM;
+    do_check_eq(ICCUtilsHelper.isICCServiceAvailable(geckoService), usimEnabled);
+  }
+
+  test_table([0x08], "ADN", true, false);
+  test_table([0x08], "FDN", false, false);
+  test_table([0x08], "SDN", false, true);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCUtilsHelper.isGsm8BitAlphabet
+ */
+add_test(function test_is_gsm_8bit_alphabet() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let ICCUtilsHelper = context.ICCUtilsHelper;
+  const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+  const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
+
+  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langTable), true);
+  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet(langShiftTable), true);
+  do_check_eq(ICCUtilsHelper.isGsm8BitAlphabet("\uaaaa"), false);
+
+  run_next_test();
+});
+
+/**
+ * Verify ICCUtilsHelper.parsePbrTlvs
+ */
+add_test(function test_parse_pbr_tlvs() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let buf = context.Buf;
+
+  let pbrTlvs = [
+    {tag: ICC_USIM_TYPE1_TAG,
+     length: 0x0F,
+     value: [{tag: ICC_USIM_EFADN_TAG,
+              length: 0x03,
+              value: [0x4F, 0x3A, 0x02]},
+             {tag: ICC_USIM_EFIAP_TAG,
+              length: 0x03,
+              value: [0x4F, 0x25, 0x01]},
+             {tag: ICC_USIM_EFPBC_TAG,
+              length: 0x03,
+              value: [0x4F, 0x09, 0x04]}]
+    },
+    {tag: ICC_USIM_TYPE2_TAG,
+     length: 0x05,
+     value: [{tag: ICC_USIM_EFEMAIL_TAG,
+              length: 0x03,
+              value: [0x4F, 0x50, 0x0B]},
+             {tag: ICC_USIM_EFANR_TAG,
+              length: 0x03,
+              value: [0x4F, 0x11, 0x02]},
+             {tag: ICC_USIM_EFANR_TAG,
+              length: 0x03,
+              value: [0x4F, 0x12, 0x03]}]
+    },
+    {tag: ICC_USIM_TYPE3_TAG,
+     length: 0x0A,
+     value: [{tag: ICC_USIM_EFCCP1_TAG,
+              length: 0x03,
+              value: [0x4F, 0x3D, 0x0A]},
+             {tag: ICC_USIM_EFEXT1_TAG,
+              length: 0x03,
+              value: [0x4F, 0x4A, 0x03]}]
+    },
+  ];
+
+  let pbr = context.ICCUtilsHelper.parsePbrTlvs(pbrTlvs);
+  do_check_eq(pbr.adn.fileId, 0x4F3a);
+  do_check_eq(pbr.iap.fileId, 0x4F25);
+  do_check_eq(pbr.pbc.fileId, 0x4F09);
+  do_check_eq(pbr.email.fileId, 0x4F50);
+  do_check_eq(pbr.anr0.fileId, 0x4f11);
+  do_check_eq(pbr.anr1.fileId, 0x4f12);
+  do_check_eq(pbr.ccp1.fileId, 0x4F3D);
+  do_check_eq(pbr.ext1.fileId, 0x4F4A);
+
+  run_next_test();
+});
+
+/**
+ * Verify MCC and MNC parsing
+ */
+add_test(function test_mcc_mnc_parsing() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.ICCUtilsHelper;
+
+  function do_test(imsi, mncLength, expectedMcc, expectedMnc) {
+    let result = helper.parseMccMncFromImsi(imsi, mncLength);
+
+    if (!imsi) {
+      do_check_eq(result, null);
+      return;
+    }
+
+    do_check_eq(result.mcc, expectedMcc);
+    do_check_eq(result.mnc, expectedMnc);
+  }
+
+  // Test the imsi is null.
+  do_test(null, null, null, null);
+
+  // Test MCC is Taiwan
+  do_test("466923202422409", 0x02, "466", "92");
+  do_test("466923202422409", 0x03, "466", "923");
+  do_test("466923202422409", null, "466", "92");
+
+  // Test MCC is US
+  do_test("310260542718417", 0x02, "310", "26");
+  do_test("310260542718417", 0x03, "310", "260");
+  do_test("310260542718417", null, "310", "260");
+
+  run_next_test();
+});
+
+add_test(function test_get_network_name_from_icc() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let RIL = context.RIL;
+  let ICCUtilsHelper = context.ICCUtilsHelper;
+
+  function testGetNetworkNameFromICC(operatorData, expectedResult) {
+    let result = ICCUtilsHelper.getNetworkNameFromICC(operatorData.mcc,
+                                                      operatorData.mnc,
+                                                      operatorData.lac);
+
+    if (expectedResult == null) {
+      do_check_eq(result, expectedResult);
+    } else {
+      do_check_eq(result.fullName, expectedResult.longName);
+      do_check_eq(result.shortName, expectedResult.shortName);
+    }
+  }
+
+  // Before EF_OPL and EF_PNN have been loaded.
+  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000}, null);
+  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x2000}, null);
+
+  // Set HPLMN
+  RIL.iccInfo.mcc = 123;
+  RIL.iccInfo.mnc = 456;
+
+  RIL.voiceRegistrationState = {
+    cell: {
+      gsmLocationAreaCode: 0x1000
+    }
+  };
+  RIL.operator = {};
+
+  // Set EF_PNN
+  RIL.iccInfoPrivate = {
+    PNN: [
+      {"fullName": "PNN1Long", "shortName": "PNN1Short"},
+      {"fullName": "PNN2Long", "shortName": "PNN2Short"},
+      {"fullName": "PNN3Long", "shortName": "PNN3Short"},
+      {"fullName": "PNN4Long", "shortName": "PNN4Short"}
+    ]
+  };
+
+  // EF_OPL isn't available and current isn't in HPLMN,
+  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000}, null);
+
+  // EF_OPL isn't available and current is in HPLMN,
+  // the first record of PNN should be returned.
+  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
+                            {longName: "PNN1Long", shortName: "PNN1Short"});
+
+  // Set EF_OPL
+  RIL.iccInfoPrivate.OPL = [
+    {
+      "mcc": 123,
+      "mnc": 456,
+      "lacTacStart": 0,
+      "lacTacEnd": 0xFFFE,
+      "pnnRecordId": 4
+    },
+    {
+      "mcc": 321,
+      "mnc": 654,
+      "lacTacStart": 0,
+      "lacTacEnd": 0x0010,
+      "pnnRecordId": 3
+    },
+    {
+      "mcc": 321,
+      "mnc": 654,
+      "lacTacStart": 0x0100,
+      "lacTacEnd": 0x1010,
+      "pnnRecordId": 2
+    }
+  ];
+
+  // Both EF_PNN and EF_OPL are presented, and current PLMN is HPLMN,
+  testGetNetworkNameFromICC({mcc: 123, mnc: 456, lac: 0x1000},
+                            {longName: "PNN4Long", shortName: "PNN4Short"});
+
+  // Current PLMN is not HPLMN, and according to LAC, we should get
+  // the second PNN record.
+  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x1000},
+                            {longName: "PNN2Long", shortName: "PNN2Short"});
+
+  // Current PLMN is not HPLMN, and according to LAC, we should get
+  // the thrid PNN record.
+  testGetNetworkNameFromICC({mcc: 321, mnc: 654, lac: 0x0001},
+                            {longName: "PNN3Long", shortName: "PNN3Short"});
+
+  run_next_test();
+});
new file mode 100644
--- /dev/null
+++ b/dom/system/gonk/tests/test_ril_worker_icc_SimRecordHelper.js
@@ -0,0 +1,489 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
+
+function run_test() {
+  run_next_test();
+}
+
+/**
+ * Verify reading EF_AD and parsing MCC/MNC
+ */
+add_test(function test_reading_ad_and_parsing_mcc_mnc() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let record = context.SimRecordHelper;
+  let helper = context.GsmPDUHelper;
+  let ril    = context.RIL;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+
+  function do_test(mncLengthInEf, imsi, expectedMcc, expectedMnc) {
+    ril.iccInfoPrivate.imsi = imsi;
+
+    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+      let ad = [0x00, 0x00, 0x00];
+      if (typeof mncLengthInEf === 'number') {
+        ad.push(mncLengthInEf);
+      }
+
+      // Write data size
+      buf.writeInt32(ad.length * 2);
+
+      // Write data
+      for (let i = 0; i < ad.length; i++) {
+        helper.writeHexOctet(ad[i]);
+      }
+
+      // Write string delimiter
+      buf.writeStringDelimiter(ad.length * 2);
+
+      if (options.callback) {
+        options.callback(options);
+      }
+    };
+
+    record.readAD();
+
+    do_check_eq(ril.iccInfo.mcc, expectedMcc);
+    do_check_eq(ril.iccInfo.mnc, expectedMnc);
+  }
+
+  do_test(undefined, "466923202422409", "466", "92" );
+  do_test(0x00,      "466923202422409", "466", "92" );
+  do_test(0x01,      "466923202422409", "466", "92" );
+  do_test(0x02,      "466923202422409", "466", "92" );
+  do_test(0x03,      "466923202422409", "466", "923");
+  do_test(0x04,      "466923202422409", "466", "92" );
+  do_test(0xff,      "466923202422409", "466", "92" );
+
+  do_test(undefined, "310260542718417", "310", "260");
+  do_test(0x00,      "310260542718417", "310", "260");
+  do_test(0x01,      "310260542718417", "310", "260");
+  do_test(0x02,      "310260542718417", "310", "26" );
+  do_test(0x03,      "310260542718417", "310", "260");
+  do_test(0x04,      "310260542718417", "310", "260");
+  do_test(0xff,      "310260542718417", "310", "260");
+
+  run_next_test();
+});
+
+add_test(function test_reading_optional_efs() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let record = context.SimRecordHelper;
+  let gsmPdu = context.GsmPDUHelper;
+  let ril    = context.RIL;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+
+  function buildSST(supportedEf) {
+    let sst = [];
+    let len = supportedEf.length;
+    for (let i = 0; i < len; i++) {
+      let index, bitmask, iccService;
+      if (ril.appType === CARD_APPTYPE_SIM) {
+        iccService = GECKO_ICC_SERVICES.sim[supportedEf[i]];
+        iccService -= 1;
+        index = Math.floor(iccService / 4);
+        bitmask = 2 << ((iccService % 4) << 1);
+      } else if (ril.appType === CARD_APPTYPE_USIM){
+        iccService = GECKO_ICC_SERVICES.usim[supportedEf[i]];
+        iccService -= 1;
+        index = Math.floor(iccService / 8);
+        bitmask = 1 << ((iccService % 8) << 0);
+      }
+
+      if (sst) {
+        sst[index] |= bitmask;
+      }
+    }
+    return sst;
+  }
+
+  ril.updateCellBroadcastConfig = function fakeUpdateCellBroadcastConfig() {
+    // Ignore updateCellBroadcastConfig after reading SST
+  };
+
+  function do_test(sst, supportedEf) {
+    // Clone supportedEf to local array for testing
+    let testEf = supportedEf.slice(0);
+
+    record.readMSISDN = function fakeReadMSISDN() {
+      testEf.splice(testEf.indexOf("MSISDN"), 1);
+    };
+
+    record.readMBDN = function fakeReadMBDN() {
+      testEf.splice(testEf.indexOf("MDN"), 1);
+    };
+
+    record.readMWIS = function fakeReadMWIS() {
+      testEf.splice(testEf.indexOf("MWIS"), 1);
+    };
+
+    io.loadTransparentEF = function fakeLoadTransparentEF(options) {
+      // Write data size
+      buf.writeInt32(sst.length * 2);
+
+      // Write data
+      for (let i = 0; i < sst.length; i++) {
+         gsmPdu.writeHexOctet(sst[i] || 0);
+      }
+
+      // Write string delimiter
+      buf.writeStringDelimiter(sst.length * 2);
+
+      if (options.callback) {
+        options.callback(options);
+      }
+
+      if (testEf.length !== 0) {
+        do_print("Un-handled EF: " + JSON.stringify(testEf));
+        do_check_true(false);
+      }
+    };
+
+    record.readSST();
+  }
+
+  // TODO: Add all necessary optional EFs eventually
+  let supportedEf = ["MSISDN", "MDN", "MWIS"];
+  ril.appType = CARD_APPTYPE_SIM;
+  do_test(buildSST(supportedEf), supportedEf);
+  ril.appType = CARD_APPTYPE_USIM;
+  do_test(buildSST(supportedEf), supportedEf);
+
+  run_next_test();
+});
+
+/**
+ * Verify fetchSimRecords.
+ */
+add_test(function test_fetch_sim_recodes() {
+  let worker = newWorker();
+  let context = worker.ContextPool._contexts[0];
+  let RIL = context.RIL;
+  let iccRecord = context.ICCRecordHelper;
+  let simRecord = context.SimRecordHelper;
+
+  function testFetchSimRecordes(expectCalled) {
+    let ifCalled = [];
+
+    RIL.getIMSI = function() {
+      ifCalled.push("getIMSI");
+    };
+
+    simRecord.readAD = function() {
+      ifCalled.push("readAD");
+    };
+
+    simRecord.readSST = function() {
+      ifCalled.push("readSST");
+    };
+
+    simRecord.fetchSimRecords();
+
+    for (let i = 0; i < expectCalled.length; i++ ) {
+      if (ifCalled[i] != expectCalled[i]) {
+        do_print(expectCalled[i] + " is not called.");
+        do_check_true(false);
+      }
+    }
+  }
+
+  let expectCalled = ["getIMSI", "readAD", "readSST"];
+  testFetchSimRecordes(expectCalled);
+
+  run_next_test();
+});
+
+/**
+ * Verify SimRecordHelper.readMWIS
+ */
+add_test(function test_read_mwis() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let helper = context.GsmPDUHelper;
+  let recordHelper = context.SimRecordHelper;
+  let buf    = context.Buf;
+  let io     = context.ICCIOHelper;
+  let mwisData;
+  let postedMessage;
+
+  worker.postMessage = function fakePostMessage(message) {
+    postedMessage = message;
+  };
+
+  io.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+    if (mwisData) {
+      // Write data size
+      buf.writeInt32(mwisData.length * 2);
+
+      // Write MWIS
+      for (let i = 0; i < mwisData.length; i++) {
+        helper.writeHexOctet(mwisData[i]);
+      }
+
+      // Write string delimiter
+      buf.writeStringDelimiter(mwisData.length * 2);
+
+      options.recordSize = mwisData.length;
+      if (options.callback) {
+        options.callback(options);
+      }
+    } else {
+      do_print("mwisData[] is not set.");
+    }
+  };
+
+  function buildMwisData(isActive, msgCount) {
+    if (msgCount < 0 || msgCount === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) {
+      msgCount = 0;
+    } else if (msgCount > 255) {
+      msgCount = 255;
+    }
+
+    mwisData =  [ (isActive) ? 0x01 : 0x00,
+                  msgCount,
+                  0xFF, 0xFF, 0xFF ];
+  }
+
+  function do_test(isActive, msgCount) {
+    buildMwisData(isActive, msgCount);
+    recordHelper.readMWIS();
+
+    do_check_eq("iccmwis", postedMessage.rilMessageType);
+    do_check_eq(isActive, postedMessage.mwi.active);
+    do_check_eq((isActive) ? msgCount : 0, postedMessage.mwi.msgCount);
+  }
+
+  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
+  do_test(true, 1);
+  do_test(true, 255);
+
+  do_test(false, 0);
+  do_test(false, 255); // Test the corner case when mwi is disable with incorrect msgCount.
+
+  run_next_test();
+});
+
+/**
+ * Verify SimRecordHelper.updateMWIS
+ */
+add_test(function test_update_mwis() {
+  let worker = newUint8Worker();
+  let context = worker.ContextPool._contexts[0];
+  let pduHelper = context.GsmPDUHelper;
+  let ril = context.RIL;
+  ril.appType = CARD_APPTYPE_USIM;
+  ril.iccInfoPrivate.mwis = [0x00, 0x00, 0x00, 0x00, 0x00];
+  let recordHelper = context.SimRecordHelper;
+  let buf = context.Buf;
+  let ioHelper = context.ICCIOHelper;
+  let recordSize = ril.iccInfoPrivate.mwis.length;
+  let recordNum = 1;
+
+  ioHelper.updateLinearFixedEF = function(options) {
+    options.pathId = context.ICCFileHelper.getEFPath(options.fileId);
+    options.command = ICC_COMMAND_UPDATE_RECORD;
+    options.p1 = options.recordNumber;
+    options.p2 = READ_RECORD_ABSOLUTE_MODE;
+    options.p3 = recordSize;
+    ril.iccIO(options);
+  };
+
+  function do_test(isActive, count) {
+    let mwis = ril.iccInfoPrivate.mwis;
+    let isUpdated = false;
+
+    function buildMwisData() {
+      let result = mwis.slice(0);
+      result[0] = isActive? (mwis[0] | 0x01) : (mwis[0] & 0xFE);
+      result[1] = (count === GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN) ? 0 : count;
+
+      return result;
+    }
+
+    buf.sendParcel = function() {
+      isUpdated = true;
+
+      // Request Type.
+      do_check_eq(this.readInt32(), REQUEST_SIM_IO);
+
+      // Token : we don't care
+      this.readInt32();
+
+      // command.
+      do_check_eq(this.readInt32(), ICC_COMMAND_UPDATE_RECORD);
+
+      // fileId.
+      do_check_eq(this.readInt32(), ICC_EF_MWIS);
+
+      // pathId.
+      do_check_eq(this.readString(),
+                  EF_PATH_MF_SIM + ((ril.appType === CARD_APPTYPE_USIM) ? EF_PATH_ADF_USIM : EF_PATH_DF_GSM));
+
+      // p1.
+      do_check_eq(this.readInt32(), recordNum);
+
+      // p2.
+      do_check_eq(this.readInt32(), READ_RECORD_ABSOLUTE_MODE);
+
+      // p3.
+      do_check_eq(this.readInt32(), recordSize);
+
+      // data.
+      let strLen = this.readInt32();
+      do_check_eq(recordSize * 2, strLen);
+      let expectedMwis = buildMwisData();
+      for (let i = 0; i < recordSize; i++) {
+        do_check_eq(expectedMwis[i], pduHelper.readHexOctet());
+      }
+      this.readStringDelimiter(strLen);
+
+      // pin2.
+      do_check_eq(this.readString(), null);
+
+      if (!ril.v5Legacy) {
+        // AID. Ignore because it's from modem.
+        this.readInt32();
+      }
+    };
+
+    do_check_false(isUpdated);
+
+    recordHelper.updateMWIS({ active: isActive,
+                              msgCount: count });
+
+    do_check_true((ril.iccInfoPrivate.mwis) ? isUpdated : !isUpdated);
+  }
+
+  do_test(true, GECKO_VOICEMAIL_MESSAGE_COUNT_UNKNOWN);
+  do_test(true, 1);
+  do_test(true, 255);
+
+  do_test(false, 0);
+
+  // Test if Path ID is correct for SIM.
+  ril.appType = CARD_APPTYPE_SIM;
+  do_test(false, 0);
+
+  // Test if loadLinearFixedEF() is not invoked in updateMWIS() when
+  // EF_MWIS is not loaded/available.
+  delete ril.iccInfoPrivate.mwis;
+  do_test(false, 0);
+
+  run_next_test();
+});
+
+/**
+ * Verify the call flow of receiving Class 2 SMS stored in SIM:
+ * 1. UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM.
+ * 2. SimRecordHelper.readSMS().
+ * 3. sendChromeMessage() with rilMessageType == "sms-received".
+ */
+add_test(function test_read_new_sms_on_sim() {
+  // Instead of reusing newUint8Worker defined in this file,
+  // we define our own worker to fake the methods in WorkerBuffer dynamically.
+  function newSmsOnSimWorkerHelper() {
+    let _postedMessage;
+    let _worker = newWorker({
+      postRILMessage: function(data) {
+      },
+      postMessage: function(message) {
+        _postedMessage = message;
+      }
+    });
+
+    _worker.debug = do_print;
+
+    return {
+      get postedMessage() {
+        return _postedMessage;
+      },
+      get worker() {
+        return _worker;
+      },
+      fakeWokerBuffer: function() {
+        let context = _worker.ContextPool._contexts[0];
+        let index = 0; // index for read
+        let buf = [];
+        context.Buf.writeUint8 = function(value) {
+          buf.push(value);
+        };
+        context.Buf.readUint8 = function() {
+          return buf[index++];
+        };
+        context.Buf.seekIncoming = function(offset) {
+          index += offset;
+        };
+        context.Buf.getReadAvailable = function() {
+          return buf.length - index;
+        };
+      }
+    };
+  }
+
+  let workerHelper = newSmsOnSimWorkerHelper();
+  let worker = workerHelper.worker;
+  let context = worker.ContextPool._contexts[0];
+
+  context.ICCIOHelper.loadLinearFixedEF = function fakeLoadLinearFixedEF(options) {
+      // SimStatus: Unread, SMSC:+0123456789, Sender: +9876543210, Text: How are you?
+      let SimSmsPduHex = "0306911032547698040A9189674523010000208062917314080CC8F71D14969741F977FD07"
+                       // In 4.2.25 EF_SMS Short Messages of 3GPP TS 31.102:
+                       // 1. Record length == 176 bytes.
+                       // 2. Any bytes in the record following the TPDU shall be filled with 'FF'.
+                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
+                       + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF";
+
+      workerHelper.fakeWokerBuffer();
+
+      context.Buf.writeString(SimSmsPduHex);
+
+      options.recordSize = 176; // Record length is fixed to 176 bytes.
+      if (options.callback) {
+        options.callback(options);
+      }
+  };
+
+  function newSmsOnSimParcel() {
+    let data = new Uint8Array(4 + 4); // Int32List with 1 element.
+    let offset = 0;
+
+    function writeInt(value) {
+      data[offset++] = value & 0xFF;
+      data[offset++] = (value >>  8) & 0xFF;
+      data[offset++] = (value >> 16) & 0xFF;
+      data[offset++] = (value >> 24) & 0xFF;
+    }
+
+    writeInt(1); // Length of Int32List
+    writeInt(1); // RecordNum = 1.
+
+    return newIncomingParcel(-1,
+                             RESPONSE_TYPE_UNSOLICITED,
+                             UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM,
+                             data);
+  }
+
+  function do_test() {
+    worker.onRILMessage(0, newSmsOnSimParcel());
+
+    let postedMessage = workerHelper.postedMessage;
+
+    do_check_eq("sms-received", postedMessage.rilMessageType);
+    do_check_eq("+0123456789", postedMessage.SMSC);
+    do_check_eq("+9876543210", postedMessage.sender);
+    do_check_eq("How are you?", postedMessage.body);
+  }
+
+  do_test();
+
+  run_next_test();
+});
+
+
--- a/dom/system/gonk/tests/test_ril_worker_mmi.js
+++ b/dom/system/gonk/tests/test_ril_worker_mmi.js
@@ -2,357 +2,32 @@
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 subscriptLoader.loadSubScript("resource://gre/modules/ril_consts.js", this);
 
 function run_test() {
   run_next_test();
 }
 
-function parseMMI(mmi) {
-  let worker = newWorker({
-    postRILMessage: function(data) {
-      // Do nothing
-    },
-    postMessage: function(message) {
-      // Do nothing
-    }
-  });
-  let context = worker.ContextPool._contexts[0];
-  return context.RIL._parseMMI(mmi);
-}
-
-function getWorker() {
-  let _postedMessage;
-  let _worker = newWorker({
-    postRILMessage: function(data) {
-    },
-    postMessage: function(message) {
-      _postedMessage = message;
-    },
-  });
-
-  return {
-    get postedMessage() {
-      return _postedMessage;
-    },
-    get worker() {
-      return _worker;
-    }
-  };
-}
-
 function testSendMMI(mmi, error) {
-  let workerhelper = getWorker();
+  let workerhelper = newInterceptWorker();
   let worker = workerhelper.worker;
   let context = worker.ContextPool._contexts[0];
 
   do_print("worker.postMessage " + worker.postMessage);
 
   context.RIL.radioState = GECKO_RADIOSTATE_READY;
   context.RIL.sendMMI({rilMessageType: "sendMMI", mmi: mmi});
 
   let postedMessage = workerhelper.postedMessage;
 
   do_check_eq(postedMessage.rilMessageType, "sendMMI");
   do_check_eq(postedMessage.errorMsg, error);
 }
 
-add_test(function test_parseMMI_empty() {
-  let mmi = parseMMI("");
-
-  do_check_null(mmi);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_undefined() {
-  let mmi = parseMMI();
-
-  do_check_null(mmi);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_one_digit_short_code() {
-  let mmi = parseMMI("1");
-
-  do_check_eq(mmi.fullMMI, "1");
-  do_check_eq(mmi.procedure, undefined);
-  do_check_eq(mmi.serviceCode, undefined);
-  do_check_eq(mmi.sia, undefined);
-  do_check_eq(mmi.sib, undefined);
-  do_check_eq(mmi.sic, undefined);
-  do_check_eq(mmi.pwd, undefined);
-  do_check_eq(mmi.dialNumber, undefined);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_invalid_short_code() {
-  let mmi = parseMMI("11");
-
-  do_check_null(mmi);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_short_code() {
-  let mmi = parseMMI("21");
-
-  do_check_eq(mmi.fullMMI, "21");
-  do_check_eq(mmi.procedure, undefined);
-  do_check_eq(mmi.serviceCode, undefined);
-  do_check_eq(mmi.sia, undefined);
-  do_check_eq(mmi.sib, undefined);
-  do_check_eq(mmi.sic, undefined);
-  do_check_eq(mmi.pwd, undefined);
-  do_check_eq(mmi.dialNumber, undefined);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_dial_string() {
-  let mmi = parseMMI("12345");
-
-  do_check_null(mmi);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_USSD_without_asterisk_prefix() {
-  let mmi = parseMMI("123#");
-
-  do_check_eq(mmi.fullMMI, "123#");
-  do_check_eq(mmi.procedure, undefined);
-  do_check_eq(mmi.serviceCode, undefined);
-  do_check_eq(mmi.sia, undefined);
-  do_check_eq(mmi.sib, undefined);
-  do_check_eq(mmi.sic, undefined);
-  do_check_eq(mmi.pwd, undefined);
-  do_check_eq(mmi.dialNumber, undefined);
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_USSD() {
-  let mmi = parseMMI("*123#");
-
-  do_check_eq(mmi.fullMMI, "*123#");
-  do_check_eq(mmi.procedure, MMI_PROCEDURE_ACTIVATION);
-  do_check_eq(mmi.serviceCode, "123");
-  do_check_eq(mmi.sia, undefined);
-  do_check_eq(mmi.sib, undefined);
-  do_check_eq(mmi.sic, undefined);
-  do_check_eq(mmi.pwd, undefined);
-  do_check_eq(mmi.dialNumber, "");
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_sia() {
-  let mmi = parseMMI("*123*1#");
-
-  do_check_eq(mmi.fullMMI, "*123*1#");
-  do_check_eq(mmi.procedure, MMI_PROCEDURE_ACTIVATION);
-  do_check_eq(mmi.serviceCode, "123");
-  do_check_eq(mmi.sia, "1");
-  do_check_eq(mmi.sib, undefined);
-  do_check_eq(mmi.sic, undefined);
-  do_check_eq(mmi.pwd, undefined);
-  do_check_eq(mmi.dialNumber, "");
-
-  run_next_test();
-});
-
-add_test(function test_parseMMI_sib() {
-  let mmi = parseMMI("*123**1#");
-
-  do_check_eq(mmi.fullMMI, "*123**1#");
-  do_check_eq(mmi.procedure, MMI_PROCEDURE_ACTIVATION);
-  do_check_eq(mmi.serviceCode, "123");
-  do_check_eq(mmi.sia, "");
-  do_check_eq(mmi.sib, "1");
-  do_check_eq(mmi.sic, undefined);
-  do_check_e