Bug 912902 - MMS/SMS: retrieve GSM MSISDN / CDMA MDN correctly. r=gene
authorEdgar Chen <echen@mozilla.com>
Tue, 15 Oct 2013 10:42:49 +0800
changeset 165989 ae5e6dc9bce92cf626de6a8b1065ad49d90f22d1
parent 165988 e6965ee39a3890455ea966fa1c1e19720ea6d531
child 165990 b082b86b2cacb56a7e27c789afbfd764fa447234
child 166018 225f31353528490cff5287c68f5cfcf2c83bae81
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgene
bugs912902
milestone27.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 912902 - MMS/SMS: retrieve GSM MSISDN / CDMA MDN correctly. r=gene
dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl
dom/mobilemessage/src/gonk/MmsService.js
dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
dom/system/gonk/RadioInterfaceLayer.js
--- a/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl
+++ b/dom/mobilemessage/interfaces/nsIRilMobileMessageDatabaseService.idl
@@ -37,17 +37,17 @@ interface nsIRilMobileMessageDatabaseSer
    *   - If |type| == "sms", we also need:
    *     - |messageClass| DOMString: the message class of received message
    *     - |receiver| DOMString: the phone number of receiver
    *
    *   - If |type| == "mms", we also need:
    *     - |delivery| DOMString: the delivery state of received message
    *     - |deliveryStatus| DOMString Array: the delivery status of received message
    *     - |receivers| DOMString Array: the phone numbers of receivers
-   *     - |msisdn| DOMString: [optional] my own phone number.
+   *     - |phoneNumber| DOMString: [optional] my own phone number.
    *     - |transactionId| DOMString: the transaction ID from MMS PDU header.
    *
    * Note: |deliveryStatus| should only contain single string to specify
    *       the delivery status of MMS message for the phone owner self.
    */
   long saveReceivedMessage(in jsval aMessage,
                 [optional] in nsIRilMobileMessageDatabaseCallback aCallback);
 
--- a/dom/mobilemessage/src/gonk/MmsService.js
+++ b/dom/mobilemessage/src/gonk/MmsService.js
@@ -1227,19 +1227,34 @@ MmsService.prototype = {
         || (config == CONFIG_SEND_REPORT_DEFAULT_YES)) {
       if (wish != null) {
         config += (wish ? 1 : -1);
       }
     }
     return config >= CONFIG_SEND_REPORT_DEFAULT_YES;
   },
 
-  getMsisdn: function getMsisdn() {
+  /**
+   * Get phone number from iccInfo.
+   *
+   * If the icc card is gsm card, the phone number is in msisdn.
+   * @see nsIDOMMozGsmIccInfo
+   *
+   * Otherwise, the phone number is in mdn.
+   * @see nsIDOMMozCdmaIccInfo
+   */
+  getPhoneNumber: function getPhoneNumber() {
     let iccInfo = gRadioInterface.rilContext.iccInfo;
-    let number = iccInfo ? iccInfo.msisdn : null;
+
+    if (!iccInfo) {
+      return null;
+    }
+
+    let number = (iccInfo instanceof Ci.nsIDOMMozGsmIccInfo)
+               ? iccInfo.msisdn : iccInfo.mdn;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (number === undefined || number === "undefined") {
       return null;
     }
     return number;
   },
@@ -1280,17 +1295,17 @@ MmsService.prototype = {
     intermediate.sender = null;
     intermediate.transactionId = intermediate.headers["x-mms-transaction-id"];
     if (intermediate.headers.from) {
       intermediate.sender = intermediate.headers.from.address;
     } else {
       intermediate.sender = "anonymous";
     }
     intermediate.receivers = [];
-    intermediate.msisdn = this.getMsisdn();
+    intermediate.phoneNumber = this.getPhoneNumber();
     return intermediate;
   },
 
   /**
    * Merge the retrieval confirmation into the savable message.
    *
    * @param intermediate
    *        Intermediate MMS message parsed from PDU, which carries
@@ -1766,17 +1781,17 @@ MmsService.prototype = {
         parts.push(part);
       }
     }
 
     // The following attributes are needed for saving message into DB.
     aMessage["type"] = "mms";
     aMessage["timestamp"] = Date.now();
     aMessage["receivers"] = receivers;
-    aMessage["sender"] = this.getMsisdn();
+    aMessage["sender"] = this.getPhoneNumber();
     try {
       aMessage["deliveryStatusRequested"] =
         Services.prefs.getBoolPref("dom.mms.requestStatusReport");
     } catch (e) {
       aMessage["deliveryStatusRequested"] = false;
     }
 
     if (DEBUG) debug("createSavableFromParams: aMessage: " +
--- a/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
+++ b/dom/mobilemessage/src/gonk/MobileMessageDatabaseService.js
@@ -1368,28 +1368,29 @@ MobileMessageDatabaseService.prototype =
       //    If the receivers contain single phone number, we don't need to
       //    add it into participants because we know that number is our own.
       // 3. receivers.length >= 2
       //    If the receivers contain multiple phone numbers, we need to add all
       //    of them but not the user's own number into participants.
       if (receivers.length >= 2) {
         let isSuccess = false;
         let slicedReceivers = receivers.slice();
-        if (aMessage.msisdn) {
-          let found = slicedReceivers.indexOf(aMessage.msisdn);
+        if (aMessage.phoneNumber) {
+          let found = slicedReceivers.indexOf(aMessage.phoneNumber);
           if (found !== -1) {
             isSuccess = true;
             slicedReceivers.splice(found, 1);
           }
         }
 
         if (!isSuccess) {
-          // For some SIMs we cannot retrieve the vaild MSISDN (i.e. the user's
-          // own phone number), so we cannot correcly exclude the user's own
-          // number from the receivers, thus wrongly building the thread index.
+          // For some SIMs we cannot retrieve the vaild MSISDN or MDN (i.e. the
+          // user's own phone number), so we cannot correcly exclude the user's
+          // own number from the receivers, thus wrongly building the thread
+          // index.
           if (DEBUG) debug("Error! Cannot strip out user's own phone number!");
         }
 
         threadParticipants = threadParticipants.concat(slicedReceivers);
       }
     }
 
     let timestamp = aMessage.timestamp;
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -42,16 +42,20 @@ function debug(s) {
 }
 
 const RADIOINTERFACELAYER_CID =
   Components.ID("{2d831c8d-6017-435b-a80c-e5d422810cea}");
 const RADIOINTERFACE_CID =
   Components.ID("{6a7c91f0-a2b3-4193-8562-8969296c0b54}");
 const RILNETWORKINTERFACE_CID =
   Components.ID("{3bdd52a9-3965-4130-b569-0ac5afed045e}");
+const GSMICCINFO_CID =
+  Components.ID("{d90c4261-a99d-47bc-8b05-b057bb7e8f8a}");
+const CDMAICCINFO_CID =
+  Components.ID("{39ba3c08-aacc-46d0-8c04-9b619c387061}");
 
 const kNetworkInterfaceStateChangedTopic = "network-interface-state-changed";
 const kSmsReceivedObserverTopic          = "sms-received";
 const kSilentSmsReceivedObserverTopic    = "silent-sms-received";
 const kSmsSendingObserverTopic           = "sms-sending";
 const kSmsSentObserverTopic              = "sms-sent";
 const kSmsFailedObserverTopic            = "sms-failed";
 const kSmsDeliverySuccessObserverTopic   = "sms-delivery-success";
@@ -458,16 +462,62 @@ XPCOMUtils.defineLazyGetter(this, "gMess
       this._sendTargetMessage("icc", message, {
         clientId: clientId,
         data: data
       });
     }
   };
 });
 
+function IccInfo() {}
+IccInfo.prototype = {
+  iccType: null,
+  iccid: null,
+  mcc: null,
+  mnc: null,
+  spn: null,
+  isDisplayNetworkNameRequired: null,
+  isDisplaySpnRequired: null
+};
+
+function GsmIccInfo() {}
+GsmIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozGsmIccInfo]),
+  classID: GSMICCINFO_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID:          GSMICCINFO_CID,
+    classDescription: "MozGsmIccInfo",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozGsmIccInfo]
+  }),
+
+  // nsIDOMMozGsmIccInfo
+
+  msisdn: null
+};
+
+function CdmaIccInfo() {}
+CdmaIccInfo.prototype = {
+  __proto__: IccInfo.prototype,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCdmaIccInfo]),
+  classID: CDMAICCINFO_CID,
+  classInfo: XPCOMUtils.generateCI({
+    classID:          CDMAICCINFO_CID,
+    classDescription: "MozCdmaIccInfo",
+    flags:            Ci.nsIClassInfo.DOM_OBJECT,
+    interfaces:       [Ci.nsIDOMMozCdmaIccInfo]
+  }),
+
+  // nsIDOMMozCdmaIccInfo
+
+  mdn: null,
+  min: null
+};
+
 function RadioInterfaceLayer() {
   gMessageManager.init(this);
 
   let options = {
     debug: debugPref,
     cellBroadcastDisabled: false,
     clirMode: RIL.CLIR_DEFAULT
   };
@@ -1044,19 +1094,37 @@ RadioInterface.prototype = {
         gSystemMessenger.broadcastMessage("cdma-info-rec-received", message);
         break;
       default:
         throw new Error("Don't know about this message type: " +
                         message.rilMessageType);
     }
   },
 
-  getMsisdn: function getMsisdn() {
+  /**
+   * Get phone number from iccInfo.
+   *
+   * If the icc card is gsm card, the phone number is in msisdn.
+   * @see nsIDOMMozGsmIccInfo
+   *
+   * Otherwise, the phone number is in mdn.
+   * @see nsIDOMMozCdmaIccInfo
+   */
+  getPhoneNumber: function getPhoneNumber() {
     let iccInfo = this.rilContext.iccInfo;
-    let number = iccInfo ? iccInfo.msisdn : null;
+
+    if (!iccInfo) {
+      return null;
+    }
+
+    // After moving SMS code out of RadioInterfaceLayer, we could use
+    // |iccInfo instanceof Ci.nsIDOMMozGsmIccInfo| here.
+    // TODO: Bug 873351 - B2G SMS: move SMS code out of RadioInterfaceLayer to
+    //                    SmsService
+    let number = (iccInfo instanceof GsmIccInfo) ? iccInfo.msisdn : iccInfo.mdn;
 
     // Workaround an xpconnect issue with undefined string objects.
     // See bug 808220
     if (number === undefined || number === "undefined") {
       return null;
     }
     return number;
   },
@@ -1739,17 +1807,17 @@ RadioInterface.prototype = {
 
     if (message.encoding == RIL.PDU_DCS_MSG_CODING_8BITS_ALPHABET) {
       // Don't know how to handle binary data yet.
       return true;
     }
 
     message.type = "sms";
     message.sender = message.sender || null;
-    message.receiver = this.getMsisdn();
+    message.receiver = this.getPhoneNumber();
     message.body = message.fullBody = message.fullBody || null;
     message.timestamp = Date.now();
 
     if (gSmsService.isSilentNumber(message.sender)) {
       message.id = -1;
       message.threadId = 0;
       message.delivery = DOM_MOBILE_MESSAGE_DELIVERY_RECEIVED;
       message.deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_SUCCESS;
@@ -1986,22 +2054,37 @@ RadioInterface.prototype = {
     voicemailInfo.number = message.number;
     voicemailInfo.displayName = message.alphaId;
 
     gMessageManager.sendVoicemailMessage("RIL:VoicemailInfoChanged",
                                          this.clientId, voicemailInfo);
   },
 
   handleIccInfoChange: function handleIccInfoChange(message) {
-    let oldIccInfo = this.rilContext.iccInfo;
-    this.rilContext.iccInfo = message;
-
-    if (!this.isInfoChanged(message, oldIccInfo)) {
-      return;
+    let oldSpn = this.rilContext.iccInfo ? this.rilContext.iccInfo.spn : null;
+
+    if (!message || !message.iccType) {
+      // Card is not detected, clear iccInfo to null.
+      this.rilContext.iccInfo = null;
+    } else {
+      if (!this.rilContext.iccInfo) {
+        if (message.iccType === "ruim" || message.iccType === "csim") {
+          this.rilContext.iccInfo = new CdmaIccInfo();
+        } else {
+          this.rilContext.iccInfo = new GsmIccInfo();
+        }
+      }
+
+      if (!this.isInfoChanged(message, this.rilContext.iccInfo)) {
+        return;
+      }
+
+      this.updateInfo(message, this.rilContext.iccInfo);
     }
+
     // RIL:IccInfoChanged corresponds to a DOM event that gets fired only
     // when iccInfo has changed.
     gMessageManager.sendIccMessage("RIL:IccInfoChanged",
                                    this.clientId,
                                    message.iccType ? message : null);
 
     // Update lastKnownSimMcc.
     if (message.mcc) {
@@ -2015,17 +2098,16 @@ RadioInterface.prototype = {
     if (message.mcc && message.mnc) {
       try {
         Services.prefs.setCharPref("ril.lastKnownHomeNetwork",
                                    message.mcc + "-" + message.mnc);
       } catch (e) {}
     }
 
     // If spn becomes available, we should check roaming again.
-    let oldSpn = oldIccInfo ? oldIccInfo.spn : null;
     if (!oldSpn && message.spn) {
       let voice = this.rilContext.voice;
       let data = this.rilContext.data;
       let voiceRoaming = voice.roaming;
       let dataRoaming = data.roaming;
       this.checkRoamingBetweenOperators(voice);
       this.checkRoamingBetweenOperators(data);
       if (voiceRoaming != voice.roaming) {
@@ -2940,17 +3022,17 @@ RadioInterface.prototype = {
 
         // Only keep current context if we have requested for delivery report.
         return context.requestStatusReport;
       }).bind(this, context)); // End of |workerMessenger.send| callback.
     }).bind(this); // End of DB saveSendingMessage callback.
 
     let sendingMessage = {
       type: "sms",
-      sender: this.getMsisdn(),
+      sender: this.getPhoneNumber(),
       receiver: number,
       body: message,
       deliveryStatusRequested: options.requestStatusReport,
       timestamp: Date.now()
     };
 
     if (silent) {
       let deliveryStatus = RIL.GECKO_SMS_DELIVERY_STATUS_PENDING;