Bug 1081789 - Redefine IccOpenChannel, IccCloseChannel & IccExchangeAPDU interfaces, in order to be accesible without a 'window' object. r=hsinyi, echen
authorSiddartha Pothapragada <Siddartha.Pothapragada@telekom.com>
Sat, 03 Jan 2015 13:15:00 +0800
changeset 247937 ab9fb3092d9f89d87766229fa81d94a23d7c0a1f
parent 247936 ce6b395d9b2ed45d5f1ccc4f957763ac43f5cd50
child 247938 355429828a63a801ff2bbd7d209798bcc1f1d041
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershsinyi, echen
bugs1081789
milestone37.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 1081789 - Redefine IccOpenChannel, IccCloseChannel & IccExchangeAPDU interfaces, in order to be accesible without a 'window' object. r=hsinyi, echen
dom/icc/interfaces/nsIIccProvider.idl
dom/system/gonk/RILContentHelper.js
--- a/dom/icc/interfaces/nsIIccProvider.idl
+++ b/dom/icc/interfaces/nsIIccProvider.idl
@@ -12,20 +12,58 @@ interface nsIIccInfo;
 interface nsIIccListener : nsISupports
 {
   void notifyStkCommand(in DOMString aMessage);
   void notifyStkSessionEnd();
   void notifyCardStateChanged();
   void notifyIccInfoChanged();
 };
 
+[scriptable, uuid(6136acab-b50e-494a-a86d-df392a032897)]
+interface nsIIccChannelCallback : nsISupports
+{
+  /**
+   * Callback function to notify on successfully opening a logical channel.
+   *
+   * @param channel
+   *        The Channel Number/Handle that is successfully opened.
+   */
+  void notifyOpenChannelSuccess(in long channel);
+
+  /**
+   * Callback function to notify on successfully closing the logical channel.
+   *
+   */
+  void notifyCloseChannelSuccess();
+
+  /**
+   * Callback function to notify the status of 'iccExchangeAPDU' command.
+   *
+   * @param sw1
+   *        Response's First Status Byte
+   * @param sw2
+   *        Response's Second Status Byte
+   * @param data
+   *        Response's data
+   */
+  void notifyExchangeAPDUResponse(in octet sw1,
+                                  in octet sw2,
+                                  in DOMString data);
+
+  /**
+   * Callback function to notify error
+   *
+   */
+  void notifyError(in DOMString error);
+};
+
 /**
  * XPCOM component (in the content process) that provides the ICC information.
  */
-[scriptable, uuid(c3e3c1a9-6ac4-4916-a777-7d49ffd89c46)]
+[scriptable, uuid(bf985ee1-14c9-43c6-a471-8ab52fb24b0d)]
 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;
@@ -161,31 +199,43 @@ interface nsIIccProvider : nsISupports
                                 in unsigned long contactType);
 
   nsIDOMDOMRequest updateContact(in unsigned long clientId,
                                  in nsIDOMWindow window,
                                  in unsigned long contactType,
                                  in jsval contact,
                                  in DOMString pin2);
 
-  /**
+/**
    * Secure Card Icc communication channel
    */
-  nsIDOMDOMRequest iccOpenChannel(in unsigned long clientId,
-                                  in nsIDOMWindow window,
-                                  in DOMString aid);
+  void iccOpenChannel(in unsigned long clientId,
+                      in DOMString aid,
+                      in nsIIccChannelCallback callback);
 
-  nsIDOMDOMRequest iccExchangeAPDU(in unsigned long clientId,
-                                   in nsIDOMWindow window,
-                                   in long channel,
-                                   in jsval apdu);
+  /**
+   * Exchange Command APDU (C-APDU) with SIM on the given logical channel.
+   * Note that 'P3' parameter could be Le/Lc depending on command APDU case.
+   * For Case 1 scenario (when only command header is present), the value
+   * of 'P3' should be set to '-1' explicitly.
+   * Refer to 3G TS 31.101 , 10.2 'Command APDU Structure' for all the cases.
+   */
+  void iccExchangeAPDU(in unsigned long clientId,
+                       in long channel,
+                       in octet cla,
+                       in octet ins,
+                       in octet p1,
+                       in octet p2,
+                       in short p3,
+                       in DOMString data,
+                       in nsIIccChannelCallback callback);
 
-  nsIDOMDOMRequest iccCloseChannel(in unsigned long clientId,
-                                   in nsIDOMWindow window,
-                                   in long channel);
+  void iccCloseChannel(in unsigned long clientId,
+                       in long channel,
+                       in nsIIccChannelCallback callback);
 
   /**
    * Helpers
    */
   nsIDOMDOMRequest matchMvno(in unsigned long clientId,
                              in nsIDOMWindow window,
                              in unsigned long mvnoType,
                              in DOMString mvnoData);
--- a/dom/system/gonk/RILContentHelper.js
+++ b/dom/system/gonk/RILContentHelper.js
@@ -57,16 +57,20 @@ const RIL_IPC_MSG_NAMES = [
   "RIL:UpdateIccContact",
   "RIL:MatchMvno"
 ];
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsISyncMessageSender");
 
+XPCOMUtils.defineLazyServiceGetter(this, "UUIDGenerator",
+                  "@mozilla.org/uuid-generator;1",
+                  "nsIUUIDGenerator");
+
 XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() {
   let appInfo = Cc["@mozilla.org/xre/app-info;1"];
   let isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
                           .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
 
   if (isParentProcess) {
     let ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
     return ril.numRadioInterfaces;
@@ -405,73 +409,68 @@ RILContentHelper.prototype = {
     cpmm.sendAsyncMessage("RIL:SendStkEventDownload", {
       clientId: clientId,
       data: {
         event: event
       }
     });
   },
 
-  iccOpenChannel: function(clientId, window, aid) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
+  iccOpenChannel: function(clientId, aid, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._addIccChannelCallback(requestId, callback);
 
     cpmm.sendAsyncMessage("RIL:IccOpenChannel", {
       clientId: clientId,
       data: {
         requestId: requestId,
         aid: aid
       }
     });
-    return request;
   },
 
-  iccExchangeAPDU: function(clientId, window, channel, apdu) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
+  iccExchangeAPDU: function(clientId, channel, cla, ins, p1, p2, p3, data, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._addIccChannelCallback(requestId, callback);
+
+    if (!data) {
+      if (DEBUG) debug('data is not set , p3 : ' + p3);
     }
 
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
+    let apdu = {
+      cla: cla,
+      command: ins,
+      p1: p1,
+      p2: p2,
+      p3: p3,
+      data: data
+    };
 
     //Potentially you need serialization here and can't pass the jsval through
     cpmm.sendAsyncMessage("RIL:IccExchangeAPDU", {
       clientId: clientId,
       data: {
         requestId: requestId,
         channel: channel,
         apdu: apdu
       }
     });
-    return request;
   },
 
-  iccCloseChannel: function(clientId, window, channel) {
-    if (window == null) {
-      throw Components.Exception("Can't get window object",
-                                  Cr.NS_ERROR_UNEXPECTED);
-    }
-
-    let request = Services.DOMRequest.createRequest(window);
-    let requestId = this.getRequestId(request);
+  iccCloseChannel: function(clientId, channel, callback) {
+    let requestId = UUIDGenerator.generateUUID().toString();
+    this._addIccChannelCallback(requestId, callback);
 
     cpmm.sendAsyncMessage("RIL:IccCloseChannel", {
       clientId: clientId,
       data: {
         requestId: requestId,
         channel: channel
       }
     });
-    return request;
   },
 
   readContacts: function(clientId, window, contactType) {
     if (window == null) {
       throw Components.Exception("Can't get window object",
                                   Cr.NS_ERROR_UNEXPECTED);
     }
 
@@ -567,16 +566,32 @@ RILContentHelper.prototype = {
 
     let index = listeners.indexOf(listener);
     if (index != -1) {
       listeners.splice(index, 1);
       if (DEBUG) debug("Unregistered listener: " + listener);
     }
   },
 
+  _addIccChannelCallback: function(requestId, channelCb) {
+    let cbInterfaces = this._iccChannelCallback;
+    if (!cbInterfaces[requestId] && channelCb) {
+      cbInterfaces[requestId] = channelCb;
+      return;
+    }
+
+    if (DEBUG) debug("Unable to add channelCbInterface for requestId : " + requestId);
+  },
+
+  _getIccChannelCallback: function(requestId) {
+    let cb = this._iccChannelCallback[requestId];
+    delete this._iccChannelCallback[requestId];
+    return cb;
+  },
+
   registerIccMsg: function(clientId, listener) {
     if (DEBUG) debug("Registering for ICC related messages");
     this.registerListener("_iccListeners", clientId, listener);
     cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
   },
 
   unregisterIccMsg: function(clientId, listener) {
     this.unregisterListener("_iccListeners", clientId, listener);
@@ -735,21 +750,20 @@ RILContentHelper.prototype = {
       case "RIL:StkCommand":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
                            [JSON.stringify(data)]);
         break;
       case "RIL:StkSessionEnd":
         this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
         break;
       case "RIL:IccOpenChannel":
-        this.handleSimpleRequest(data.requestId, data.errorMsg,
-                                 data.channel);
+        this.handleIccOpenChannel(data);
         break;
       case "RIL:IccCloseChannel":
-        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
+        this.handleIccCloseChannel(data);
         break;
       case "RIL:IccExchangeAPDU":
         this.handleIccExchangeAPDU(data);
         break;
       case "RIL:ReadIccContacts":
         this.handleReadIccContacts(data);
         break;
       case "RIL:UpdateIccContact":
@@ -764,23 +778,48 @@ RILContentHelper.prototype = {
   handleSimpleRequest: function(requestId, errorMsg, result) {
     if (errorMsg) {
       this.fireRequestError(requestId, errorMsg);
     } else {
       this.fireRequestSuccess(requestId, result);
     }
   },
 
+  handleIccOpenChannel: function(message) {
+    let requestId = message.requestId;
+    let callback = this._getIccChannelCallback(requestId);
+    if (!callback) {
+      return;
+    }
+
+    return !message.errorMsg ? callback.notifyOpenChannelSuccess(message.channel) :
+                               callback.notifyError(message.errorMsg);
+  },
+
+  handleIccCloseChannel: function(message) {
+    let requestId = message.requestId;
+    let callback = this._getIccChannelCallback(requestId);
+    if (!callback) {
+      return;
+    }
+
+    return !message.errorMsg ? callback.notifyCloseChannelSuccess() :
+                               callback.notifyError(message.errorMsg);
+  },
+
   handleIccExchangeAPDU: function(message) {
-    if (message.errorMsg) {
-      this.fireRequestError(message.requestId, message.errorMsg);
-    } else {
-      var result = [message.sw1, message.sw2, message.simResponse];
-      this.fireRequestSuccess(message.requestId, result);
+    let requestId = message.requestId;
+    let callback = this._getIccChannelCallback(requestId);
+    if (!callback) {
+      return;
     }
+
+    return !message.errorMsg ?
+           callback.notifyExchangeAPDUResponse(message.sw1, message.sw2, message.simResponse) :
+           callback.notifyError(message.errorMsg);
   },
 
   handleReadIccContacts: function(message) {
     if (message.errorMsg) {
       this.fireRequestError(message.requestId, message.errorMsg);
       return;
     }