Bug 912902 - MMS/SMS: retrieve GSM MSISDN / CDMA MDN correctly. r=gene, a=koi+
authorEdgar Chen <echen@mozilla.com>
Tue, 15 Oct 2013 10:42:49 +0800
changeset 160750 6dda5c6088a56782400ac99b20437b1c88ebd6f0
parent 160749 56ec10275771ca6bf470dbd9dcb8b1123f6eda6f
child 160751 34b2b21296940e932f2b713afc5fa9d3be6c2f86
push id2961
push userlsblakk@mozilla.com
push dateMon, 28 Oct 2013 21:59:28 +0000
treeherdermozilla-beta@73ef4f13486f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgene, koi
bugs912902
milestone26.0a2
Bug 912902 - MMS/SMS: retrieve GSM MSISDN / CDMA MDN correctly. r=gene, a=koi+
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
@@ -1220,19 +1220,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;
   },
@@ -1273,17 +1288,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
@@ -1759,17 +1774,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
@@ -1376,28 +1376,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
@@ -41,16 +41,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";
@@ -451,16 +455,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
   };
@@ -1027,19 +1077,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;
   },
@@ -1722,17 +1790,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;
@@ -1969,22 +2037,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) {
@@ -1998,17 +2081,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) {
@@ -2914,17 +2996,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;