Bug 761057 - Part 3: send M-Send.req, r=philikon
authorVicamo Yang <vyang@mozilla.com>
Thu, 26 Jul 2012 12:11:46 +0800
changeset 100526 13a837f5cba4738e9f5bca4a4b092f05f9a7d74d
parent 100525 7001e01f26ecf30487b51ed382a4faa4ae0afe89
child 100527 5ee7f05cfefff80766e67f740e2bf4f1753b82ac
push idunknown
push userunknown
push dateunknown
reviewersphilikon
bugs761057
milestone17.0a1
Bug 761057 - Part 3: send M-Send.req, r=philikon
dom/mms/src/ril/MmsPduHelper.jsm
dom/mms/src/ril/MmsService.js
dom/mms/src/ril/WspPduHelper.jsm
--- a/dom/mms/src/ril/MmsPduHelper.jsm
+++ b/dom/mms/src/ril/MmsPduHelper.jsm
@@ -1545,31 +1545,46 @@ const MMS_PDU_TYPES = (function () {
   function add(number, hasContent, mandatoryFields) {
     pdus[number] = {
       number: number,
       hasContent: hasContent,
       mandatoryFields: mandatoryFields,
     };
   }
 
+  add(MMS_PDU_TYPE_SEND_REQ, true, ["x-mms-message-type",
+                                    "x-mms-transaction-id",
+                                    "x-mms-mms-version",
+                                    "from",
+                                    "content-type"]);
+  add(MMS_PDU_TYPE_SEND_CONF, false, ["x-mms-message-type",
+                                      "x-mms-transaction-id",
+                                      "x-mms-mms-version",
+                                      "x-mms-response-status"]);
   add(MMS_PDU_TYPE_NOTIFICATION_IND, false, ["x-mms-message-type",
                                              "x-mms-transaction-id",
                                              "x-mms-mms-version",
                                              "x-mms-message-class",
                                              "x-mms-message-size",
                                              "x-mms-expiry",
                                              "x-mms-content-location"]);
   add(MMS_PDU_TYPE_RETRIEVE_CONF, true, ["x-mms-message-type",
                                          "x-mms-mms-version",
                                          "date",
                                          "content-type"]);
   add(MMS_PDU_TYPE_NOTIFYRESP_IND, false, ["x-mms-message-type",
                                            "x-mms-transaction-id",
                                            "x-mms-mms-version",
                                            "x-mms-status"]);
+  add(MMS_PDU_TYPE_DELIVERY_IND, false, ["x-mms-message-type",
+                                         "x-mms-mms-version",
+                                         "message-id",
+                                         "to",
+                                         "date",
+                                         "x-mms-status"]);
 
   return pdus;
 })();
 
 /**
  * Header field names and assigned numbers.
  *
  * @see OMA-TS-MMS_ENC-V1_3-20110913-A clause 7.4
--- a/dom/mms/src/ril/MmsService.js
+++ b/dom/mms/src/ril/MmsService.js
@@ -36,16 +36,20 @@ const CONFIG_SEND_REPORT_NEVER       = 0
 const CONFIG_SEND_REPORT_DEFAULT_NO  = 1;
 const CONFIG_SEND_REPORT_DEFAULT_YES = 2;
 const CONFIG_SEND_REPORT_ALWAYS      = 3;
 
 XPCOMUtils.defineLazyServiceGetter(this, "gpps",
                                    "@mozilla.org/network/protocol-proxy-service;1",
                                    "nsIProtocolProxyService");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gUUIDGenerator",
+                                   "@mozilla.org/uuid-generator;1",
+                                   "nsIUUIDGenerator");
+
 XPCOMUtils.defineLazyGetter(this, "MMS", function () {
   let MMS = {};
   Cu.import("resource://gre/modules/MmsPduHelper.jsm", MMS);
   return MMS;
 });
 
 /**
  * MmsService
@@ -223,16 +227,94 @@ MmsService.prototype = {
     // Optional fields
     headers["x-mms-report-allowed"] = ra;
 
     let istream = MMS.PduHelper.compose(null, {headers: headers});
     this.sendMmsRequest("POST", this.MMSC, istream);
   },
 
   /**
+   * Send M-Send.req to MMSC
+   */
+  sendSendRequest: function sendSendRequest(msg, callback) {
+    msg.headers["x-mms-message-type"] = MMS.MMS_PDU_TYPE_SEND_REQ;
+    if (!msg.headers["x-mms-transaction-id"]) {
+      // Create an unique transaction id
+      let tid = gUUIDGenerator.generateUUID().toString();
+      msg.headers["x-mms-transaction-id"] = tid;
+    }
+    msg.headers["x-mms-mms-version"] = MMS.MMS_VERSION;
+
+    // Let MMS Proxy Relay insert from address automatically for us
+    msg.headers["from"] = null;
+
+    msg.headers["date"] = new Date();
+    msg.headers["x-mms-message-class"] = "personal";
+    msg.headers["x-mms-expiry"] = 7 * 24 * 60 * 60;
+    msg.headers["x-mms-priority"] = 129;
+    msg.headers["x-mms-read-report"] = true;
+    msg.headers["x-mms-delivery-report"] = true;
+
+    let messageSize = 0;
+
+    if (msg.content) {
+      messageSize = msg.content.length;
+    } else if (msg.parts) {
+      for (let i = 0; i < msg.parts.length; i++) {
+        messageSize += msg.parts[i].content.length;
+      }
+
+      let contentType = {
+        params: {
+          // `The type parameter must be specified and its value is the MIME
+          // media type of the "root" body part.` ~ RFC 2387 clause 3.1
+          type: msg.parts[0].headers["content-type"].media,
+        },
+      };
+
+      // `The Content-Type in M-Send.req and M-Retrieve.conf SHALL be
+      // application/vnd.wap.multipart.mixed when there is no presentation, and
+      // application/vnd.wap.multipart.related SHALL be used when there is SMIL
+      // presentation available.` ~ OMA-TS-MMS_CONF-V1_3-20110913-A clause 10.2.1
+      if (contentType.params.type === "application/smil") {
+        contentType.media = "application/vnd.wap.multipart.related";
+
+        // `The start parameter, if given, is the content-ID of the compound
+        // object's "root".` ~ RFC 2387 clause 3.2
+        contentType.params.start = msg.parts[0].headers["content-id"];
+      } else {
+        contentType.media = "application/vnd.wap.multipart.mixed";
+      }
+
+      // Assign to Content-Type
+      msg.headers["content-type"] = contentType;
+    }
+
+    // Assign to X-Mms-Message-Size
+    msg.headers["x-mms-message-size"] = messageSize;
+
+    debug("msg: " + JSON.stringify(msg));
+
+    let istream = MMS.PduHelper.compose(null, msg);
+    if (!istream) {
+      debug("sendSendRequest: failed to compose M-Send.ind PDU");
+      callback(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
+      return;
+    }
+
+    this.sendMmsRequest("POST", this.MMSC, istream, (function (status, data) {
+      if (!data) {
+        callback(MMS.MMS_PDU_ERROR_PERMANENT_FAILURE, null);
+      } else if (!this.parseStreamAndDispatch(data, {msg: msg, callback: callback})) {
+        callback(MMS.MMS_PDU_RESPONSE_ERROR_UNSUPPORTED_MESSAGE, null);
+      }
+    }).bind(this));
+  },
+
+  /**
    * @param file
    *        A nsIFile object indicating where to save the data.
    * @param data
    *        An array of raw octets.
    * @param callback
    *        Callback function when I/O is done.
    *
    * @return An nsIRequest representing the copy operation returned by
@@ -312,31 +394,65 @@ MmsService.prototype = {
   parseStreamAndDispatch: function parseStreamAndDispatch(data, options) {
     let msg = MMS.PduHelper.parse(data, null);
     if (!msg) {
       return false;
     }
     debug("parseStreamAndDispatch: msg = " + JSON.stringify(msg));
 
     switch (msg.type) {
+      case MMS.MMS_PDU_TYPE_SEND_CONF:
+        this.handleSendConfirmation(msg, options);
+        break;
       case MMS.MMS_PDU_TYPE_NOTIFICATION_IND:
         this.handleNotificationIndication(msg, options);
         break;
       case MMS.MMS_PDU_TYPE_RETRIEVE_CONF:
         this.handleRetrieveConfirmation(msg, options);
         break;
+      case MMS.MMS_PDU_TYPE_DELIVERY_IND:
+        this.handleDeliveryIndication(msg, options);
+        break;
       default:
         debug("Unsupported X-MMS-Message-Type: " + msg.type);
         return false;
     }
 
     return true;
   },
 
   /**
+   * Handle incoming M-Send.conf PDU.
+   *
+   * @param msg
+   *        The M-Send.conf message object.
+   */
+  handleSendConfirmation: function handleSendConfirmation(msg, options) {
+    let status = msg.headers["x-mms-response-status"];
+    if (status == null) {
+      return;
+    }
+
+    if (status == MMS.MMS_PDU_ERROR_OK) {
+      // `This ID SHALL always be present after the MMS Proxy-Relay accepted
+      // the corresponding M-Send.req PDU. The ID enables a MMS Client to match
+      // delivery reports or read-report PDUs with previously sent MM.`
+      let messageId = msg.headers["message-id"];
+      options.msg.headers["message-id"] = messageId;
+    } else if ((status >= MMS.MMS_PDU_ERROR_TRANSIENT_FAILURE)
+               && (status < MMS.MMS_PDU_ERROR_PERMANENT_FAILURE)) {
+      return;
+    }
+
+    if (options.callback) {
+      options.callback(status, msg);
+    }
+  },
+
+  /**
    * Handle incoming M-Notification.ind PDU.
    *
    * @param msg
    *        The MMS message object.
    */
   handleNotificationIndication: function handleNotificationIndication(msg) {
     function callback(status, retr) {
       let tid = msg.headers["x-mms-transaction-id"];
@@ -392,16 +508,24 @@ MmsService.prototype = {
       callbackIfValid(status, msg);
       return;
     }
 
     this.saveMessageContent(msg, callbackIfValid.bind(null, MMS.MMS_PDU_ERROR_OK));
   },
 
   /**
+   * Handle incoming M-Delivery.ind PDU.
+   */
+  handleDeliveryIndication: function handleDeliveryIndication(msg) {
+    let messageId = msg.headers["message-id"];
+    debug("handleDeliveryIndication: got delivery report for " + messageId);
+  },
+
+  /**
    * Update proxyInfo & MMSC from preferences.
    *
    * @param enabled
    *        Enable or disable MMS proxy.
    */
   updateProxyInfo: function updateProxyInfo(enabled) {
     try {
       if (enabled) {
--- a/dom/mms/src/ril/WspPduHelper.jsm
+++ b/dom/mms/src/ril/WspPduHelper.jsm
@@ -2483,16 +2483,19 @@ const WSP_WELL_KNOWN_CONTENT_TYPES = (fu
     let entry = {
       type: type,
       number: number,
     };
     types[type] = types[number] = entry;
   }
 
   // Well Known Values
+  // Encoding Version: 1.1
+  add("application/vnd.wap.multipart.mixed", 0x23);
+
   // Encoding Version: 1.2
   add("application/vnd.wap.multipart.related", 0x33);
 
   // Encoding Version: 1.4
   add("application/vnd.wap.mms-message", 0x3E);
 
   return types;
 })();