Bug 1072808 - Part 5: Add IccMessenger as a Wrapper for STK-related System Messages. r=htsai,echen
☠☠ backed out by d120afea9715 ☠ ☠
authorBevis Tseng <btseng@mozilla.com>
Mon, 27 Oct 2014 15:58:56 +0800
changeset 241678 4e67992092d9ad88b5db03ad19b86fb17399d402
parent 241677 959ee37e80d5aff91a4ee091e5e8732117848a1e
child 241679 22da7cf68b33b0fc381b0c006ca4936273892849
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershtsai, echen
bugs1072808
milestone36.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 1072808 - Part 5: Add IccMessenger as a Wrapper for STK-related System Messages. r=htsai,echen
dom/icc/gonk/StkProactiveCmdFactory.jsm
dom/icc/interfaces/moz.build
dom/icc/interfaces/nsIIccMessenger.idl
dom/icc/moz.build
dom/system/gonk/RILSystemMessenger.jsm
dom/system/gonk/RILSystemMessengerHelper.js
dom/system/gonk/RadioInterfaceLayer.js
dom/system/gonk/ril_consts.js
dom/system/gonk/tests/test_ril_system_messenger.js
new file mode 100644
--- /dev/null
+++ b/dom/icc/gonk/StkProactiveCmdFactory.jsm
@@ -0,0 +1,1073 @@
+/* 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/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+let RIL = {};
+Cu.import("resource://gre/modules/ril_consts.js", RIL);
+
+/**
+ * Helper Utilities to convert JS Objects to IDL Objects.
+ */
+
+/**
+ * To map { timeUnit, timeInterval } into StkDuration.
+ */
+function mapDurationToStkDuration(aDuration) {
+  return (aDuration)
+    ? new StkDuration(aDuration.timeUnit, aDuration.timeInterval)
+    : null;
+}
+
+/**
+ * To map { iconSelfExplanatory, icons } into StkIconInfo.
+ */
+function mapIconInfoToStkIconInfo(aIconInfo) {
+  let mapIconToStkIcon = function(aIcon) {
+    return new StkIcon(aIcon.width, aIcon.height,
+                       aIcon.codingScheme, aIcon.pixels);
+  };
+
+  return (aIconInfo &&
+          aIconInfo.icons !== undefined &&
+          aIconInfo.iconSelfExplanatory !== undefined)
+    ? new StkIconInfo(aIconInfo.iconSelfExplanatory,
+                      aIconInfo.icons.map(mapIconToStkIcon))
+    : null;
+}
+
+/**
+ * Helper Utilities to append the STK attributes to System Message.
+ */
+
+function appendDuration(aTarget, aStkDuration) {
+  aTarget.timeUnit = aStkDuration.timeUnit;
+  aTarget.timeInterval = aStkDuration.timeInterval;
+}
+
+function appendIconInfo(aTarget, aStkIconInfo) {
+  aTarget.iconSelfExplanatory = aStkIconInfo.iconSelfExplanatory;
+  aTarget.icons = aStkIconInfo.getIcons().map(function(aStkIcon) {
+    return {
+      width: aStkIcon.width,
+      height: aStkIcon.height,
+      codingScheme: RIL.ICC_IMG_CODING_SCHEME_TO_GECKO[aStkIcon.codingScheme],
+      pixels: aStkIcon.getPixels()
+    };
+  });
+}
+
+/**
+ * The implementation of the data types used in variant types of
+ * StkProactiveCommand.
+ */
+
+function StkDuration(aTimeUnit, aTimeInterval) {
+  this.timeUnit = aTimeUnit;
+  this.timeInterval = aTimeInterval;
+}
+StkDuration.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkDuration]),
+
+  // nsIStkDuration
+  timeUnit: 0,
+  timeInterval: 0
+};
+
+function StkIcon(aWidth, aHeight, aCodingScheme, aPixels) {
+  this.width = aWidth;
+  this.height = aHeight;
+  this.codingScheme = this.IMG_CODING_SCHEME[aCodingScheme];
+  this.pixels = aPixels.slice();
+}
+StkIcon.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkIcon]),
+
+  // Cache pixels for getPixels()
+  pixels: null,
+
+  // Scheme mapping.
+  IMG_CODING_SCHEME: {
+    "basic": Ci.nsIStkIcon.CODING_SCHEME_BASIC,
+    "color": Ci.nsIStkIcon.CODING_SCHEME_COLOR,
+    "color-transparency": Ci.nsIStkIcon.CODING_SCHEME_COLOR_TRANSPARENCY
+  },
+
+  // StkIcon
+  width: 0,
+  height: 0,
+  codingScheme: 0,
+  getPixels: function(aCount) {
+    if (!this.pixels) {
+      if (aCount) {
+        aCount.value = 0;
+      }
+      return null;
+    }
+
+    if (aCount) {
+      aCount.value = this.pixels.length;
+    }
+
+    return this.pixels.slice();
+  }
+};
+
+function StkIconInfo(aIconSelfExplanatory, aStkIcons) {
+  this.iconSelfExplanatory = aIconSelfExplanatory;
+  this.icons = aStkIcons;
+}
+StkIconInfo.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkIconInfo]),
+
+  // Cache the list of StkIcon(s) for getIcons()
+  icons: null,
+
+  // nsIStkIconInfo
+  iconSelfExplanatory: false,
+
+  getIcons: function(aCount) {
+    if (!this.icons) {
+      if (aCount) {
+        aCount.value = 0;
+      }
+      return null;
+    }
+
+    if (aCount) {
+      aCount.value = this.icons.length;
+    }
+
+    return this.icons.slice();
+  }
+};
+
+function StkItem(aIdentifier, aText, aStkIconInfo) {
+  this.identifier = aIdentifier;
+  if (aText) {
+    this.text = aText;
+  }
+  this.iconInfo = aStkIconInfo;
+}
+StkItem.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkItem]),
+
+  // nsIStkItem
+  identifier: 0,
+  text: null,
+  iconInfo: null
+};
+
+function StkTimer(aTimerId, aTimerValue, aTimerAction) {
+  this.timerId = aTimerId;
+  if (aTimerValue !== undefined &&
+      aTimerValue !== null) {
+    this.timerValue = aTimerValue;
+  }
+  this.timerAction = aTimerAction;
+}
+StkTimer.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkTimer]),
+
+  // nsIStkTimer
+  timerId: 0,
+  timerValue: Ci.nsIStkTimer.TIMER_VALUE_INVALID,
+  timerAction: 0
+};
+
+/**
+ * The implementation of nsIStkProactiveCommand Set and STK System Message Set.
+ */
+function StkProactiveCommand(aCommandDetails) {
+  this.commandNumber = aCommandDetails.commandNumber;
+  this.typeOfCommand = aCommandDetails.typeOfCommand;
+  this.commandQualifier = aCommandDetails.commandQualifier;
+}
+StkProactiveCommand.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd]),
+
+  // nsIStkProactiveCmd
+  commandNumber: 0,
+  typeOfCommand: 0,
+  commandQualifier: 0
+};
+
+function StkCommandMessage(aStkProactiveCmd) {
+  this.commandNumber = aStkProactiveCmd.commandNumber;
+  this.typeOfCommand = aStkProactiveCmd.typeOfCommand;
+  this.commandQualifier = aStkProactiveCmd.commandQualifier;
+}
+StkCommandMessage.prototype = {
+  commandNumber: 0,
+  typeOfCommand: 0,
+  commandQualifier: 0,
+  options: null
+};
+
+function StkPollIntervalCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  this.duration = mapDurationToStkDuration(aCommandDetails.options);
+}
+StkPollIntervalCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkPollIntervalCmd])
+  },
+
+  // nsIStkPollIntervalCmd
+  duration: { value: null, writable: true }
+});
+
+function StkPollIntervalMessage(aStkPollIntervalCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkPollIntervalCmd);
+
+  this.options = {};
+  appendDuration(this.options, aStkPollIntervalCmd.duration);
+}
+StkPollIntervalMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkProvideLocalInfoCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  this.localInfoType = aCommandDetails.options.localInfoType;
+}
+StkProvideLocalInfoCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkProvideLocalInfoCmd])
+  },
+
+  // nsIStkPollIntervalCmd
+  localInfoType: { value: 0x00, writable: true }
+});
+
+function StkProvideLocalInfoMessage(aStkProvideLocalInfoCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkProvideLocalInfoCmd);
+
+  this.options = {
+    localInfoType: aStkProvideLocalInfoCmd.localInfoType
+  };
+}
+StkProvideLocalInfoMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkSetupEventListCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+  let eventList = aCommandDetails.options.eventList;
+  if (eventList) {
+    this.eventList = eventList.slice();
+  }
+}
+StkSetupEventListCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkSetupEventListCmd])
+  },
+
+  // Cache eventList for getEventList()
+  eventList: { value: null, writable: true },
+
+  // nsIStkSetupEventListCmd
+  getEventList: {
+    value: function(aCount) {
+      if (!this.eventList) {
+        if (aCount) {
+          aCount.value = 0;
+        }
+        return null;
+      }
+
+      if (aCount) {
+        aCount.value = this.eventList.length;
+      }
+
+      return this.eventList.slice();
+    }
+  }
+});
+
+function StkSetupEventListMessage(aStkSetupEventListCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkSetupEventListCmd);
+
+  this.options = {
+    eventList: null
+  };
+
+  let eventList = aStkSetupEventListCmd.getEventList();
+
+  if (eventList && eventList.length > 0) {
+    this.options.eventList = eventList;
+  }
+}
+StkSetupEventListMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkMenuCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  if (options.title) {
+    this.title = options.title;
+  }
+
+  this.items = options.items.map(function(aItem) {
+    // For |SET-UP MENU|, the 1st item in |aItems| could be null as an
+    // indication to the ME to remove the existing menu from the menu
+    // system in the ME.
+    return (aItem) ? new StkItem(aItem.identifier,
+                                 aItem.text,
+                                 mapIconInfoToStkIconInfo(aItem))
+                   : null;
+  });
+
+  if (options.nextActionList) {
+    this.nextActionList = options.nextActionList.slice();
+  }
+
+  this.iconInfo = mapIconInfoToStkIconInfo(options);
+
+  this.isHelpAvailable = !!(options.isHelpAvailable);
+}
+StkMenuCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkMenuCmd])
+  },
+
+  // Cache items for getItems()
+  items: { value: null, writable: true },
+
+  // Cache items for getNextActionList()
+  nextActionList: { value: null, writable: true },
+
+  // nsIStkMenuCmd
+  title: { value: null, writable: true },
+
+  getItems: {
+    value: function(aCount) {
+      if (!this.items) {
+        if (aCount) {
+          aCount.value = 0;
+        }
+        return null;
+      }
+
+      if (aCount) {
+        aCount.value = this.items.length;
+      }
+
+      return this.items.slice();
+    }
+  },
+
+  getNextActionList: {
+    value: function(aCount) {
+      if (!this.nextActionList) {
+        if (aCount) {
+          aCount.value = 0;
+        }
+        return null;
+      }
+
+      if (aCount) {
+        aCount.value = this.nextActionList.length;
+      }
+
+      return this.nextActionList.slice();
+    }
+  },
+
+  iconInfo: { value: null, writable: true },
+  isHelpAvailable: { value: false, writable: true }
+});
+
+function StkMenuMessage(aStkMenuCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkMenuCmd);
+
+  this.options = {
+    items: aStkMenuCmd.getItems().map(function(aStkItem) {
+      if (!aStkItem) {
+        return null;
+      }
+
+      let item = {
+        identifier: aStkItem.identifier,
+        text: aStkItem.text
+      };
+
+      if (aStkItem.iconInfo) {
+        appendIconInfo(item, aStkItem.iconInfo);
+      }
+
+      return item;
+    }),
+    isHelpAvailable: aStkMenuCmd.isHelpAvailable
+  };
+
+  if (aStkMenuCmd.title) {
+    this.options.title = aStkMenuCmd.title;
+  }
+
+  let nextActionList = aStkMenuCmd.getNextActionList();
+  if (nextActionList && nextActionList.length > 0) {
+    this.options.nextActionList = nextActionList;
+  }
+
+  if (aStkMenuCmd.iconInfo) {
+    appendIconInfo(this.options, aStkMenuCmd.iconInfo);
+  }
+}
+StkMenuMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkSetUpMenuCmd(aCommandDetails) {
+  // Call |StkMenuCmd| constructor.
+  StkMenuCmd.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  this.presentationType = options.presentationType;
+}
+StkSetUpMenuCmd.prototype = Object.create(StkMenuCmd.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkMenuCmd,
+                                  Ci.nsIStkSetUpMenuCmd])
+  },
+
+  // nsIStkSetUpMenuCmd
+  presentationType: { value: 0, writable: true }
+});
+
+function StkSetUpMenuMessage(aStkSetUpMenuCmd) {
+  // Call |StkMenuMessage| constructor.
+  StkMenuMessage.call(this, aStkSetUpMenuCmd);
+
+  this.options.presentationType = aStkSetUpMenuCmd.presentationType;
+}
+StkSetUpMenuMessage.prototype = Object.create(StkMenuMessage.prototype);
+
+function StkSelectItemCmd(aCommandDetails) {
+  // Call |StkMenuCmd| constructor.
+  StkMenuCmd.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  if (options.defaultItem !== undefined &&
+      options.defaultItem !== null) {
+    this.defaultItem = options.defaultItem;
+  }
+}
+StkSelectItemCmd.prototype = Object.create(StkMenuCmd.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkMenuCmd,
+                                  Ci.nsIStkSelectItemCmd])
+  },
+
+  // nsIStkSelectItemCmd
+  defaultItem: {
+    value: Ci.nsIStkSelectItemCmd.DEFAULT_ITEM_INVALID,
+    writable: true
+  }
+});
+
+function StkSelectItemMessage(aStkSelectItemCmd) {
+  // Call |StkMenuMessage| constructor.
+  StkMenuMessage.call(this, aStkSelectItemCmd);
+
+  if (aStkSelectItemCmd.defaultItem !== Ci.nsIStkSelectItemCmd.DEFAULT_ITEM_INVALID) {
+    this.options.defaultItem = aStkSelectItemCmd.defaultItem;
+  }
+}
+StkSelectItemMessage.prototype = Object.create(StkMenuMessage.prototype);
+
+function StkTextMessageCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  if (options.text) {
+    this.text = options.text;
+  }
+
+  this.iconInfo = mapIconInfoToStkIconInfo(options);
+}
+StkTextMessageCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkTextMessageCmd])
+  },
+
+  // nsIStkTextMessageCmd
+  text: { value: null, writable: true },
+  iconInfo: { value: null, writable: true }
+});
+
+function StkTextMessage(aStkTextMessageCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkTextMessageCmd);
+
+  this.options = {};
+
+  if (aStkTextMessageCmd.text) {
+    this.options.text = aStkTextMessageCmd.text;
+  }
+
+  if (aStkTextMessageCmd.iconInfo) {
+    appendIconInfo(this.options, aStkTextMessageCmd.iconInfo);
+  }
+}
+StkTextMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkDisplayTextCmd(aCommandDetails) {
+  // Call |StkTextMessageCmd| constructor.
+  StkTextMessageCmd.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  this.duration = mapDurationToStkDuration(options.duration);
+
+  this.isHighPriority = !!(options.isHighPriority);
+  this.userClear = !!(options.userClear);
+  this.responseNeeded = !!(options.responseNeeded);
+}
+StkDisplayTextCmd.prototype = Object.create(StkTextMessageCmd.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkTextMessageCmd,
+                                  Ci.nsIStkDisplayTextCmd])
+  },
+
+  // nsIStkDisplayTextCmd
+  duration: { value: null, writable: true },
+  isHighPriority: { value: false, writable: true },
+  userClear: { value: false, writable: true },
+  responseNeeded: { value: false, writable: true }
+});
+
+function StkDisplayTextMessage(aStkDisplayTextCmd) {
+  // Call |StkTextMessage| constructor.
+  StkTextMessage.call(this, aStkDisplayTextCmd);
+
+  this.options.isHighPriority = aStkDisplayTextCmd.isHighPriority;
+  this.options.userClear = aStkDisplayTextCmd.userClear;
+  this.options.responseNeeded = aStkDisplayTextCmd.responseNeeded;
+
+  if (aStkDisplayTextCmd.duration) {
+    this.options.duration = {};
+    appendDuration(this.options.duration, aStkDisplayTextCmd.duration);
+  }
+}
+StkDisplayTextMessage.prototype = Object.create(StkTextMessage.prototype);
+
+function StkInputCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  if (options.text) {
+    this.text = options.text;
+  }
+
+  this.duration = mapDurationToStkDuration(options.duration);
+
+  if (options.defaultText) {
+    this.defaultText = options.defaultText;
+  }
+
+  this.isAlphabet = !!(options.isAlphabet);
+  this.isUCS2 = !!(options.isUCS2);
+  this.isHelpAvailable = !!(options.isHelpAvailable);
+
+  this.iconInfo = mapIconInfoToStkIconInfo(options);
+}
+StkInputCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkInputCmd])
+  },
+
+  // nsIStkInputCmd
+  text: { value: null, writable: true },
+  duration: { value: null, writable: true },
+  minLength: { value: 1, writable: true },
+  maxLength: { value: 1, writable: true },
+  defaultText: { value: null, writable: true },
+  isAlphabet: { value: false, writable: true },
+  isUCS2: { value: false, writable: true },
+  isHelpAvailable: { value: false, writable: true },
+  iconInfo: { value: null, writable: true }
+});
+
+function StkInputMessage(aStkInputCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkInputCmd);
+
+  this.options = {
+    text: aStkInputCmd.text,
+    minLength: aStkInputCmd.minLength,
+    maxLength: aStkInputCmd.maxLength,
+    isAlphabet: aStkInputCmd.isAlphabet,
+    isUCS2: aStkInputCmd.isUCS2,
+    isHelpAvailable: aStkInputCmd.isHelpAvailable,
+  };
+
+  if (aStkInputCmd.duration) {
+    this.options.duration = {};
+    appendDuration(this.options.duration, aStkInputCmd.duration);
+  }
+
+  if (aStkInputCmd.defaultText) {
+    this.options.defaultText = aStkInputCmd.defaultText;
+  }
+
+  if (aStkInputCmd.iconInfo) {
+    appendIconInfo(this.options, aStkInputCmd.iconInfo);
+  }
+}
+StkInputMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkInputKeyCmd(aCommandDetails) {
+  // Call |StkInputCmd| constructor.
+  StkInputCmd.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  // Note: For STK_CMD_INKEY,
+  // this.minLength = this.maxLength = 1;
+
+  this.isYesNoRequested = !!(options.isYesNoRequested);
+}
+StkInputKeyCmd.prototype = Object.create(StkInputCmd.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkInputCmd,
+                                  Ci.nsIStkInputKeyCmd])
+  },
+
+  // nsIStkInputKeyCmd
+  isYesNoRequested: { value: false, writable: true }
+});
+
+function StkInputKeyMessage(aStkInputKeyCmd) {
+  // Call |StkInputMessage| constructor.
+  StkInputMessage.call(this, aStkInputKeyCmd);
+
+  this.options.isYesNoRequested = aStkInputKeyCmd.isYesNoRequested;
+}
+StkInputKeyMessage.prototype = Object.create(StkInputMessage.prototype);
+
+function StkInputTextCmd(aCommandDetails) {
+  // Call |StkInputCmd| constructor.
+  StkInputCmd.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  this.minLength = options.minLength;
+  this.maxLength = options.maxLength;
+
+  this.hideInput = !!(options.hideInput);
+  this.isPacked = !!(options.isPacked);
+}
+StkInputTextCmd.prototype = Object.create(StkInputCmd.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkInputCmd,
+                                  Ci.nsIStkInputTextCmd])
+  },
+
+  // nsIStkInputTextCmd
+  hideInput: { value: false, writable: true },
+  isPacked: { value: false, writable: true }
+});
+
+function StkInputTextMessage(aStkInputTextCmd) {
+  // Call |StkInputMessage| constructor.
+  StkInputMessage.call(this, aStkInputTextCmd);
+
+  this.options.hideInput = aStkInputTextCmd.hideInput;
+  this.options.isPacked = aStkInputTextCmd.isPacked;
+}
+StkInputTextMessage.prototype = Object.create(StkInputMessage.prototype);
+
+function StkSetUpCallCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  let confirmMessage = options.confirmMessage;
+  let callMessage = options.callMessage;
+
+  this.address = options.address;
+
+  if(confirmMessage) {
+    if (confirmMessage.text) {
+      this.confirmText = confirmMessage.text;
+    }
+    this.confirmIconInfo = mapIconInfoToStkIconInfo(confirmMessage);
+  }
+
+  if(callMessage) {
+    if (callMessage.text) {
+      this.callText = callMessage.text;
+    }
+    this.callIconInfo = mapIconInfoToStkIconInfo(callMessage);
+  }
+
+  this.duration = mapDurationToStkDuration(options.duration);
+}
+StkSetUpCallCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkSetUpCallCmd])
+  },
+
+  // nsIStkSetUpCallCmd
+  address: { value: null, writable: true },
+  confirmText: { value: null, writable: true },
+  confirmIconInfo: { value: null, writable: true },
+  callText: { value: null, writable: true },
+  callIconInfo: { value: null, writable: true },
+  duration: { value: null, writable: true }
+});
+
+function StkSetUpCallMessage(aStkSetUpCallCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkSetUpCallCmd);
+
+  this.options = {
+    address: aStkSetUpCallCmd.address
+  };
+
+  if (aStkSetUpCallCmd.confirmText || aStkSetUpCallCmd.confirmIconInfo) {
+    let confirmMessage = {};
+    if (aStkSetUpCallCmd.confirmText) {
+      confirmMessage.text = aStkSetUpCallCmd.confirmText;
+    }
+    if (aStkSetUpCallCmd.confirmIconInfo) {
+      appendIconInfo(confirmMessage, aStkSetUpCallCmd.confirmIconInfo);
+    }
+    this.options.confirmMessage = confirmMessage;
+  }
+
+  if (aStkSetUpCallCmd.callText || aStkSetUpCallCmd.callIconInfo) {
+    let callMessage = {};
+    if (aStkSetUpCallCmd.callText) {
+      callMessage.text = aStkSetUpCallCmd.callText;
+    }
+    if (aStkSetUpCallCmd.callIconInfo) {
+      appendIconInfo(callMessage, aStkSetUpCallCmd.callIconInfo);
+    }
+    this.options.callMessage = callMessage;
+  }
+
+  if (aStkSetUpCallCmd.duration) {
+    this.options.duration = {};
+    appendDuration(this.options.duration, aStkSetUpCallCmd.duration);
+  }
+}
+StkSetUpCallMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkBrowserSettingCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  this.url = options.url;
+
+  this.mode = options.mode;
+
+  let confirmMessage = options.confirmMessage;
+
+  if(confirmMessage) {
+    if (confirmMessage.text) {
+      this.confirmText = confirmMessage.text;
+    }
+    this.confirmIconInfo = mapIconInfoToStkIconInfo(confirmMessage);
+  }
+}
+StkBrowserSettingCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkBrowserSettingCmd])
+  },
+
+  // nsIStkBrowserSettingCmd
+  url: { value: null, writable: true },
+  mode: { value: 0, writable: true },
+  confirmText: { value: null, writable: true },
+  confirmIconInfo: { value: null, writable: true }
+});
+
+function StkBrowserSettingMessage(aStkBrowserSettingCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkBrowserSettingCmd);
+
+  this.options = {
+    url: aStkBrowserSettingCmd.url,
+    mode: aStkBrowserSettingCmd.mode
+  };
+
+  if (aStkBrowserSettingCmd.confirmText || aStkBrowserSettingCmd.confirmIconInfo) {
+    let confirmMessage = {};
+    if (aStkBrowserSettingCmd.confirmText) {
+      confirmMessage.text = aStkBrowserSettingCmd.confirmText;
+    }
+    if (aStkBrowserSettingCmd.confirmIconInfo) {
+      appendIconInfo(confirmMessage, aStkBrowserSettingCmd.confirmIconInfo);
+    }
+    this.options.confirmMessage = confirmMessage;
+  }
+}
+StkBrowserSettingMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkPlayToneCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  if(options.text) {
+    this.text = options.text;
+  }
+
+  if (options.tone !== undefined &&
+      options.tone !== null) {
+    this.tone = options.tone;
+  }
+
+  if (options.isVibrate) {
+    this.isVibrate = true;
+  }
+
+  this.duration = mapDurationToStkDuration(options.duration);
+
+  this.iconInfo = mapIconInfoToStkIconInfo(options);
+}
+StkPlayToneCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkPlayToneCmd])
+  },
+
+  // nsIStkPlayToneCmd
+  text: { value: null, writable: true },
+  tone: { value: Ci.nsIStkPlayToneCmd.TONE_TYPE_INVALID, writable: true },
+  duration: { value: null, writable: true },
+  isVibrate: { value: false, writable: true },
+  iconInfo: { value: null, writable: true }
+});
+
+function StkPlayToneMessage(aStkPlayToneCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkPlayToneCmd);
+
+  this.options = {
+    isVibrate: aStkPlayToneCmd.isVibrate
+  };
+
+  if (aStkPlayToneCmd.text) {
+    this.options.text = aStkPlayToneCmd.text;
+  }
+
+  if (aStkPlayToneCmd.tone != Ci.nsIStkPlayToneCmd.TONE_TYPE_INVALID) {
+    this.options.tone = aStkPlayToneCmd.tone;
+  }
+
+  if (aStkPlayToneCmd.duration) {
+    this.options.duration = {};
+    appendDuration(this.options.duration, aStkPlayToneCmd.duration);
+  }
+
+  if (aStkPlayToneCmd.iconInfo) {
+    appendIconInfo(this.options, aStkPlayToneCmd.iconInfo);
+  }
+}
+StkPlayToneMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+function StkTimerManagementCmd(aCommandDetails) {
+  // Call |StkProactiveCommand| constructor.
+  StkProactiveCommand.call(this, aCommandDetails);
+
+  let options = aCommandDetails.options;
+
+  this.timerInfo = new StkTimer(options.timerId,
+                                options.timerValue,
+                                options.timerAction);
+
+}
+StkTimerManagementCmd.prototype = Object.create(StkProactiveCommand.prototype, {
+  QueryInterface: {
+    value: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                  Ci.nsIStkTimerManagementCmd])
+  },
+
+  // nsIStkTimerManagementCmd
+  timerInfo: { value: null, writable: true }
+});
+
+function StkTimerMessage(aStkTimerManagementCmd) {
+  // Call |StkCommandMessage| constructor.
+  StkCommandMessage.call(this, aStkTimerManagementCmd);
+
+  let timerInfo = aStkTimerManagementCmd.timerInfo;
+
+  this.options = {
+    timerId: timerInfo.timerId,
+    timerAction: timerInfo.timerAction
+  };
+
+  if (timerInfo.timerValue !== Ci.nsIStkTimer.TIMER_VALUE_INVALID) {
+    this.options.timerValue = timerInfo.timerValue;
+  }
+}
+StkTimerMessage.prototype = Object.create(StkCommandMessage.prototype);
+
+/**
+ * Command Prototype Mappings.
+ */
+let CmdPrototypes = {};
+CmdPrototypes[RIL.STK_CMD_REFRESH] = StkProactiveCommand;
+CmdPrototypes[RIL.STK_CMD_POLL_INTERVAL] = StkPollIntervalCmd;
+CmdPrototypes[RIL.STK_CMD_POLL_OFF] = StkProactiveCommand;
+CmdPrototypes[RIL.STK_CMD_PROVIDE_LOCAL_INFO] = StkProvideLocalInfoCmd;
+CmdPrototypes[RIL.STK_CMD_SET_UP_EVENT_LIST] = StkSetupEventListCmd;
+CmdPrototypes[RIL.STK_CMD_SET_UP_MENU] = StkSetUpMenuCmd;
+CmdPrototypes[RIL.STK_CMD_SELECT_ITEM] = StkSelectItemCmd;
+CmdPrototypes[RIL.STK_CMD_DISPLAY_TEXT] = StkDisplayTextCmd;
+CmdPrototypes[RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_SEND_SS] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_SEND_USSD] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_SEND_SMS] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_SEND_DTMF] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_GET_INKEY] = StkInputKeyCmd;
+CmdPrototypes[RIL.STK_CMD_GET_INPUT] = StkInputTextCmd;
+CmdPrototypes[RIL.STK_CMD_SET_UP_CALL] = StkSetUpCallCmd;
+CmdPrototypes[RIL.STK_CMD_LAUNCH_BROWSER] = StkBrowserSettingCmd;
+CmdPrototypes[RIL.STK_CMD_PLAY_TONE] = StkPlayToneCmd;
+CmdPrototypes[RIL.STK_CMD_TIMER_MANAGEMENT] = StkTimerManagementCmd;
+CmdPrototypes[RIL.STK_CMD_OPEN_CHANNEL] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_CLOSE_CHANNEL] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_SEND_DATA] = StkTextMessageCmd;
+CmdPrototypes[RIL.STK_CMD_RECEIVE_DATA] = StkTextMessageCmd;
+
+/**
+ * Message Prototype Mappings.
+ */
+let MsgPrototypes = {};
+MsgPrototypes[RIL.STK_CMD_REFRESH] = StkCommandMessage;
+MsgPrototypes[RIL.STK_CMD_POLL_INTERVAL] = StkPollIntervalMessage;
+MsgPrototypes[RIL.STK_CMD_POLL_OFF] = StkCommandMessage;
+MsgPrototypes[RIL.STK_CMD_PROVIDE_LOCAL_INFO] = StkProvideLocalInfoMessage;
+MsgPrototypes[RIL.STK_CMD_SET_UP_EVENT_LIST] = StkSetupEventListMessage;
+MsgPrototypes[RIL.STK_CMD_SET_UP_MENU] = StkSetUpMenuMessage;
+MsgPrototypes[RIL.STK_CMD_SELECT_ITEM] = StkSelectItemMessage;
+MsgPrototypes[RIL.STK_CMD_DISPLAY_TEXT] = StkDisplayTextMessage;
+MsgPrototypes[RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_SEND_SS] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_SEND_USSD] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_SEND_SMS] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_SEND_DTMF] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_GET_INKEY] = StkInputKeyMessage;
+MsgPrototypes[RIL.STK_CMD_GET_INPUT] = StkInputTextMessage;
+MsgPrototypes[RIL.STK_CMD_SET_UP_CALL] = StkSetUpCallMessage;
+MsgPrototypes[RIL.STK_CMD_LAUNCH_BROWSER] = StkBrowserSettingMessage;
+MsgPrototypes[RIL.STK_CMD_PLAY_TONE] = StkPlayToneMessage;
+MsgPrototypes[RIL.STK_CMD_TIMER_MANAGEMENT] = StkTimerMessage;
+MsgPrototypes[RIL.STK_CMD_OPEN_CHANNEL] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_CLOSE_CHANNEL] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_SEND_DATA] = StkTextMessage;
+MsgPrototypes[RIL.STK_CMD_RECEIVE_DATA] = StkTextMessage;
+
+/**
+ * QueryInterface Mappings.
+ */
+let QueriedIFs = {};
+QueriedIFs[RIL.STK_CMD_REFRESH] = Ci.nsIStkProactiveCmd;
+QueriedIFs[RIL.STK_CMD_POLL_INTERVAL] = Ci.nsIStkPollIntervalCmd;
+QueriedIFs[RIL.STK_CMD_POLL_OFF] = Ci.nsIStkProactiveCmd;
+QueriedIFs[RIL.STK_CMD_PROVIDE_LOCAL_INFO] = Ci.nsIStkProvideLocalInfoCmd;
+QueriedIFs[RIL.STK_CMD_SET_UP_EVENT_LIST] = Ci.nsIStkSetupEventListCmd;
+QueriedIFs[RIL.STK_CMD_SET_UP_MENU] = Ci.nsIStkSetUpMenuCmd;
+QueriedIFs[RIL.STK_CMD_SELECT_ITEM] = Ci.nsIStkSelectItemCmd;
+QueriedIFs[RIL.STK_CMD_DISPLAY_TEXT] = Ci.nsIStkDisplayTextCmd;
+QueriedIFs[RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_SEND_SS] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_SEND_USSD] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_SEND_SMS] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_SEND_DTMF] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_GET_INKEY] = Ci.nsIStkInputKeyCmd;
+QueriedIFs[RIL.STK_CMD_GET_INPUT] = Ci.nsIStkInputTextCmd;
+QueriedIFs[RIL.STK_CMD_SET_UP_CALL] = Ci.nsIStkSetUpCallCmd;
+QueriedIFs[RIL.STK_CMD_LAUNCH_BROWSER] = Ci.nsIStkBrowserSettingCmd;
+QueriedIFs[RIL.STK_CMD_PLAY_TONE] = Ci.nsIStkPlayToneCmd;
+QueriedIFs[RIL.STK_CMD_TIMER_MANAGEMENT] = Ci.nsIStkTimerManagementCmd;
+QueriedIFs[RIL.STK_CMD_OPEN_CHANNEL] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_CLOSE_CHANNEL] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_SEND_DATA] = Ci.nsIStkTextMessageCmd;
+QueriedIFs[RIL.STK_CMD_RECEIVE_DATA] = Ci.nsIStkTextMessageCmd;
+
+/**
+ * StkProactiveCmdFactory
+ */
+this.StkProactiveCmdFactory = {
+  /**
+   * @param  aCommandDetails
+   *         The CommandDetails decoded from ril_worker.js.
+   * @return a nsIStkProactiveCmd instance.
+   */
+  createCommand: function(aCommandDetails) {
+    let cmdType = CmdPrototypes[aCommandDetails.typeOfCommand];
+
+    if (typeof cmdType != "function") {
+      throw new Error("Unknown Command Type: " + aCommandDetails.typeOfCommand);
+    }
+
+    return new cmdType(aCommandDetails);
+  },
+
+  /**
+   * @param  nsIStkProactiveCmd instance.
+   * @return a Javascript object with the same structure to MozStkCommandEvent.
+   */
+  createCommandMessage: function(aStkProactiveCmd) {
+    let cmd = null;
+
+    let msgType = MsgPrototypes[aStkProactiveCmd.typeOfCommand];
+
+    if (typeof msgType != "function") {
+      throw new Error("Unknown Command Type: " + aStkProactiveCmd.typeOfCommand);
+    }
+
+    // convert aStkProactiveCmd to it's concrete interface before creating
+    // system message.
+    try {
+      cmd = aStkProactiveCmd.QueryInterface(QueriedIFs[aStkProactiveCmd.typeOfCommand]);
+    } catch (e) {
+      throw new Error("Failed to convert command into concrete class: " + e);
+    }
+
+    return new msgType(cmd);
+  },
+};
+
+this.EXPORTED_SYMBOLS = [
+  'StkProactiveCmdFactory'
+];
--- a/dom/icc/interfaces/moz.build
+++ b/dom/icc/interfaces/moz.build
@@ -4,9 +4,14 @@
 # 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/.
 
 XPIDL_SOURCES += [
     'nsIIccInfo.idl',
     'nsIIccProvider.idl',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
+    XPIDL_SOURCES += [
+        'nsIIccMessenger.idl',
+    ]
+
 XPIDL_MODULE = 'dom_icc'
new file mode 100644
--- /dev/null
+++ b/dom/icc/interfaces/nsIIccMessenger.idl
@@ -0,0 +1,667 @@
+/* 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 "nsISupports.idl"
+
+[scriptable, uuid(1510cf0c-5db6-11e4-9869-6bf419e26642)]
+interface nsIStkDuration : nsISupports
+{
+  /**
+   * The value of Time units defined in 12.8 Duration of TS 11.14.
+   */
+  readonly attribute unsigned short timeUnit;
+
+  /**
+   * The length of time required, expressed in timeUnit.
+   *
+   * Note: the range is from 1 unit to 255 units.
+   */
+  readonly attribute unsigned short timeInterval;
+};
+
+[scriptable, uuid(c7b6e57a-696d-11e4-bcaa-bfe8386e75a9)]
+interface nsIStkIcon : nsISupports
+{
+  /**
+   * The color coding schemes defined in 4.6.1.1 of TS 31.102.
+   */
+  const unsigned short CODING_SCHEME_BASIC              = 0x11;
+  const unsigned short CODING_SCHEME_COLOR              = 0x21;
+  const unsigned short CODING_SCHEME_COLOR_TRANSPARENCY = 0x22;
+
+  /**
+   * Width of the icon.
+   */
+  readonly attribute unsigned long width;
+
+  /**
+   * Height of the icon.
+   */
+  readonly attribute unsigned long height;
+
+  /**
+   * Image coding scheme of the icon.
+   * One of CODING_SCHEME_*.
+   */
+  readonly attribute unsigned short codingScheme;
+
+  /**
+   * Array of pixels. Each pixel represents a color in the RGBA format made up
+   * of four bytes, that is, the Red sample in the highest 8 bits, followed by
+   * the Green sample, Blue sample and the Alpha sample in the lowest 8 bits.
+   *
+   * @param aCount
+   *        The number of pixels.
+   *
+   * @returns a copy of the array of pixels.
+   */
+  void getPixels([optional] out unsigned long aCount,
+                 [array, size_is(aCount), retval] out unsigned long aPixels);
+};
+
+[scriptable, uuid(4a6d173e-5e8b-11e4-9d78-071bb3d6ba8f)]
+interface nsIStkIconInfo : nsISupports
+{
+  /**
+   * Indicates how the icon is to be used.
+   *
+   * @see TS 11.14, clause 12.31, Icon Identifier.
+   *
+   * true: icon replaces the text string.
+   * false: icon shall be displayed together with the text string.
+   */
+  readonly attribute boolean iconSelfExplanatory;
+
+  /**
+   * Icon(s) that replaces or accompanies the text string.
+   *
+   * @see TS 11.14, clause 12.31, Icon Identifier.
+   *
+   * Array of icons, basically of a same image, that may differ in size,
+   * resolution or coding scheme. The first icon should be the default one.
+   *
+   * @param aCount
+   *        The number of icons.
+   *
+   * @returns a copy of the list of icons.
+   */
+  void getIcons([optional] out unsigned long aCount,
+                [array, size_is(aCount), retval] out nsIStkIcon aIcons);
+};
+
+[scriptable, uuid(ea95d25c-5e84-11e4-bd96-07285c50c1f2)]
+interface nsIStkItem : nsISupports
+{
+  /**
+   * Identifier of item.
+   *
+   * The identifier is a single byte between '01' and 'FF'. Each item shall
+   * have a unique identifier within an Item list.
+   */
+  readonly attribute unsigned short identifier;
+
+  /**
+   * Text string of item.
+   */
+  readonly attribute DOMString text;
+
+  /**
+   * (Optional)
+   * Icon info of item.
+   */
+  readonly attribute nsIStkIconInfo iconInfo;
+};
+
+[scriptable, uuid(222651f0-6976-11e4-accf-736a9c6e7d19)]
+interface nsIStkTimer : nsISupports
+{
+  /**
+   * Identifier of a timer.
+   */
+  readonly attribute unsigned short timerId;
+
+  const unsigned long TIMER_VALUE_INVALID = 0xFFFFFFFF;
+
+  /**
+   * Length of time during which the timer has to run.
+   *
+   * The possible duration of a timer is between 1 s and 24 h.
+   * The resolution of a timer is 1 second.
+   *
+   * Note: In TS 11.14, clause 6.6.21 TIMER MANAGEMENT,
+   *       "
+   *        The SIM shall supply this data object only when a timer has to
+   *        be started.
+   *       "
+   *       Hence, set to TIMER_VALUE_INVALID when |timerAction| is not equal to
+   *       TIMER_ACTION_START.
+   */
+  readonly attribute unsigned long timerValue;
+
+  /*
+   * Times actions defined in TS 11.14, clause 12.6,
+   * Command Qualifier, TIMER MANAGEMENT
+   */
+  const unsigned short TIMER_ACTION_START             = 0x00;
+  const unsigned short TIMER_ACTION_DEACTIVATE        = 0x01;
+  const unsigned short TIMER_ACTION_GET_CURRENT_VALUE = 0x02;
+
+  /**
+   * The action requested from UICC.
+   * It shall be one of TIMER_ACTION_*.
+   */
+  readonly attribute unsigned short timerAction;
+};
+
+/**
+ * The base class of all STK Proactive Commands.
+ *
+ * This interface is to be applied by the commands that provide info no more than:
+ * |commandNumber|, |typeOfCommand|, |commandQualifier|.
+ *
+ * The commands in this category are:
+ * - STK_CMD_REFRESH
+ * - STK_CMD_POLL_OFF
+ */
+[scriptable, uuid(f47f25b2-5d84-11e4-8637-7f59ea6da82f)]
+interface nsIStkProactiveCmd : nsISupports
+{
+  /**
+   * The number of command issued by ICC. And it is assigned
+   * by ICC may take any hexadecimal value betweean '01' and 'FE'.
+   *
+   * @see TS 11.14, clause 6.5.1
+   */
+  readonly attribute unsigned short commandNumber;
+
+  /**
+   * The value of |Type of Command| defined in TS 11.14, clause 13.4
+   */
+  readonly attribute unsigned short typeOfCommand;
+
+  /**
+   * Qualifiers specific to the command.
+   */
+  readonly attribute unsigned short commandQualifier;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_POLL_INTERVAL.
+ */
+[scriptable, uuid(0a27c090-5dbc-11e4-92eb-ebc26db3db29)]
+interface nsIStkPollIntervalCmd : nsIStkProactiveCmd
+{
+  /**
+   * The maximum interval between two STATUS commands related to
+   * Proactive Polling.
+   *
+   * Note: Mandatory for STK_CMD_POLL_INTERVAL.
+   *
+   * @See TS 11.14, clause 6.6.6 POLL INTERVAL
+   */
+  readonly attribute nsIStkDuration duration;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_PROVIDE_LOCAL_INFO.
+ */
+[scriptable, uuid(89a304ce-5dc6-11e4-8dce-23723fb242b4)]
+interface nsIStkProvideLocalInfoCmd : nsIStkProactiveCmd
+{
+  /**
+   * Values defined in TS 11.14, clause 12.6, Command Qualifier,
+   * PROVIDE LOCAL INFORMATION
+   */
+  readonly attribute unsigned short localInfoType;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_SET_UP_EVENT_LIST.
+ */
+[scriptable, uuid(5f796dec-5e6a-11e4-aaf3-bb675cb36df5)]
+interface nsIStkSetupEventListCmd : nsIStkProactiveCmd
+{
+  /**
+   * (Optional)
+   * Get the list of events.
+   * Each event could be one of values defined in TS 11.14, clause 8.25, Event list.
+   *
+   * Note: It could be null as an indication to the terminal to remove the
+   *       existing list of events in the terminal.
+   *
+   * @param aCount
+   *        The number of events.
+   *
+   * @returns a copy of the list of events.
+   */
+  void getEventList([optional] out unsigned long aCount,
+                    [array, size_is(aCount), retval] out unsigned short aEventList);
+};
+
+/**
+ * The base interface of nsIStkSetUpMenuCmd and nsIStkSelectItemCmd.
+ */
+[scriptable, uuid(298bf414-6a1f-11e4-9045-3b3fd28e7f6a)]
+interface nsIStkMenuCmd : nsIStkProactiveCmd
+{
+  /**
+   * (Optional for STK_CMD_SELECT_ITEM)
+   * Title of the menu.
+   */
+  readonly attribute DOMString title;
+
+  /**
+   * Get the list of menu items.
+   *
+   * Note: The minimal number of items is 1.
+   *       See TS 11.14, clause 6.6.7 SET-UP MENU and 6.6.8 SELECT ITEM.
+   *
+   * @param aCount
+   *        The number of items.
+   *
+   * @returns a copy of the list of menu items.
+   *          For |SET-UP MENU|, the 1st item in |aItems| could be null as an
+   *          indication to the ME to remove the existing menu from the menu
+   *          system in the ME.
+   */
+  void getItems([optional] out unsigned long aCount,
+                [array, size_is(aCount), retval] out nsIStkItem aItems);
+
+  /**
+   * (Optional)
+   * Get the list of Next Action Indicators.
+   *
+   * Each element should be the value of |Next Action Indicator| in TS 11.14,
+   * clause 13.4.
+   *
+   * @see TS 11.14, clause 12.24, Items Next Action Indicator.
+   *
+   * @param aCount
+   *        The number of indicators.
+   *
+   * @returns a copy of the list of Next Action Indicators.
+   */
+  void getNextActionList([optional] out unsigned long aCount,
+                         [array, size_is(aCount), retval] out unsigned short aActions);
+
+  /**
+   * (Optional)
+   * Icon info of the menu.
+   */
+  readonly attribute nsIStkIconInfo iconInfo;
+
+  /**
+   * Help information available or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, SET UP MENU, bit 8.
+   *
+   * true: help information available.
+   * false: no help information available.
+   *
+   */
+  readonly attribute boolean isHelpAvailable;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_SET_UP_MENU.
+ */
+[scriptable, uuid(d3ddb1f0-631c-11e4-aac3-4beb03196b7b)]
+interface nsIStkSetUpMenuCmd : nsIStkMenuCmd
+{
+  /**
+   * Presentation type, one of PRESENTATION_TYPE_*.
+   *
+   * @See TS 11.14, clause 12.6, Command Qualifier: Select Item
+   */
+  const short PRESENTATION_TYPE_NOT_SPECIFIED = 0x00;
+  const short PRESENTATION_TYPE_DATA_VALUES = 0x01;
+  const short PRESENTATION_TYPE_NAVIGATION_OPTIONS = 0x03;
+
+  readonly attribute unsigned short presentationType;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_SELECT_ITEM.
+ */
+[scriptable, uuid(816dc186-631b-11e4-864f-b37f7b54a1b8)]
+interface nsIStkSelectItemCmd : nsIStkMenuCmd
+{
+  const unsigned short DEFAULT_ITEM_INVALID = 0xFFFF;
+
+  /**
+   * (Optional)
+   * Default item identifier of the menu.
+   *
+   * Set to DEFAULT_ITEM_INVALID if null.
+   */
+  readonly attribute unsigned short defaultItem;
+};
+
+/**
+ * This interface is to be applied by
+ * - STK_CMD_SET_UP_IDLE_MODE_TEXT
+ * - STK_CMD_SEND_{SS|USSD|SMS|DTMF}
+ * - STK_CMD_OPEN_CHANNEL
+ * - STK_CMD_CLOSE_CHANNEL
+ * - STK_CMD_SEND_DATA
+ * - STK_CMD_RECEIVE_DATA
+ */
+[scriptable, uuid(61c42b3c-6324-11e4-959e-7fb2dc9a3f0d)]
+interface nsIStkTextMessageCmd : nsIStkProactiveCmd
+{
+  /**
+   * Text String.
+   */
+  readonly attribute DOMString text;
+
+  /**
+   * (Optional)
+   * Icon to be displayed.
+   */
+  readonly attribute nsIStkIconInfo iconInfo;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_DISPLAY_TEXT.
+ */
+[scriptable, uuid(66a83f0a-6322-11e4-a773-9382de87a74a)]
+interface nsIStkDisplayTextCmd : nsIStkTextMessageCmd
+{
+  /**
+   * (Optional)
+   * The length of time for which the ME shall display the dialog.
+   */
+  readonly attribute nsIStkDuration duration;
+
+  /**
+   * Indicate this text message is high priority or normal priority.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 1.
+   *
+   * true: high priority
+   * false: normal priority
+   */
+  readonly attribute boolean isHighPriority;
+
+  /**
+   * Need to wait for user to clear message or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, Display Text, bit 8.
+   *
+   * true: Wait for user to clear message.
+   * false: clear message after a delay.
+   */
+  readonly attribute boolean userClear;
+
+  /**
+   * Need to response immediately or not.
+   *
+   * @see TS 11.14, clause 12.43, Immediate response.
+   *
+   * true: The terminal shall send response immediately.
+   * false: otherwise.
+   */
+  readonly attribute boolean responseNeeded;
+};
+
+/**
+ * The base interface of nsIStkInputKeyCmd, nsIStkInputTextCmd.
+ */
+[scriptable, uuid(ed16a67e-6022-11e4-a8fd-c34fe6e6bb11)]
+interface nsIStkInputCmd : nsIStkProactiveCmd
+{
+  /**
+   * Text for the ME to display in conjunction with asking the user to respond.
+   */
+  readonly attribute DOMString text;
+
+  /**
+   * (Optional)
+   * The length of time for which the ME shall display the dialog.
+   */
+  readonly attribute nsIStkDuration duration;
+
+  /**
+   * Minimum length of response.
+   * Set to 1 for STK_CMD_GET_INKEY.
+   */
+  readonly attribute unsigned short minLength;
+
+  /**
+   * Maximum length of response.
+   * Set to 1 for STK_CMD_GET_INKEY.
+   */
+  readonly attribute unsigned short maxLength;
+
+  /**
+   * (Optional)
+   * Text for the ME to display, corresponds to a default text string offered
+   * by the ICC.
+   */
+  readonly attribute DOMString defaultText;
+
+  /**
+   * Input format.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 1.
+   *
+   * true: Alphabet set.
+   * false: Digits only.
+   */
+  readonly attribute boolean isAlphabet;
+
+  /**
+   * Alphabet encoding.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 2.
+   *
+   * true: UCS2 alphabet.
+   * false: default SMS alphabet.
+   */
+  readonly attribute boolean isUCS2;
+
+  /**
+   * Help information available or not.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT/GET INKEY, bit 8.
+   *
+   * true: help information available.
+   * false: no help information available.
+   */
+  readonly attribute boolean isHelpAvailable;
+
+  /**
+   * (Optional)
+   * Icon to be displayed.
+   */
+  readonly attribute nsIStkIconInfo iconInfo;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_GET_INKEY.
+ */
+[scriptable, uuid(27a4078a-6025-11e4-a9ab-bf39252bfaf1)]
+interface nsIStkInputKeyCmd : nsIStkInputCmd
+{
+  /**
+   * Yes/No response is requested.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INKEY, bit 3.
+   *
+   * true: Yes/No response is requested, and character sets
+   *       (Alphabet set and UCS2) are disabled.
+   * false: Character sets (Alphabet set and UCS2) are enabled.
+   */
+  readonly attribute boolean isYesNoRequested;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_GET_INPUT.
+ */
+[scriptable, uuid(f3c33ae8-60d4-11e4-9da8-4ff4cb8566c3)]
+interface nsIStkInputTextCmd : nsIStkInputCmd
+{
+  /**
+   * Visibility of input.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 3.
+   *
+   * true: User input shall not be revealed in any way.
+   * false: ME may echo user input on the display.
+   */
+  readonly attribute boolean hideInput;
+
+  /**
+   * User input in packed or unpacked format.
+   *
+   * @see TS 11.14, clause 12.6, Command Qualifier, GET INPUT, bit 4.
+   *
+   * true: User input to be in SMS packed format.
+   * false: User input to be in unpacked format.
+   */
+  readonly attribute boolean isPacked;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_SET_UP_CALL.
+ */
+[scriptable, uuid(6abbf688-6956-11e4-a9d3-4b07f063ef21)]
+interface nsIStkSetUpCallCmd : nsIStkProactiveCmd
+{
+  /**
+   * The Dialling number.
+   */
+  readonly attribute DOMString address;
+
+  /**
+   * (Optional)
+   * The text message used in user confirmation phase.
+   */
+  readonly attribute DOMString confirmText;
+
+  /**
+   * (Optional)
+   * Icon to be displayed in user confirmation phase.
+   */
+  readonly attribute nsIStkIconInfo confirmIconInfo;
+
+  /**
+   * (Optional)
+   * The text message used in call set up phase.
+   */
+  readonly attribute DOMString callText;
+
+  /**
+   * (Optional)
+   * Icon to be displayed in call set up phase.
+   */
+  readonly attribute nsIStkIconInfo callIconInfo;
+
+  /**
+   * (Optional)
+   * The maximum duration for the redial mechanism.
+   * The time elapsed since the first call set-up attempt has exceeded the duration
+   * requested by the UICC, the redial mechanism is terminated.
+   */
+  readonly attribute nsIStkDuration duration;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_LAUNCH_BROWSER.
+ */
+[scriptable, uuid(b9bca548-695b-11e4-8c1f-cfb850f421ab)]
+interface nsIStkBrowserSettingCmd : nsIStkProactiveCmd
+{
+  /**
+   * The URL to be opened by browser.
+   */
+  readonly attribute DOMString url;
+
+  /**
+   * Browser launch mode.
+   * @See TS 11.14, clause 12.6, Command Qualifier, LAUNCH BROWSER.
+   */
+  readonly attribute unsigned short mode;
+
+  /**
+   * (Optional)
+   * Confirm message to launch browser.
+   */
+  readonly attribute DOMString confirmText;
+
+  /**
+   * (Optional)
+   * Icon to be displayed in user confirmation phase.
+   */
+  readonly attribute nsIStkIconInfo confirmIconInfo;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_PLAY_TONE.
+ */
+[scriptable, uuid(f49dd148-60ee-11e4-af46-6b938538de51)]
+interface nsIStkPlayToneCmd : nsIStkProactiveCmd
+{
+  const unsigned short TONE_TYPE_INVALID = 0xFFFF;
+
+  /**
+   * (Optional)
+   * Text String.
+   */
+  readonly attribute DOMString text;
+
+  /**
+   * (Optional)
+   * One of the tone value coded in TS 11.14, clause 12.16, Tone.
+   *
+   * Set to TONE_TYPE_INVALID if null.
+   */
+  readonly attribute unsigned short tone;
+
+  /**
+   * (Optional)
+   * The length of time for which the ME shall generate the tone.
+   */
+  readonly attribute nsIStkDuration duration;
+
+  /**
+   * Need to vibrate or not.
+   * true: vibrate alert, if available, with the tone.
+   * false: use of vibrate alert is up to the ME.
+   */
+  readonly attribute boolean isVibrate;
+
+  /**
+   * (Optional)
+   * Icon to be displayed.
+   */
+  readonly attribute nsIStkIconInfo iconInfo;
+};
+
+/**
+ * This interface is to be applied by STK_CMD_TIMER_MANAGEMENT.
+ */
+[scriptable, uuid(e421b122-60f3-11e4-b8d7-bfe75825a796)]
+interface nsIStkTimerManagementCmd : nsIStkProactiveCmd
+{
+  /**
+   * Timer Information.
+   */
+  readonly attribute nsIStkTimer timerInfo;
+};
+
+[scriptable, uuid(000696fe-5d85-11e4-8da2-2fdf3880276b)]
+interface nsIIccMessenger : nsISupports
+{
+  /**
+   * To broadcast 'icc-stkcommand' system message
+   *
+   * @param aIccId
+   *        Integrated Circuit Card Identifier.
+   * @param aCommand
+   *        An instance of nsIStkProactiveCmd or its sub-class.
+   */
+  void notifyStkProactiveCommand(in DOMString aIccId,
+                                 in nsIStkProactiveCmd aCommand);
+};
--- a/dom/icc/moz.build
+++ b/dom/icc/moz.build
@@ -17,16 +17,21 @@ UNIFIED_SOURCES += [
     'Assertions.cpp',
     'Icc.cpp',
     'IccCardLockError.cpp',
     "IccInfo.cpp",
     'IccListener.cpp',
     'IccManager.cpp',
 ]
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
+    EXTRA_JS_MODULES += [
+        'gonk/StkProactiveCmdFactory.jsm',
+    ]
+
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/system/gonk',
--- a/dom/system/gonk/RILSystemMessenger.jsm
+++ b/dom/system/gonk/RILSystemMessenger.jsm
@@ -9,16 +9,22 @@ const {classes: Cc, interfaces: Ci, util
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "RIL", function () {
   let obj = {};
   Cu.import("resource://gre/modules/ril_consts.js", obj);
   return obj;
 });
 
+XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() {
+  let stk = {};
+  Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk);
+  return stk.StkProactiveCmdFactory;
+});
+
 /**
  * RILSystemMessenger
  */
 this.RILSystemMessenger = function() {};
 RILSystemMessenger.prototype = {
 
   /**
    * Hook of Broadcast function
@@ -297,14 +303,24 @@ RILSystemMessenger.prototype = {
   notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
     this.broadcastMessage("cdma-info-rec-received", {
       clientId: aServiceId,
       audioControl: {
         upLink: aUpLink,
         downLink: aDownLink
       }
     });
+  },
+
+  /**
+   * Wrapper to send 'icc-stkcommand' system message with Audio Control Info.
+   */
+  notifyStkProactiveCommand: function(aIccId, aCommand) {
+    this.broadcastMessage("icc-stkcommand", {
+      iccId: aIccId,
+      command: gStkCmdFactory.createCommandMessage(aCommand)
+    });
   }
 };
 
 this.EXPORTED_SYMBOLS = [
   'RILSystemMessenger'
 ];
--- a/dom/system/gonk/RILSystemMessengerHelper.js
+++ b/dom/system/gonk/RILSystemMessengerHelper.js
@@ -47,17 +47,18 @@ function RILSystemMessengerHelper() {
   };
 }
 RILSystemMessengerHelper.prototype = {
 
   classID: RILSYSTEMMESSENGERHELPER_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsITelephonyMessenger,
                                          Ci.nsISmsMessenger,
                                          Ci.nsICellbroadcastMessenger,
-                                         Ci.nsIMobileConnectionMessenger]),
+                                         Ci.nsIMobileConnectionMessenger,
+                                         Ci.nsIIccMessenger]),
 
   /**
    * RILSystemMessenger instance.
    */
   messenger: null,
 
   /**
    * nsITelephonyMessenger API
@@ -142,12 +143,19 @@ RILSystemMessengerHelper.prototype = {
   },
 
   notifyCdmaInfoRecClir: function(aServiceId, aCause) {
     this.messenger.notifyCdmaInfoRecClir(aServiceId, aCause);
   },
 
   notifyCdmaInfoRecAudioControl: function(aServiceId, aUpLink, aDownLink) {
     this.messenger.notifyCdmaInfoRecAudioControl(aServiceId, aUpLink, aDownLink);
+  },
+
+  /**
+   * nsIIccMessenger API
+   */
+  notifyStkProactiveCommand: function(aIccId, aCommand) {
+    this.messenger.notifyStkProactiveCommand(aIccId, aCommand);
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILSystemMessengerHelper]);
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -186,16 +186,26 @@ XPCOMUtils.defineLazyServiceGetter(this,
 XPCOMUtils.defineLazyServiceGetter(this, "gCellBroadcastService",
                                    "@mozilla.org/cellbroadcast/gonkservice;1",
                                    "nsIGonkCellBroadcastService");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gSmsMessenger",
                                    "@mozilla.org/ril/system-messenger-helper;1",
                                    "nsISmsMessenger");
 
+XPCOMUtils.defineLazyServiceGetter(this, "gIccMessenger",
+                                   "@mozilla.org/ril/system-messenger-helper;1",
+                                   "nsIIccMessenger");
+
+XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() {
+  let stk = {};
+  Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk);
+  return stk.StkProactiveCmdFactory;
+});
+
 XPCOMUtils.defineLazyGetter(this, "WAP", function() {
   let wap = {};
   Cu.import("resource://gre/modules/WapPushManager.js", wap);
   return wap;
 });
 
 XPCOMUtils.defineLazyGetter(this, "PhoneNumberUtils", function() {
   let ns = {};
@@ -2805,19 +2815,19 @@ RadioInterface.prototype = {
       gMobileConnectionService.notifySpnAvailable(this.clientId);
     }
   },
 
   handleStkProactiveCommand: function(message) {
     if (DEBUG) this.debug("handleStkProactiveCommand " + JSON.stringify(message));
     let iccId = this.rilContext.iccInfo && this.rilContext.iccInfo.iccid;
     if (iccId) {
-      gSystemMessenger.broadcastMessage("icc-stkcommand",
-                                        {iccId: iccId,
-                                         command: message});
+      gIccMessenger
+        .notifyStkProactiveCommand(iccId,
+                                   gStkCmdFactory.createCommand(message));
     }
     gMessageManager.sendIccMessage("RIL:StkCommand", this.clientId, message);
   },
 
   _convertCbGsmGeographicalScope: function(aGeographicalScope) {
     return (aGeographicalScope != null)
       ? aGeographicalScope
       : Ci.nsICellBroadcastService.GSM_GEOGRAPHICAL_SCOPE_INVALID;
--- a/dom/system/gonk/ril_consts.js
+++ b/dom/system/gonk/ril_consts.js
@@ -1059,16 +1059,21 @@ this.STK_LOCAL_INFO_MULTIPLE_ACCESS_TECH
 this.STK_LOCAL_INFO_INFO_FOR_MULTIPLE_ACCESS_TECH = 0x0F;
 this.STK_LOCAL_INFO_NMR_FOR_MULTIPLE_ACCESS_TECH = 0x10;
 
 // Timer Management.
 this.STK_TIMER_START = 0x00;
 this.STK_TIMER_DEACTIVATE = 0x01;
 this.STK_TMIER_GET_CURRENT_VALUE = 0x02;
 
+// Browser Launch Mode.
+this.STK_BROWSER_MODE_LAUNCH_IF_NOT_ALREADY_LAUNCHED = 0x00;
+this.STK_BROWSER_MODE_USING_EXISTING_BROWSER         = 0x02;
+this.STK_BROWSER_MODE_USING_NEW_BROWSER              = 0x03;
+
 // Browser Termination Cause.
 this.STK_BROWSER_TERMINATION_CAUSE_USER = 0x00;
 this.STK_BROWSER_TERMINATION_CAUSE_ERROR = 0x01;
 
 // Next Action Indicator.
 this.STK_NEXT_ACTION_NULL = 0x00;
 this.STK_NEXT_ACTION_END_PROACTIVE_SESSION = 0x81;
 
--- a/dom/system/gonk/tests/test_ril_system_messenger.js
+++ b/dom/system/gonk/tests/test_ril_system_messenger.js
@@ -1,15 +1,24 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
+let RIL = {};
+Cu.import("resource://gre/modules/ril_consts.js", RIL);
+
+XPCOMUtils.defineLazyGetter(this, "gStkCmdFactory", function() {
+  let stk = {};
+  Cu.import("resource://gre/modules/StkProactiveCmdFactory.jsm", stk);
+  return stk.StkProactiveCmdFactory;
+});
+
 /**
  * Name space for RILSystemMessenger.jsm. Only initialized after first call to
  * newRILSystemMessenger.
  */
 let RSM;
 
 let gReceivedMsgType = null;
 let gReceivedMessage = null;
@@ -52,20 +61,24 @@ function run_test() {
                      .getService(Ci.nsISmsMessenger);
 
   let cellbroadcastMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
                                .getService(Ci.nsICellbroadcastMessenger);
 
   let mobileConnectionMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
                                   .getService(Ci.nsIMobileConnectionMessenger);
 
+  let iccMessenger = Cc["@mozilla.org/ril/system-messenger-helper;1"]
+                     .getService(Ci.nsIIccMessenger);
+
   ok(telephonyMessenger !== null, "Get TelephonyMessenger.");
   ok(smsMessenger != null, "Get SmsMessenger.");
   ok(cellbroadcastMessenger != null, "Get CellbroadcastMessenger.");
   ok(mobileConnectionMessenger != null, "Get MobileConnectionMessenger.");
+  ok(iccMessenger != null, "Get IccMessenger.");
 
   run_next_test();
 }
 
 /**
  * Verify RILSystemMessenger.notifyNewCall()
  */
 add_test(function test_telephony_messenger_notify_new_call() {
@@ -506,8 +519,593 @@ add_test(function test_mobileconnection_
     audioControl: {
       upLink: 255,
       downLink: -1
     }
   });
 
   run_next_test();
 });
+
+/**
+ * Verify Error Handling of StkProactiveCmdFactory.createCommand()
+ */
+add_test(function test_icc_stk_cmd_factory_create_command_error() {
+  let messenger = newRILSystemMessenger();
+
+  // Verify the protection of invalid typeOfCommand.
+  try {
+    gStkCmdFactory.createCommand({
+      commandNumber: 0,
+      typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
+      commandQualifier: 0x00
+    });
+
+    ok(false, "Failed to verify the protection of createCommand()!");
+  } catch (e) {
+    equal(e.message, "Unknown Command Type: " + RIL.STK_CMD_MORE_TIME);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
+ */
+add_test(function test_icc_stk_cmd_factory_create_system_msg_invalid_cmd_type() {
+  let messenger = newRILSystemMessenger();
+  let iccId = "99887766554433221100";
+
+  // Verify the protection of invalid typeOfCommand.
+  try {
+    gStkCmdFactory.createCommandMessage({
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd]),
+
+      // nsIStkProactiveCmd
+      commandNumber: 0,
+      typeOfCommand: RIL.STK_CMD_MORE_TIME, // Invalid TypeOfCommand
+      commandQualifier: 0
+    });
+
+    ok(false, "Failed to identify invalid typeOfCommand!");
+  } catch (e) {
+    equal(e.message, "Unknown Command Type: " + RIL.STK_CMD_MORE_TIME);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify Error Handling of StkProactiveCmdFactory.createCommandMessage()
+ */
+add_test(function test_icc_stk_cmd_factory_create_system_msg_incorrect_cmd_type() {
+  let messenger = newRILSystemMessenger();
+  let iccId = "99887766554433221100";
+
+  // Verify the protection of invalid typeOfCommand.
+  try {
+    gStkCmdFactory.createCommandMessage({
+      QueryInterface: XPCOMUtils.generateQI([Ci.nsIStkProactiveCmd,
+                                             Ci.nsIStkProvideLocalInfoCmd]),
+
+      // nsIStkProactiveCmd
+      commandNumber: 0,
+      typeOfCommand: RIL.STK_CMD_POLL_INTERVAL, // Incorrect typeOfCommand
+      commandQualifier: 0,
+      // nsIStkProvideLocalInfoCmd
+      localInfoType: 0x00,
+    });
+
+    ok(false, "Failed to identify incorrect typeOfCommand!");
+  } catch (e) {
+    ok(e.message.indexOf("Failed to convert command into concrete class: ") !== -1);
+  }
+
+  run_next_test();
+});
+
+/**
+ * Verify RILSystemMessenger.notifyStkProactiveCommand()
+ */
+add_test(function test_icc_notify_stk_proactive_command() {
+  let messenger = newRILSystemMessenger();
+  let iccId = "99887766554433221100";
+  let WHT = 0xFFFFFFFF;
+  let BLK = 0x000000FF;
+  let RED = 0xFF0000FF;
+  let GRN = 0x00FF00FF;
+  let BLU = 0x0000FFFF;
+  let TSP = 0;
+  // Basic Image, see Anex B.1 in TS 31.102.
+  let basicIcon = {
+    width: 8,
+    height: 8,
+    codingScheme: "basic",
+    pixels: [WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT,
+             BLK, BLK, BLK, BLK, BLK, BLK, WHT, WHT,
+             WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
+             WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
+             WHT, BLK, BLK, WHT, WHT, BLK, BLK, WHT,
+             WHT, BLK, WHT, BLK, BLK, WHT, BLK, WHT,
+             WHT, WHT, BLK, BLK, BLK, BLK, WHT, WHT,
+             WHT, WHT, WHT, WHT, WHT, WHT, WHT, WHT]
+  };
+  // Color Image, see Anex B.2 in TS 31.102.
+  let colorIcon = {
+    width: 8,
+    height: 8,
+    codingScheme: "color",
+    pixels: [BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU,
+             BLU, RED, RED, RED, RED, RED, RED, BLU,
+             BLU, RED, GRN, GRN, GRN, RED, RED, BLU,
+             BLU, RED, RED, GRN, GRN, RED, RED, BLU,
+             BLU, RED, RED, GRN, GRN, RED, RED, BLU,
+             BLU, RED, RED, GRN, GRN, GRN, RED, BLU,
+             BLU, RED, RED, RED, RED, RED, RED, BLU,
+             BLU, BLU, BLU, BLU, BLU, BLU, BLU, BLU]
+  };
+  // Color Image with Transparency, see Anex B.2 in TS 31.102.
+  let colorTransparencyIcon = {
+    width: 8,
+    height: 8,
+    codingScheme: "color-transparency",
+    pixels: [TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP,
+             TSP, RED, RED, RED, RED, RED, RED, TSP,
+             TSP, RED, GRN, GRN, GRN, RED, RED, TSP,
+             TSP, RED, RED, GRN, GRN, RED, RED, TSP,
+             TSP, RED, RED, GRN, GRN, RED, RED, TSP,
+             TSP, RED, RED, GRN, GRN, GRN, RED, TSP,
+             TSP, RED, RED, RED, RED, RED, RED, TSP,
+             TSP, TSP, TSP, TSP, TSP, TSP, TSP, TSP]
+  };
+
+  let cmdCount = 0;
+
+  // Test Messages:
+  let messages = [
+    // STK_CMD_REFRESH
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_REFRESH,
+      commandQualifier: 0x04 // UICC Reset
+    },
+    // STK_CMD_POLL_INTERVAL
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_POLL_INTERVAL,
+      commandQualifier: 0x00, // RFU
+      options: {
+        timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
+        timeInterval: 0x05
+      }
+    },
+    // STK_CMD_POLL_OFF
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_POLL_OFF,
+      commandQualifier: 0x00, // RFU
+    },
+    // STK_CMD_PROVIDE_LOCAL_INFO
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_PROVIDE_LOCAL_INFO,
+      commandQualifier: 0x01, // IMEI of the terminal
+      options: {
+        localInfoType: 0x01 // IMEI of the terminal
+      }
+    },
+    // STK_CMD_SET_UP_EVENT_LIST with eventList
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
+      commandQualifier: 0x00, // RFU
+      options: {
+        eventList: [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                     0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
+                     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+                     0x18, 0x19, 0x1A, 0x1B, 0x1C ]
+      }
+    },
+    // STK_CMD_SET_UP_EVENT_LIST without eventList
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_EVENT_LIST,
+      commandQualifier: 0x00, // RFU
+      options: {
+        eventList: null
+      }
+    },
+    // STK_CMD_SET_UP_MENU with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
+      commandQualifier: 0x80, // bit 8: 1 = help information available
+      options: {
+        title: "Toolkit Menu 1",
+        items: [
+          { identifier: 0x01, text: "Menu Item 1" },
+          { identifier: 0x02, text: "Menu Item 2" },
+          { identifier: 0x03, text: "Menu Item 3" }
+        ],
+        presentationType: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
+        isHelpAvailable: true
+      }
+    },
+    // STK_CMD_SET_UP_MENU with optional properties including:
+    // iconInfo for this menu, iconInfo for each item and nextActionList.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_MENU,
+      commandQualifier: 0x00, // bit 8: 0 = help information is not available
+      options: {
+        title: "Toolkit Menu 2",
+        items: [
+          { identifier: 0x01,
+            text: "Menu Item 1",
+            iconSelfExplanatory: true,
+            icons: [basicIcon]
+          },
+          { identifier: 0x02,
+            text: "Menu Item 2",
+            iconSelfExplanatory: false,
+            icons: [basicIcon, colorIcon]
+          },
+          { identifier: 0x03,
+            text: "Menu Item 3",
+            iconSelfExplanatory: true,
+            icons: [basicIcon, colorIcon, colorTransparencyIcon]
+          },
+        ],
+        nextActionList: [
+          RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
+          RIL.STK_NEXT_ACTION_NULL,
+          RIL.STK_NEXT_ACTION_NULL,
+          RIL.STK_NEXT_ACTION_NULL
+        ],
+        iconSelfExplanatory: false,
+        icons: [basicIcon, colorIcon, colorTransparencyIcon],
+        presentationType: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
+        isHelpAvailable: false
+      }
+    },
+    // STK_CMD_SELECT_ITEM with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
+      commandQualifier: RIL.STK_PRESENTATION_TYPE_NOT_SPECIFIED,
+      options: {
+        items: [
+          { identifier: 0x01, text: "Menu Item 1" },
+          { identifier: 0x02, text: "Menu Item 2" },
+          { identifier: 0x03, text: "Menu Item 3" }
+        ],
+        isHelpAvailable: false
+      }
+    },
+    // STK_CMD_SELECT_ITEM with optional properties including:
+    // title, iconInfo for this menu, iconInfo for each item and nextActionList.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SELECT_ITEM,
+      commandQualifier: RIL.STK_PRESENTATION_TYPE_NAVIGATION_OPTIONS,
+      options: {
+        title: "Selected Toolkit Menu",
+        items: [
+          { identifier: 0x01,
+            text: "Menu Item 1",
+            iconSelfExplanatory: true,
+            icons: [basicIcon]
+          },
+          { identifier: 0x02,
+            text: "Menu Item 2",
+            iconSelfExplanatory: false,
+            icons: [basicIcon, colorIcon]
+          },
+          { identifier: 0x03,
+            text: "Menu Item 3",
+            iconSelfExplanatory: true,
+            icons: [basicIcon, colorIcon, colorTransparencyIcon]
+          },
+        ],
+        nextActionList: [
+          RIL.STK_NEXT_ACTION_END_PROACTIVE_SESSION,
+          RIL.STK_NEXT_ACTION_NULL,
+          RIL.STK_NEXT_ACTION_NULL,
+          RIL.STK_NEXT_ACTION_NULL
+        ],
+        defaultItem: 0x02,
+        iconSelfExplanatory: false,
+        icons: [basicIcon, colorIcon, colorTransparencyIcon],
+        isHelpAvailable: false
+      }
+    },
+    // STK_CMD_DISPLAY_TEXT with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
+      commandQualifier: 0x01, // bit 1: High Priority
+      options: {
+        text: "Display Text 1",
+        isHighPriority: true,
+        userClear: false,
+        responseNeeded: false
+      }
+    },
+    // STK_CMD_DISPLAY_TEXT with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_DISPLAY_TEXT,
+      commandQualifier: 0x80, // bit 8: User Clear
+      options: {
+        text: "Display Text 2",
+        isHighPriority: false,
+        userClear: true,
+        responseNeeded: true,
+        duration: {
+          timeUnit: RIL.STK_TIME_UNIT_TENTH_SECOND,
+          timeInterval: 0x05
+        },
+        iconSelfExplanatory: true,
+        icons: [basicIcon]
+      }
+    },
+    // STK_CMD_SET_UP_IDLE_MODE_TEXT
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_IDLE_MODE_TEXT,
+      commandQualifier: 0x00, // RFU
+      options: {
+        text: "Setup Idle Mode Text"
+      }
+    },
+    // STK_CMD_SEND_SS
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SEND_SS,
+      commandQualifier: 0x00, // RFU
+      options: {
+        text: "Send SS",
+        iconSelfExplanatory: true,
+        icons: [colorIcon]
+      }
+    },
+    // STK_CMD_SEND_USSD
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SEND_USSD,
+      commandQualifier: 0x00, // RFU
+      options: {
+        text: "Send USSD"
+      }
+    },
+    // STK_CMD_SEND_SMS
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SEND_SMS,
+      commandQualifier: 0x00, // RFU
+      options: {
+        text: "Send SMS",
+        iconSelfExplanatory: false,
+        icons: [colorTransparencyIcon]
+      }
+    },
+    // STK_CMD_SEND_DTMF
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SEND_DTMF,
+      commandQualifier: 0x00, // RFU
+      options: {
+        text: "Send DTMF",
+        iconSelfExplanatory: true,
+        icons: [basicIcon]
+      }
+    },
+    // STK_CMD_GET_INKEY
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_GET_INKEY,
+      commandQualifier: 0x84, // bit 3: isYesNoRequested, bit 8: isHelpAvailable
+      options: {
+        text: "Get Input Key",
+        minLength: 1,
+        maxLength: 1,
+        duration: {
+          timeUnit: RIL.STK_TIME_UNIT_SECOND,
+          timeInterval: 0x0A
+        },
+        isAlphabet: false,
+        isUCS2: false,
+        isYesNoRequested: true,
+        isHelpAvailable: true,
+        iconSelfExplanatory: false,
+        icons: [colorIcon]
+      }
+    },
+    // STK_CMD_GET_INPUT
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_GET_INPUT,
+      commandQualifier: 0x0F, // bit 1-4: isAlphabet, isUCS2, hideInput, isPacked
+      options: {
+        text: "Get Input Text",
+        minLength: 1,
+        maxLength: 255,
+        defaultText: "Default Input Text",
+        isAlphabet: true,
+        isUCS2: true,
+        hideInput: true,
+        isPacked: true,
+        isHelpAvailable: false,
+        iconSelfExplanatory: true,
+        icons: [basicIcon]
+      }
+    },
+    // STK_CMD_SET_UP_CALL with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
+      commandQualifier: 0x00, // RFU
+      options: {
+        address: "+0987654321"
+      }
+    },
+    // STK_CMD_SET_UP_CALL with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SET_UP_CALL,
+      commandQualifier: 0x00, // RFU
+      options: {
+        address: "+0987654321",
+        confirmMessage: {
+          text: "Confirm Message",
+          iconSelfExplanatory: false,
+          icons: [colorIcon]
+        },
+        callMessage: {
+          text: "Call Message",
+          iconSelfExplanatory: true,
+          icons: [basicIcon]
+        },
+        duration: {
+          timeUnit: RIL.STK_TIME_UNIT_SECOND,
+          timeInterval: 0x0A
+        }
+      }
+    },
+    // STK_CMD_LAUNCH_BROWSER with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
+      commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
+      options: {
+        url: "http://www.mozilla.org",
+        mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER
+      }
+    },
+    // STK_CMD_LAUNCH_BROWSER with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_LAUNCH_BROWSER,
+      commandQualifier: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
+      options: {
+        url: "http://www.mozilla.org",
+        mode: RIL.STK_BROWSER_MODE_USING_NEW_BROWSER,
+        confirmMessage: {
+          text: "Confirm Message for Launch Browser",
+          iconSelfExplanatory: false,
+          icons: [colorTransparencyIcon]
+        }
+      }
+    },
+    // STK_CMD_PLAY_TONE with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_PLAY_TONE,
+      commandQualifier: 0x01, // isVibrate
+      options: {
+        isVibrate: true
+      }
+    },
+    // STK_CMD_PLAY_TONE with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_PLAY_TONE,
+      commandQualifier: 0x00, // isVibrate = false
+      options: {
+        text: "Play Tone",
+        tone: RIL.STK_TONE_TYPE_CONGESTION,
+        isVibrate: false,
+        duration: {
+          timeUnit: RIL.STK_TIME_UNIT_SECOND,
+          timeInterval: 0x0A
+        },
+        iconSelfExplanatory: true,
+        icons: [basicIcon]
+      }
+    },
+    // STK_CMD_TIMER_MANAGEMENT with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
+      commandQualifier: RIL.STK_TIMER_DEACTIVATE,
+      options: {
+        timerId: 0x08,
+        timerAction: RIL.STK_TIMER_DEACTIVATE
+      }
+    },
+    // STK_CMD_TIMER_MANAGEMENT with optional properties.
+    {
+      commandNumber: ++cmdCount,
+        typeOfCommand: RIL.STK_CMD_TIMER_MANAGEMENT,
+        commandQualifier: RIL.STK_TIMER_START,
+        options: {
+          timerId: 0x01,
+          timerValue: (12 * 60 * 60) + (30 * 60) + (30), // 12:30:30
+          timerAction: RIL.STK_TIMER_START
+        }
+    },
+    // STK_CMD_OPEN_CHANNEL with mandatory properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
+      commandQualifier: 0x00,  //RFU
+      options: {
+      }
+    },
+    // STK_CMD_OPEN_CHANNEL with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_OPEN_CHANNEL,
+      commandQualifier: 0x00,  //RFU
+      options: {
+        text: "Open Channel",
+        iconSelfExplanatory: false,
+        icons: [colorIcon]
+      }
+    },
+    // STK_CMD_CLOSE_CHANNEL with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_CLOSE_CHANNEL,
+      commandQualifier: 0x00,  //RFU
+      options: {
+        text: "Close Channel",
+        iconSelfExplanatory: true,
+        icons: [colorTransparencyIcon]
+      }
+    },
+    // STK_CMD_SEND_DATA with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_SEND_DATA,
+      commandQualifier: 0x00,  //RFU
+      options: {
+        iconSelfExplanatory: false,
+        icons: [basicIcon]
+      }
+    },
+    // STK_CMD_RECEIVE_DATA with optional properties.
+    {
+      commandNumber: ++cmdCount,
+      typeOfCommand: RIL.STK_CMD_RECEIVE_DATA,
+      commandQualifier: 0x00,  //RFU
+      options: {
+        text: "Receive Data"
+      }
+    },
+    null // Termination condition to run_next_test()
+  ];
+
+  messages.forEach(function(aMessage) {
+    if (!aMessage) {
+      run_next_test();
+      return;
+    }
+
+    messenger.notifyStkProactiveCommand(iccId,
+                                        gStkCmdFactory.createCommand(aMessage));
+
+    equal_received_system_message("icc-stkcommand", {
+      iccId: iccId,
+      command: aMessage
+    });
+  });
+});