Bug 937485 - [WebIcc] use Webidl enum for cardState. r=edgar,smaug
authorVicamo Yang <vyang@mozilla.com>
Wed, 03 Sep 2014 19:31:00 +0800
changeset 209435 957c83999c91f9f14bca2e9f23424de1617326ce
parent 209434 9900e904fc8ae57ba1d1294de7d58dd36bb70b32
child 209436 513216e37ce850afb656bbb91390a8c5af4d7a78
push id27617
push userkwierso@gmail.com
push dateWed, 08 Oct 2014 23:59:35 +0000
treeherdermozilla-central@f0bb13ef0ee4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersedgar, smaug
bugs937485
milestone35.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
Bug 937485 - [WebIcc] use Webidl enum for cardState. r=edgar,smaug
dom/icc/Assertions.cpp
dom/icc/Icc.cpp
dom/icc/Icc.h
dom/icc/interfaces/nsIIccProvider.idl
dom/icc/moz.build
dom/mobilemessage/gonk/MmsService.js
dom/system/gonk/RILContentHelper.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/nsIRadioInterfaceLayer.idl
dom/system/gonk/ril_consts.js
dom/system/gonk/tests/test_ril_worker_icc_CardState.js
dom/webidl/MozIcc.webidl
new file mode 100644
--- /dev/null
+++ b/dom/icc/Assertions.cpp
@@ -0,0 +1,49 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/dom/MozIccBinding.h"
+#include "nsIIccProvider.h"
+
+namespace mozilla {
+namespace dom {
+
+#define ASSERT_ICC_CARD_STATE_EQUALITY(webidlState, xpidlState) \
+  static_assert(static_cast<uint32_t>(IccCardState::webidlState) == nsIIccProvider::xpidlState, \
+                "IccCardState::" #webidlState " should equal to nsIIccProvider::" #xpidlState)
+
+ASSERT_ICC_CARD_STATE_EQUALITY(Unknown, CARD_STATE_UNKNOWN);
+ASSERT_ICC_CARD_STATE_EQUALITY(Ready, CARD_STATE_READY);
+ASSERT_ICC_CARD_STATE_EQUALITY(PinRequired, CARD_STATE_PIN_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(PukRequired, CARD_STATE_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(PermanentBlocked, CARD_STATE_PERMANENT_BLOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(PersonalizationInProgress, CARD_STATE_PERSONALIZATION_IN_PROGRESS);
+ASSERT_ICC_CARD_STATE_EQUALITY(PersonalizationReady, CARD_STATE_PERSONALIZATION_READY);
+ASSERT_ICC_CARD_STATE_EQUALITY(NetworkLocked, CARD_STATE_NETWORK_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(NetworkSubsetLocked, CARD_STATE_NETWORK_SUBSET_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(CorporateLocked, CARD_STATE_CORPORATE_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(ServiceProviderLocked, CARD_STATE_SERVICE_PROVIDER_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(SimPersonalizationLocked, CARD_STATE_SIM_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(NetworkPukRequired, CARD_STATE_NETWORK_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(NetworkSubsetPukRequired, CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(CorporatePukRequired, CARD_STATE_CORPORATE_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(ServiceProviderPukRequired, CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(SimPersonalizationPukRequired, CARD_STATE_SIM_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(Network1Locked, CARD_STATE_NETWORK1_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(Network2Locked, CARD_STATE_NETWORK2_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(HrpdNetworkLocked, CARD_STATE_HRPD_NETWORK_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimCorporateLocked, CARD_STATE_RUIM_CORPORATE_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimServiceProviderLocked, CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimPersonalizationLocked, CARD_STATE_RUIM_LOCKED);
+ASSERT_ICC_CARD_STATE_EQUALITY(Network1PukRequired, CARD_STATE_NETWORK1_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(Network2PukRequired, CARD_STATE_NETWORK2_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(HrpdNetworkPukRequired, CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimCorporatePukRequired, CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimServiceProviderPukRequired, CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(RuimPersonalizationPukRequired, CARD_STATE_RUIM_PUK_REQUIRED);
+ASSERT_ICC_CARD_STATE_EQUALITY(Illegal, CARD_STATE_ILLEGAL);
+
+#undef ASSERT_ICC_CARD_STATE_EQUALITY
+
+} // namespace dom
+} // namespace mozilla
--- a/dom/icc/Icc.cpp
+++ b/dom/icc/Icc.cpp
@@ -1,17 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/Icc.h"
 
 #include "mozilla/dom/DOMRequest.h"
 #include "mozilla/dom/IccInfo.h"
-#include "mozilla/dom/MozIccBinding.h"
 #include "mozilla/dom/MozStkCommandEvent.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsIIccInfo.h"
 #include "nsIIccProvider.h"
 #include "nsJSON.h"
 #include "nsRadioInterfaceLayer.h"
 #include "nsServiceManagerUtils.h"
 
@@ -131,29 +130,30 @@ Icc::WrapObject(JSContext* aCx)
 // MozIcc WebIDL
 
 void
 Icc::GetIccInfo(Nullable<OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo>& aIccInfo) const
 {
   aIccInfo = mIccInfo;
 }
 
-void
-Icc::GetCardState(nsString& aCardState) const
+Nullable<IccCardState>
+Icc::GetCardState() const
 {
-  aCardState.SetIsVoid(true);
+  Nullable<IccCardState> result;
 
-  if (!mProvider) {
-    return;
+  uint32_t cardState = nsIIccProvider::CARD_STATE_UNDETECTED;
+  if (mProvider &&
+      NS_SUCCEEDED(mProvider->GetCardState(mClientId, &cardState)) &&
+      cardState != nsIIccProvider::CARD_STATE_UNDETECTED) {
+    MOZ_ASSERT(cardState < static_cast<uint32_t>(IccCardState::EndGuard_));
+    result.SetValue(static_cast<IccCardState>(cardState));
   }
 
-  nsresult rv = mProvider->GetCardState(mClientId, aCardState);
-  if (NS_FAILED(rv)) {
-    aCardState.SetIsVoid(true);
-  }
+  return result;
 }
 
 void
 Icc::SendStkResponse(const JSContext* aCx, JS::Handle<JS::Value> aCommand,
                      JS::Handle<JS::Value> aResponse, ErrorResult& aRv)
 {
   if (!mProvider) {
     aRv.Throw(NS_ERROR_FAILURE);
--- a/dom/icc/Icc.h
+++ b/dom/icc/Icc.h
@@ -1,15 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Icc_h
 #define mozilla_dom_Icc_h
 
+#include "mozilla/dom/MozIccBinding.h" // For IccCardState
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/DOMEventTargetHelper.h"
 
 class nsIIccInfo;
 class nsIIccProvider;
 
 namespace mozilla {
 namespace dom {
@@ -52,18 +53,18 @@ public:
   // WrapperCache
   virtual JSObject*
   WrapObject(JSContext* aCx) MOZ_OVERRIDE;
 
   // MozIcc WebIDL
   void
   GetIccInfo(Nullable<OwningMozIccInfoOrMozGsmIccInfoOrMozCdmaIccInfo>& aIccInfo) const;
 
-  void
-  GetCardState(nsString& aCardState) const;
+  Nullable<IccCardState>
+  GetCardState() const;
 
   void
   SendStkResponse(const JSContext* aCx, JS::Handle<JS::Value> aCommand,
                   JS::Handle<JS::Value> aResponse, ErrorResult& aRv);
 
   void
   SendStkMenuSelection(uint16_t aItemIdentifier, bool aHelpRequested,
                        ErrorResult& aRv);
--- a/dom/icc/interfaces/nsIIccProvider.idl
+++ b/dom/icc/interfaces/nsIIccProvider.idl
@@ -15,36 +15,72 @@ interface nsIIccListener : nsISupports
   void notifyStkSessionEnd();
   void notifyCardStateChanged();
   void notifyIccInfoChanged();
 };
 
 /**
  * XPCOM component (in the content process) that provides the ICC information.
  */
-[scriptable, uuid(1afa72d0-3d70-11e4-916c-0800200c9a66)]
+[scriptable, uuid(bf802bf0-4df2-11e4-916c-0800200c9a66)]
 interface nsIIccProvider : nsISupports
 {
+  // MUST match enum IccCardState in MozIcc.webidl!
+  const unsigned long CARD_STATE_UNKNOWN = 0;
+  const unsigned long CARD_STATE_READY = 1;
+  const unsigned long CARD_STATE_PIN_REQUIRED = 2;
+  const unsigned long CARD_STATE_PUK_REQUIRED = 3;
+  const unsigned long CARD_STATE_PERMANENT_BLOCKED = 4;
+  const unsigned long CARD_STATE_PERSONALIZATION_IN_PROGRESS = 5;
+  const unsigned long CARD_STATE_PERSONALIZATION_READY = 6;
+  const unsigned long CARD_STATE_NETWORK_LOCKED = 7;
+  const unsigned long CARD_STATE_NETWORK_SUBSET_LOCKED = 8;
+  const unsigned long CARD_STATE_CORPORATE_LOCKED = 9;
+  const unsigned long CARD_STATE_SERVICE_PROVIDER_LOCKED = 10;
+  const unsigned long CARD_STATE_SIM_LOCKED = 11;
+  const unsigned long CARD_STATE_NETWORK_PUK_REQUIRED = 12;
+  const unsigned long CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
+  const unsigned long CARD_STATE_CORPORATE_PUK_REQUIRED = 14;
+  const unsigned long CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
+  const unsigned long CARD_STATE_SIM_PUK_REQUIRED = 16;
+  const unsigned long CARD_STATE_NETWORK1_LOCKED = 17;
+  const unsigned long CARD_STATE_NETWORK2_LOCKED = 18;
+  const unsigned long CARD_STATE_HRPD_NETWORK_LOCKED = 19;
+  const unsigned long CARD_STATE_RUIM_CORPORATE_LOCKED = 20;
+  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
+  const unsigned long CARD_STATE_RUIM_LOCKED = 22;
+  const unsigned long CARD_STATE_NETWORK1_PUK_REQUIRED = 23;
+  const unsigned long CARD_STATE_NETWORK2_PUK_REQUIRED = 24;
+  const unsigned long CARD_STATE_HRPD_NETWORK_PUK_REQUIRED = 25;
+  const unsigned long CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
+  const unsigned long CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
+  const unsigned long CARD_STATE_RUIM_PUK_REQUIRED = 28;
+  const unsigned long CARD_STATE_ILLEGAL = 29;
+
+  const unsigned long CARD_STATE_UNDETECTED = 4294967295; // UINT32_MAX
+
   /**
    * Called when a content process registers receiving unsolicited messages from
    * RadioInterfaceLayer in the chrome process. Only a content process that has
    * the 'mobileconnection' permission is allowed to register.
    */
   void registerIccMsg(in unsigned long clientId, in nsIIccListener listener);
   void unregisterIccMsg(in unsigned long clientId, in nsIIccListener listener);
 
   /**
    * UICC Information
    */
   nsIIccInfo getIccInfo(in unsigned long clientId);
 
   /**
    * Card State
+   *
+   * One of the nsIIccProvider.CARD_STATE_* values.
    */
-  DOMString getCardState(in unsigned long clientId);
+  unsigned long getCardState(in unsigned long clientId);
 
   /**
    * STK interfaces.
    */
   void sendStkResponse(in unsigned long clientId,
                        in nsIDOMWindow window,
                        in jsval command,
                        in jsval response);
--- a/dom/icc/moz.build
+++ b/dom/icc/moz.build
@@ -8,16 +8,17 @@ DIRS += ['interfaces']
 
 EXPORTS.mozilla.dom += [
     'Icc.h',
     'IccInfo.h',
     'IccManager.h',
 ]
 
 UNIFIED_SOURCES += [
+    'Assertions.cpp',
     'Icc.cpp',
     "IccInfo.cpp",
     'IccListener.cpp',
     'IccManager.cpp',
 ]
 
 FAIL_ON_WARNINGS = True
 
--- a/dom/mobilemessage/gonk/MmsService.js
+++ b/dom/mobilemessage/gonk/MmsService.js
@@ -415,17 +415,18 @@ MmsConnection.prototype = {
     // MMS request and try to setup the MMS network first.
     if (!this.connected) {
       this.pendingCallbacks.push(callback);
 
       let errorStatus;
       if (getRadioDisabledState()) {
         if (DEBUG) debug("Error! Radio is disabled when sending MMS.");
         errorStatus = _HTTP_STATUS_RADIO_DISABLED;
-      } else if (this.radioInterface.rilContext.cardState != "ready") {
+      } else if (this.radioInterface.rilContext.cardState !=
+                 Ci.nsIIccProvider.CARD_STATE_READY) {
         if (DEBUG) debug("Error! SIM card is not ready when sending MMS.");
         errorStatus = _HTTP_STATUS_NO_SIM_CARD;
       }
       if (errorStatus != null) {
         this.flushPendingCallbacks(errorStatus);
         return true;
       }
 
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -154,18 +154,18 @@ function RILContentHelper() {
   this.updateDebugFlag();
 
   this.numClients = gNumRadioInterfaces;
   if (DEBUG) debug("Number of clients: " + this.numClients);
 
   this.rilContexts = [];
   for (let clientId = 0; clientId < this.numClients; clientId++) {
     this.rilContexts[clientId] = {
-      cardState:            RIL.GECKO_CARDSTATE_UNKNOWN,
-      iccInfo:              null
+      cardState: Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
+      iccInfo: null
     };
   }
 
   this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   this._windowsMap = [];
   this._iccListeners = [];
 
   Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -495,18 +495,18 @@ XPCOMUtils.defineLazyGetter(this, "gRadi
           numCards++;
         }
       }
       return numCards;
     },
 
     _isCardPresentAtClient: function(clientId) {
       let cardState = _ril.getRadioInterface(clientId).rilContext.cardState;
-      return cardState !== RIL.GECKO_CARDSTATE_UNDETECTED &&
-             cardState !== RIL.GECKO_CARDSTATE_UNKNOWN;
+      return cardState !== Ci.nsIIccProvider.CARD_STATE_UNDETECTED &&
+             cardState !== Ci.nsIIccProvider.CARD_STATE_UNKNOWN;
     },
 
     _isRadioAbleToEnableAtClient: function(clientId, numCards) {
       if (!RILQUIRKS_RADIO_OFF_WO_CARD) {
         return true;
       }
 
       // We could only turn on the radio for clientId if
@@ -1795,17 +1795,17 @@ function RadioInterface(aClientId, aWork
   this.workerMessenger = {
     send: aWorkerMessenger.send.bind(aWorkerMessenger, aClientId),
     sendWithIPCMessage:
       aWorkerMessenger.sendWithIPCMessage.bind(aWorkerMessenger, aClientId),
   };
   aWorkerMessenger.registerClient(aClientId, this);
 
   this.rilContext = {
-    cardState:      RIL.GECKO_CARDSTATE_UNKNOWN,
+    cardState:      Ci.nsIIccProvider.CARD_STATE_UNKNOWN,
     iccInfo:        null,
     imsi:           null
   };
 
   this.operatorInfo = {};
 
   let lock = gSettingsService.createLock();
 
@@ -3631,17 +3631,17 @@ RadioInterface.prototype = {
       if (!PhoneNumberUtils.isPlainPhoneNumber(options.number)) {
         if (DEBUG) this.debug("Error! Address is invalid when sending SMS: " +
                               options.number);
         errorCode = Ci.nsIMobileMessageCallback.INVALID_ADDRESS_ERROR;
       } else if (radioState == null ||
                  radioState == RIL.GECKO_RADIOSTATE_DISABLED) {
         if (DEBUG) this.debug("Error! Radio is disabled when sending SMS.");
         errorCode = Ci.nsIMobileMessageCallback.RADIO_DISABLED_ERROR;
-      } else if (this.rilContext.cardState != "ready") {
+      } else if (this.rilContext.cardState != Ci.nsIIccProvider.CARD_STATE_READY) {
         if (DEBUG) this.debug("Error! SIM card is not ready when sending SMS.");
         errorCode = Ci.nsIMobileMessageCallback.NO_SIM_CARD_ERROR;
       }
       if (errorCode) {
         if (silent) {
           request.notifySendMessageFailed(errorCode, domMessage);
           return;
         }
--- a/dom/system/gonk/nsIRadioInterfaceLayer.idl
+++ b/dom/system/gonk/nsIRadioInterfaceLayer.idl
@@ -18,20 +18,23 @@ interface nsIRilNetworkInterface : nsINe
   readonly attribute DOMString iccId;
 
   /* The following attributes are for MMS proxy settings. */
   readonly attribute DOMString mmsc;     // Empty string if not set.
   readonly attribute DOMString mmsProxy; // Empty string if not set.
   readonly attribute long      mmsPort;  // -1 if not set.
 };
 
-[scriptable, uuid(08a69c70-34b1-11e4-8c21-0800200c9a66)]
+[scriptable, uuid(4441e660-4ad0-11e4-916c-0800200c9a66)]
 interface nsIRilContext : nsISupports
 {
-  readonly attribute DOMString cardState;
+  /**
+   * One of the nsIIccProvider.CARD_STATE_* values.
+   */
+  readonly attribute unsigned long cardState;
 
   readonly attribute DOMString imsi;
 
   readonly attribute nsIIccInfo iccInfo;
 };
 
 [scriptable, function, uuid(3bc96351-53b0-47a1-a888-c74c64b60f25)]
 interface nsIRilSendWorkerMessageCallback : nsISupports
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -2487,48 +2487,50 @@ this.CALL_FAIL_ERROR_UNSPECIFIED = 0xfff
 
 // Other Gecko-specific constants
 this.GECKO_RADIOSTATE_UNKNOWN   = null;
 this.GECKO_RADIOSTATE_ENABLING  = "enabling";
 this.GECKO_RADIOSTATE_ENABLED   = "enabled";
 this.GECKO_RADIOSTATE_DISABLING = "disabling";
 this.GECKO_RADIOSTATE_DISABLED  = "disabled";
 
-this.GECKO_CARDSTATE_UNINITIALIZED                 = "uninitialized";
-this.GECKO_CARDSTATE_UNDETECTED                    = null;
-this.GECKO_CARDSTATE_ILLEGAL                       = "illegal";
-this.GECKO_CARDSTATE_UNKNOWN                       = "unknown";
-this.GECKO_CARDSTATE_PIN_REQUIRED                  = "pinRequired";
-this.GECKO_CARDSTATE_PUK_REQUIRED                  = "pukRequired";
-this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS   = "personalizationInProgress";
-this.GECKO_CARDSTATE_PERSONALIZATION_READY         = "personalizationReady";
-this.GECKO_CARDSTATE_NETWORK_LOCKED                = "networkLocked";
-this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED         = "networkSubsetLocked";
-this.GECKO_CARDSTATE_NETWORK1_LOCKED               = "network1Locked";
-this.GECKO_CARDSTATE_NETWORK2_LOCKED               = "network2Locked";
-this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED           = "hrpdNetworkLocked";
-this.GECKO_CARDSTATE_CORPORATE_LOCKED              = "corporateLocked";
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED       = "serviceProviderLocked";
-this.GECKO_CARDSTATE_SIM_LOCKED                    = "simPersonalizationLock";
-this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED         = "ruimCorporateLocked";
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED  = "ruimServiceProviderLocked";
-this.GECKO_CARDSTATE_RUIM_LOCKED                   = "ruimPersonalizationLock";
-this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED          = "networkPukRequired";
-this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED   = "networkSubsetPukRequired";
-this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED         = "network1PukRequired";
-this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED         = "network2PukRequired";
-this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED     = "hrpdNetworkPukRequired";
-this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED        = "corporatePukRequired";
-this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = "serviceProviderPukRequired";
-this.GECKO_CARDSTATE_SIM_PUK_REQUIRED              = "simPersonalizationPukRequired";
-this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED   = "ruimCorporatePukRequired";
-this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = "ruimServiceProviderPukRequired";
-this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED             = "ruimPersonalizationPukRequired";
-this.GECKO_CARDSTATE_READY                         = "ready";
-this.GECKO_CARDSTATE_PERMANENT_BLOCKED             = "permanentBlocked";
+// Only used in ril_worker.js
+this.GECKO_CARDSTATE_UNINITIALIZED = 4294967294; // UINT32_MAX - 1
+// See nsIIccProvider::CARD_STATE_*
+this.GECKO_CARDSTATE_UNDETECTED = 4294967295; // UINT32_MAX
+this.GECKO_CARDSTATE_UNKNOWN = 0;
+this.GECKO_CARDSTATE_READY = 1;
+this.GECKO_CARDSTATE_PIN_REQUIRED = 2;
+this.GECKO_CARDSTATE_PUK_REQUIRED = 3;
+this.GECKO_CARDSTATE_PERMANENT_BLOCKED = 4;
+this.GECKO_CARDSTATE_PERSONALIZATION_IN_PROGRESS = 5;
+this.GECKO_CARDSTATE_PERSONALIZATION_READY = 6;
+this.GECKO_CARDSTATE_NETWORK_LOCKED = 7;
+this.GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED = 8;
+this.GECKO_CARDSTATE_CORPORATE_LOCKED = 9;
+this.GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED = 10;
+this.GECKO_CARDSTATE_SIM_LOCKED = 11;
+this.GECKO_CARDSTATE_NETWORK_PUK_REQUIRED = 12;
+this.GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED = 13;
+this.GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED = 14;
+this.GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED = 15;
+this.GECKO_CARDSTATE_SIM_PUK_REQUIRED = 16;
+this.GECKO_CARDSTATE_NETWORK1_LOCKED = 17;
+this.GECKO_CARDSTATE_NETWORK2_LOCKED = 18;
+this.GECKO_CARDSTATE_HRPD_NETWORK_LOCKED = 19;
+this.GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED = 20;
+this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED = 21;
+this.GECKO_CARDSTATE_RUIM_LOCKED = 22;
+this.GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED = 23;
+this.GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED = 24;
+this.GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED = 25;
+this.GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED = 26;
+this.GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED = 27;
+this.GECKO_CARDSTATE_RUIM_PUK_REQUIRED = 28;
+this.GECKO_CARDSTATE_ILLEGAL = 29;
 
 this.GECKO_CARDLOCK_PIN      = "pin";
 this.GECKO_CARDLOCK_PIN2     = "pin2";
 this.GECKO_CARDLOCK_PUK      = "puk";
 this.GECKO_CARDLOCK_PUK2     = "puk2";
 this.GECKO_CARDLOCK_FDN      = "fdn";
 this.GECKO_CARDLOCK_NCK      = "nck";
 this.GECKO_CARDLOCK_NCK1     = "nck1";
@@ -2556,16 +2558,17 @@ PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NE
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET] = GECKO_CARDSTATE_NETWORK_SUBSET_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE] = GECKO_CARDSTATE_CORPORATE_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM] = GECKO_CARDSTATE_SIM_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_PUK] = GECKO_CARDSTATE_NETWORK_PUK_REQUIRED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK] = GECKO_CARDSTATE_NETWORK_SUBSET_PUK_REQUIRED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK] = GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK] = GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED;
+PERSONSUBSTATE[CARD_PERSOSUBSTATE_SIM_SIM_PUK] = GECKO_CARDSTATE_SIM_PUK_REQUIRED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1] = GECKO_CARDSTATE_NETWORK1_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2] = GECKO_CARDSTATE_NETWORK2_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_HRPD] = GECKO_CARDSTATE_HRPD_NETWORK_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_CORPORATE] = GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER] = GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_RUIM] = GECKO_CARDSTATE_RUIM_LOCKED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK] = GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED;
 PERSONSUBSTATE[CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK] = GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED;
--- a/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc_CardState.js
@@ -28,55 +28,75 @@ add_test(function test_personalization_s
 
     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);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK_LOCKED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET,
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK_SUBSET_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE,
-                      GECKO_CARDSTATE_CORPORATE_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_CORPORATE_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER,
-                      GECKO_CARDSTATE_SERVICE_PROVIDER_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_SERVICE_PROVIDER_LOCKED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM,
+                      Ci.nsIIccProvider.CARD_STATE_SIM_LOCKED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_PUK,
-                      GECKO_CARDSTATE_NETWORK_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK_PUK_REQUIRED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_NETWORK_SUBSET_PUK,
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK_SUBSET_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_CORPORATE_PUK,
-                      GECKO_CARDSTATE_CORPORATE_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_CORPORATE_PUK_REQUIRED);
   testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SERVICE_PROVIDER_PUK,
-                      GECKO_CARDSTATE_SERVICE_PROVIDER_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_SERVICE_PROVIDER_PUK_REQUIRED);
+  testPersonalization(false, CARD_PERSOSUBSTATE_SIM_SIM_PUK,
+                      Ci.nsIIccProvider.CARD_STATE_SIM_PUK_REQUIRED);
+
+  testPersonalization(false, CARD_PERSOSUBSTATE_UNKNOWN,
+                      Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+  testPersonalization(false, CARD_PERSOSUBSTATE_IN_PROGRESS,
+                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
   testPersonalization(false, CARD_PERSOSUBSTATE_READY,
-                      GECKO_CARDSTATE_PERSONALIZATION_READY);
+                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_READY);
 
   // Test CDMA personalization state.
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1,
-                      GECKO_CARDSTATE_NETWORK1_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK1_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2,
-                      GECKO_CARDSTATE_NETWORK2_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK2_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD,
-                      GECKO_CARDSTATE_HRPD_NETWORK_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_HRPD_NETWORK_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE,
-                      GECKO_CARDSTATE_RUIM_CORPORATE_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_CORPORATE_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER,
-                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_SERVICE_PROVIDER_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM,
-                      GECKO_CARDSTATE_RUIM_LOCKED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_LOCKED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK1_PUK,
-                      GECKO_CARDSTATE_NETWORK1_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK1_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_NETWORK2_PUK,
-                      GECKO_CARDSTATE_NETWORK2_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_NETWORK2_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_HRPD_PUK,
-                      GECKO_CARDSTATE_HRPD_NETWORK_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_HRPD_NETWORK_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_CORPORATE_PUK,
-                      GECKO_CARDSTATE_RUIM_CORPORATE_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_CORPORATE_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_SERVICE_PROVIDER_PUK,
-                      GECKO_CARDSTATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_SERVICE_PROVIDER_PUK_REQUIRED);
   testPersonalization(true, CARD_PERSOSUBSTATE_RUIM_RUIM_PUK,
-                      GECKO_CARDSTATE_RUIM_PUK_REQUIRED);
+                      Ci.nsIIccProvider.CARD_STATE_RUIM_PUK_REQUIRED);
+
+  testPersonalization(true, CARD_PERSOSUBSTATE_UNKNOWN,
+                      Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
+  testPersonalization(true, CARD_PERSOSUBSTATE_IN_PROGRESS,
+                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_IN_PROGRESS);
+  testPersonalization(true, CARD_PERSOSUBSTATE_READY,
+                      Ci.nsIIccProvider.CARD_STATE_PERSONALIZATION_READY);
 
   run_next_test();
 });
 
 /**
  * Verify SIM app_state in _processICCStatus
  */
 add_test(function test_card_app_state() {
@@ -96,27 +116,27 @@ add_test(function test_card_app_state() 
       }],
     };
 
     ril._processICCStatus(iccStatus);
     do_check_eq(ril.cardState, geckoCardState);
   }
 
   testCardAppState(CARD_APPSTATE_ILLEGAL,
-                   GECKO_CARDSTATE_ILLEGAL);
+                   Ci.nsIIccProvider.CARD_STATE_ILLEGAL);
   testCardAppState(CARD_APPSTATE_PIN,
-                   GECKO_CARDSTATE_PIN_REQUIRED);
+                   Ci.nsIIccProvider.CARD_STATE_PIN_REQUIRED);
   testCardAppState(CARD_APPSTATE_PUK,
-                   GECKO_CARDSTATE_PUK_REQUIRED);
+                   Ci.nsIIccProvider.CARD_STATE_PUK_REQUIRED);
   testCardAppState(CARD_APPSTATE_READY,
-                   GECKO_CARDSTATE_READY);
+                   Ci.nsIIccProvider.CARD_STATE_READY);
   testCardAppState(CARD_APPSTATE_UNKNOWN,
-                   GECKO_CARDSTATE_UNKNOWN);
+                   Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
   testCardAppState(CARD_APPSTATE_DETECTED,
-                   GECKO_CARDSTATE_UNKNOWN);
+                   Ci.nsIIccProvider.CARD_STATE_UNKNOWN);
 
   run_next_test();
 });
 
 /**
  * Verify permanent blocked for ICC.
  */
 add_test(function test_icc_permanent_blocked() {
@@ -134,17 +154,17 @@ add_test(function test_icc_permanent_blo
       apps: [
       {
         pin1_replaced: pin1_replaced,
         pin1: pin1
       }]
     };
 
     ril._processICCStatus(iccStatus);
-    do_check_eq(ril.cardState, GECKO_CARDSTATE_PERMANENT_BLOCKED);
+    do_check_eq(ril.cardState, Ci.nsIIccProvider.CARD_STATE_PERMANENT_BLOCKED);
   }
 
   testPermanentBlocked(1,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED,
                        CARD_PINSTATE_UNKNOWN);
   testPermanentBlocked(1,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED,
                        CARD_PINSTATE_ENABLED_PERM_BLOCKED);
--- a/dom/webidl/MozIcc.webidl
+++ b/dom/webidl/MozIcc.webidl
@@ -1,12 +1,59 @@
 /* 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/. */
 
+enum IccCardState {
+  "unknown", // ICC card state is either not yet reported from modem or in an
+             // unknown state.
+  "ready",
+  "pinRequired",
+  "pukRequired",
+  "permanentBlocked",
+
+  /**
+   * Personalization States
+   */
+  "personalizationInProgress",
+  "personalizationReady",
+
+  // SIM Personalization States.
+  "networkLocked",
+  "networkSubsetLocked",
+  "corporateLocked",
+  "serviceProviderLocked",
+  "simPersonalizationLocked",
+  "networkPukRequired",
+  "networkSubsetPukRequired",
+  "corporatePukRequired",
+  "serviceProviderPukRequired",
+  "simPersonalizationPukRequired",
+
+  // RUIM Personalization States.
+  "network1Locked",
+  "network2Locked",
+  "hrpdNetworkLocked",
+  "ruimCorporateLocked",
+  "ruimServiceProviderLocked",
+  "ruimPersonalizationLocked",
+  "network1PukRequired",
+  "network2PukRequired",
+  "hrpdNetworkPukRequired",
+  "ruimCorporatePukRequired",
+  "ruimServiceProviderPukRequired",
+  "ruimPersonalizationPukRequired",
+
+  /**
+   * Additional States.
+   */
+  "illegal" // See Bug 916000. An owed pay card will be rejected by the network
+            // and fall in this state.
+};
+
 [Pref="dom.icc.enabled"]
 interface MozIcc : EventTarget
 {
   // Integrated Circuit Card Information.
 
   /**
    * Information stored in the device's ICC.
    *
@@ -22,31 +69,21 @@ interface MozIcc : EventTarget
    */
   attribute EventHandler oniccinfochange;
 
   // Integrated Circuit Card State.
 
   /**
    * Indicates the state of the device's ICC.
    *
-   * Possible values: 'illegal', 'unknown', 'pinRequired', 'pukRequired',
-   * 'personalizationInProgress', 'networkLocked', 'network1Locked',
-   * 'network2Locked', 'hrpdNetworkLocked', 'corporateLocked',
-   * 'serviceProviderLocked', 'ruimCorporateLocked', 'ruimServiceProviderLocked',
-   * 'networkPukRequired', 'network1PukRequired', 'network2PukRequired',
-   * 'hrpdNetworkPukRequired', 'corporatePukRequired',
-   * 'serviceProviderPukRequired', 'ruimCorporatePukRequired',
-   * 'ruimServiceProviderPukRequired', 'personalizationReady', 'ready',
-   * 'permanentBlocked'.
-   *
    * Once the ICC becomes undetectable, cardstatechange event will be notified.
    * Also, the attribute is set to null and this MozIcc object becomes invalid.
    * Calling asynchronous functions raises exception then.
    */
-  readonly attribute DOMString? cardState;
+  readonly attribute IccCardState? cardState;
 
   /**
    * The 'cardstatechange' event is notified when the 'cardState' attribute
    * changes value.
    */
   attribute EventHandler oncardstatechange;
 
   // Integrated Circuit Card STK.