dom/system/gonk/RILContentHelper.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/system/gonk/RILContentHelper.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2236 @@
     1.4 +/* Copyright 2012 Mozilla Foundation and Mozilla contributors
     1.5 + *
     1.6 + * Licensed under the Apache License, Version 2.0 (the "License");
     1.7 + * you may not use this file except in compliance with the License.
     1.8 + * You may obtain a copy of the License at
     1.9 + *
    1.10 + *     http://www.apache.org/licenses/LICENSE-2.0
    1.11 + *
    1.12 + * Unless required by applicable law or agreed to in writing, software
    1.13 + * distributed under the License is distributed on an "AS IS" BASIS,
    1.14 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    1.15 + * See the License for the specific language governing permissions and
    1.16 + * limitations under the License.
    1.17 + */
    1.18 +
    1.19 +"use strict";
    1.20 +
    1.21 +const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
    1.22 +
    1.23 +Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
    1.24 +Cu.import("resource://gre/modules/Services.jsm");
    1.25 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.26 +
    1.27 +var RIL = {};
    1.28 +Cu.import("resource://gre/modules/ril_consts.js", RIL);
    1.29 +
    1.30 +const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
    1.31 +
    1.32 +const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
    1.33 +
    1.34 +const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
    1.35 +const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
    1.36 +const kPrefVoicemailDefaultServiceId = "dom.voicemail.defaultServiceId";
    1.37 +
    1.38 +let DEBUG;
    1.39 +function debug(s) {
    1.40 +  dump("-*- RILContentHelper: " + s + "\n");
    1.41 +}
    1.42 +
    1.43 +const RILCONTENTHELPER_CID =
    1.44 +  Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
    1.45 +const GSMICCINFO_CID =
    1.46 +  Components.ID("{e0fa785b-ad3f-46ed-bc56-fcb0d6fe4fa8}");
    1.47 +const CDMAICCINFO_CID =
    1.48 +  Components.ID("{3d1f844f-9ec5-48fb-8907-aed2e5421709}");
    1.49 +const MOBILECONNECTIONINFO_CID =
    1.50 +  Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
    1.51 +const MOBILENETWORKINFO_CID =
    1.52 +  Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
    1.53 +const MOBILECELLINFO_CID =
    1.54 +  Components.ID("{ae724dd4-ccaf-4006-98f1-6ce66a092464}");
    1.55 +const VOICEMAILSTATUS_CID=
    1.56 +  Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
    1.57 +const MOBILECFINFO_CID=
    1.58 +  Components.ID("{a4756f16-e728-4d9f-8baa-8464f894888a}");
    1.59 +const CELLBROADCASTMESSAGE_CID =
    1.60 +  Components.ID("{29474c96-3099-486f-bb4a-3c9a1da834e4}");
    1.61 +const CELLBROADCASTETWSINFO_CID =
    1.62 +  Components.ID("{59f176ee-9dcd-4005-9d47-f6be0cd08e17}");
    1.63 +const DOMMMIERROR_CID =
    1.64 +  Components.ID("{6b204c42-7928-4e71-89ad-f90cd82aff96}");
    1.65 +const ICCCARDLOCKERROR_CID =
    1.66 +  Components.ID("{08a71987-408c-44ff-93fd-177c0a85c3dd}");
    1.67 +
    1.68 +const RIL_IPC_MSG_NAMES = [
    1.69 +  "RIL:CardStateChanged",
    1.70 +  "RIL:IccInfoChanged",
    1.71 +  "RIL:VoiceInfoChanged",
    1.72 +  "RIL:DataInfoChanged",
    1.73 +  "RIL:GetAvailableNetworks",
    1.74 +  "RIL:NetworkSelectionModeChanged",
    1.75 +  "RIL:SelectNetwork",
    1.76 +  "RIL:SelectNetworkAuto",
    1.77 +  "RIL:SetPreferredNetworkType",
    1.78 +  "RIL:GetPreferredNetworkType",
    1.79 +  "RIL:EmergencyCbModeChanged",
    1.80 +  "RIL:VoicemailNotification",
    1.81 +  "RIL:VoicemailInfoChanged",
    1.82 +  "RIL:CardLockResult",
    1.83 +  "RIL:CardLockRetryCount",
    1.84 +  "RIL:USSDReceived",
    1.85 +  "RIL:SendMMI",
    1.86 +  "RIL:CancelMMI",
    1.87 +  "RIL:StkCommand",
    1.88 +  "RIL:StkSessionEnd",
    1.89 +  "RIL:DataError",
    1.90 +  "RIL:SetCallForwardingOptions",
    1.91 +  "RIL:GetCallForwardingOptions",
    1.92 +  "RIL:SetCallBarringOptions",
    1.93 +  "RIL:GetCallBarringOptions",
    1.94 +  "RIL:ChangeCallBarringPassword",
    1.95 +  "RIL:SetCallWaitingOptions",
    1.96 +  "RIL:GetCallWaitingOptions",
    1.97 +  "RIL:SetCallingLineIdRestriction",
    1.98 +  "RIL:GetCallingLineIdRestriction",
    1.99 +  "RIL:CellBroadcastReceived",
   1.100 +  "RIL:CfStateChanged",
   1.101 +  "RIL:IccOpenChannel",
   1.102 +  "RIL:IccCloseChannel",
   1.103 +  "RIL:IccExchangeAPDU",
   1.104 +  "RIL:ReadIccContacts",
   1.105 +  "RIL:UpdateIccContact",
   1.106 +  "RIL:SetRoamingPreference",
   1.107 +  "RIL:GetRoamingPreference",
   1.108 +  "RIL:ExitEmergencyCbMode",
   1.109 +  "RIL:SetRadioEnabled",
   1.110 +  "RIL:RadioStateChanged",
   1.111 +  "RIL:SetVoicePrivacyMode",
   1.112 +  "RIL:GetVoicePrivacyMode",
   1.113 +  "RIL:OtaStatusChanged",
   1.114 +  "RIL:MatchMvno"
   1.115 +];
   1.116 +
   1.117 +XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
   1.118 +                                   "@mozilla.org/childprocessmessagemanager;1",
   1.119 +                                   "nsISyncMessageSender");
   1.120 +
   1.121 +XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() {
   1.122 +  let appInfo = Cc["@mozilla.org/xre/app-info;1"];
   1.123 +  let isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
   1.124 +                          .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
   1.125 +
   1.126 +  if (isParentProcess) {
   1.127 +    let ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
   1.128 +    return ril.numRadioInterfaces;
   1.129 +  }
   1.130 +
   1.131 +  return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
   1.132 +});
   1.133 +
   1.134 +function MobileIccCardLockResult(options) {
   1.135 +  this.lockType = options.lockType;
   1.136 +  this.enabled = options.enabled;
   1.137 +  this.retryCount = options.retryCount;
   1.138 +  this.success = options.success;
   1.139 +}
   1.140 +MobileIccCardLockResult.prototype = {
   1.141 +  __exposedProps__ : {lockType: 'r',
   1.142 +                      enabled: 'r',
   1.143 +                      retryCount: 'r',
   1.144 +                      success: 'r'}
   1.145 +};
   1.146 +
   1.147 +function MobileIccCardLockRetryCount(options) {
   1.148 +  this.lockType = options.lockType;
   1.149 +  this.retryCount = options.retryCount;
   1.150 +  this.success = options.success;
   1.151 +}
   1.152 +MobileIccCardLockRetryCount.prototype = {
   1.153 +  __exposedProps__ : {lockType: 'r',
   1.154 +                      retryCount: 'r',
   1.155 +                      success: 'r'}
   1.156 +};
   1.157 +
   1.158 +function IccInfo() {}
   1.159 +IccInfo.prototype = {
   1.160 +  iccType: null,
   1.161 +  iccid: null,
   1.162 +  mcc: null,
   1.163 +  mnc: null,
   1.164 +  spn: null,
   1.165 +  isDisplayNetworkNameRequired: null,
   1.166 +  isDisplaySpnRequired: null
   1.167 +};
   1.168 +
   1.169 +function GsmIccInfo() {}
   1.170 +GsmIccInfo.prototype = {
   1.171 +  __proto__: IccInfo.prototype,
   1.172 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozGsmIccInfo]),
   1.173 +  classID: GSMICCINFO_CID,
   1.174 +  classInfo: XPCOMUtils.generateCI({
   1.175 +    classID:          GSMICCINFO_CID,
   1.176 +    classDescription: "MozGsmIccInfo",
   1.177 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.178 +    interfaces:       [Ci.nsIDOMMozGsmIccInfo]
   1.179 +  }),
   1.180 +
   1.181 +  // nsIDOMMozGsmIccInfo
   1.182 +
   1.183 +  msisdn: null
   1.184 +};
   1.185 +
   1.186 +function CdmaIccInfo() {}
   1.187 +CdmaIccInfo.prototype = {
   1.188 +  __proto__: IccInfo.prototype,
   1.189 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCdmaIccInfo]),
   1.190 +  classID: CDMAICCINFO_CID,
   1.191 +  classInfo: XPCOMUtils.generateCI({
   1.192 +    classID:          CDMAICCINFO_CID,
   1.193 +    classDescription: "MozCdmaIccInfo",
   1.194 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.195 +    interfaces:       [Ci.nsIDOMMozCdmaIccInfo]
   1.196 +  }),
   1.197 +
   1.198 +  // nsIDOMMozCdmaIccInfo
   1.199 +
   1.200 +  mdn: null,
   1.201 +  prlVersion: 0
   1.202 +};
   1.203 +
   1.204 +function VoicemailInfo() {}
   1.205 +VoicemailInfo.prototype = {
   1.206 +  number: null,
   1.207 +  displayName: null
   1.208 +};
   1.209 +
   1.210 +function MobileConnectionInfo() {}
   1.211 +MobileConnectionInfo.prototype = {
   1.212 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileConnectionInfo]),
   1.213 +  classID:        MOBILECONNECTIONINFO_CID,
   1.214 +  classInfo:      XPCOMUtils.generateCI({
   1.215 +    classID:          MOBILECONNECTIONINFO_CID,
   1.216 +    classDescription: "MobileConnectionInfo",
   1.217 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.218 +    interfaces:       [Ci.nsIDOMMozMobileConnectionInfo]
   1.219 +  }),
   1.220 +
   1.221 +  // nsIDOMMozMobileConnectionInfo
   1.222 +
   1.223 +  connected: false,
   1.224 +  state: null,
   1.225 +  emergencyCallsOnly: false,
   1.226 +  roaming: false,
   1.227 +  network: null,
   1.228 +  cell: null,
   1.229 +  type: null,
   1.230 +  signalStrength: null,
   1.231 +  relSignalStrength: null
   1.232 +};
   1.233 +
   1.234 +function MobileNetworkInfo() {}
   1.235 +MobileNetworkInfo.prototype = {
   1.236 +  __exposedProps__ : {shortName: 'r',
   1.237 +                      longName: 'r',
   1.238 +                      mcc: 'r',
   1.239 +                      mnc: 'r',
   1.240 +                      state: 'r'},
   1.241 +
   1.242 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileNetworkInfo]),
   1.243 +  classID:        MOBILENETWORKINFO_CID,
   1.244 +  classInfo:      XPCOMUtils.generateCI({
   1.245 +    classID:          MOBILENETWORKINFO_CID,
   1.246 +    classDescription: "MobileNetworkInfo",
   1.247 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.248 +    interfaces:       [Ci.nsIDOMMozMobileNetworkInfo]
   1.249 +  }),
   1.250 +
   1.251 +  // nsIDOMMozMobileNetworkInfo
   1.252 +
   1.253 +  shortName: null,
   1.254 +  longName: null,
   1.255 +  mcc: null,
   1.256 +  mnc: null,
   1.257 +  state: null
   1.258 +};
   1.259 +
   1.260 +function MobileCellInfo() {}
   1.261 +MobileCellInfo.prototype = {
   1.262 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileCellInfo]),
   1.263 +  classID:        MOBILECELLINFO_CID,
   1.264 +  classInfo:      XPCOMUtils.generateCI({
   1.265 +    classID:          MOBILECELLINFO_CID,
   1.266 +    classDescription: "MobileCellInfo",
   1.267 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.268 +    interfaces:       [Ci.nsIDOMMozMobileCellInfo]
   1.269 +  }),
   1.270 +
   1.271 +  // nsIDOMMozMobileCellInfo
   1.272 +
   1.273 +  gsmLocationAreaCode: -1,
   1.274 +  gsmCellId: -1,
   1.275 +  cdmaBaseStationId: -1,
   1.276 +  cdmaBaseStationLatitude: -2147483648,
   1.277 +  cdmaBaseStationLongitude: -2147483648,
   1.278 +  cdmaSystemId: -1,
   1.279 +  cdmaNetworkId: -1
   1.280 +};
   1.281 +
   1.282 +function VoicemailStatus(clientId) {
   1.283 +  this.serviceId = clientId;
   1.284 +}
   1.285 +VoicemailStatus.prototype = {
   1.286 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
   1.287 +  classID:        VOICEMAILSTATUS_CID,
   1.288 +  classInfo:      XPCOMUtils.generateCI({
   1.289 +    classID:          VOICEMAILSTATUS_CID,
   1.290 +    classDescription: "VoicemailStatus",
   1.291 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.292 +    interfaces:       [Ci.nsIDOMMozVoicemailStatus]
   1.293 +  }),
   1.294 +
   1.295 +  // nsIDOMMozVoicemailStatus
   1.296 +
   1.297 +  serviceId: -1,
   1.298 +  hasMessages: false,
   1.299 +  messageCount: -1, // Count unknown.
   1.300 +  returnNumber: null,
   1.301 +  returnMessage: null
   1.302 +};
   1.303 +
   1.304 +function MobileCFInfo() {}
   1.305 +MobileCFInfo.prototype = {
   1.306 +  __exposedProps__ : {active: 'r',
   1.307 +                      action: 'r',
   1.308 +                      reason: 'r',
   1.309 +                      number: 'r',
   1.310 +                      timeSeconds: 'r',
   1.311 +                      serviceClass: 'r'},
   1.312 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileCFInfo]),
   1.313 +  classID:        MOBILECFINFO_CID,
   1.314 +  classInfo:      XPCOMUtils.generateCI({
   1.315 +    classID:          MOBILECFINFO_CID,
   1.316 +    classDescription: "MobileCFInfo",
   1.317 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.318 +    interfaces:       [Ci.nsIDOMMozMobileCFInfo]
   1.319 +  }),
   1.320 +
   1.321 +  // nsIDOMMozMobileCFInfo
   1.322 +
   1.323 +  active: false,
   1.324 +  action: -1,
   1.325 +  reason: -1,
   1.326 +  number: null,
   1.327 +  timeSeconds: 0,
   1.328 +  serviceClass: -1
   1.329 +};
   1.330 +
   1.331 +function CellBroadcastMessage(pdu) {
   1.332 +  this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
   1.333 +  this.messageCode = pdu.messageCode;
   1.334 +  this.messageId = pdu.messageId;
   1.335 +  this.language = pdu.language;
   1.336 +  this.body = pdu.fullBody;
   1.337 +  this.messageClass = pdu.messageClass;
   1.338 +  this.timestamp = new Date(pdu.timestamp);
   1.339 +
   1.340 +  if (pdu.etws != null) {
   1.341 +    this.etws = new CellBroadcastEtwsInfo(pdu.etws);
   1.342 +  }
   1.343 +
   1.344 +  this.cdmaServiceCategory = pdu.serviceCategory;
   1.345 +}
   1.346 +CellBroadcastMessage.prototype = {
   1.347 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastMessage]),
   1.348 +  classID:        CELLBROADCASTMESSAGE_CID,
   1.349 +  classInfo:      XPCOMUtils.generateCI({
   1.350 +    classID:          CELLBROADCASTMESSAGE_CID,
   1.351 +    classDescription: "CellBroadcastMessage",
   1.352 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.353 +    interfaces:       [Ci.nsIDOMMozCellBroadcastMessage]
   1.354 +  }),
   1.355 +
   1.356 +  // nsIDOMMozCellBroadcastMessage
   1.357 +
   1.358 +  gsmGeographicalScope: null,
   1.359 +  messageCode: null,
   1.360 +  messageId: null,
   1.361 +  language: null,
   1.362 +  body: null,
   1.363 +  messageClass: null,
   1.364 +  timestamp: null,
   1.365 +
   1.366 +  etws: null,
   1.367 +  cdmaServiceCategory: null
   1.368 +};
   1.369 +
   1.370 +function CellBroadcastEtwsInfo(etwsInfo) {
   1.371 +  if (etwsInfo.warningType != null) {
   1.372 +    this.warningType = RIL.CB_ETWS_WARNING_TYPE_NAMES[etwsInfo.warningType];
   1.373 +  }
   1.374 +  this.emergencyUserAlert = etwsInfo.emergencyUserAlert;
   1.375 +  this.popup = etwsInfo.popup;
   1.376 +}
   1.377 +CellBroadcastEtwsInfo.prototype = {
   1.378 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastEtwsInfo]),
   1.379 +  classID:        CELLBROADCASTETWSINFO_CID,
   1.380 +  classInfo:      XPCOMUtils.generateCI({
   1.381 +    classID:          CELLBROADCASTETWSINFO_CID,
   1.382 +    classDescription: "CellBroadcastEtwsInfo",
   1.383 +    flags:            Ci.nsIClassInfo.DOM_OBJECT,
   1.384 +    interfaces:       [Ci.nsIDOMMozCellBroadcastEtwsInfo]
   1.385 +  }),
   1.386 +
   1.387 +  // nsIDOMMozCellBroadcastEtwsInfo
   1.388 +
   1.389 +  warningType: null,
   1.390 +  emergencyUserAlert: null,
   1.391 +  popup: null
   1.392 +};
   1.393 +
   1.394 +function CallBarringOptions(options) {
   1.395 +  this.program = options.program;
   1.396 +  this.enabled = options.enabled;
   1.397 +  this.password = options.password;
   1.398 +  this.serviceClass = options.serviceClass;
   1.399 +}
   1.400 +CallBarringOptions.prototype = {
   1.401 +  __exposedProps__ : {program: 'r',
   1.402 +                      enabled: 'r',
   1.403 +                      password: 'r',
   1.404 +                      serviceClass: 'r'}
   1.405 +};
   1.406 +
   1.407 +function DOMMMIResult(result) {
   1.408 +  this.serviceCode = result.serviceCode;
   1.409 +  this.statusMessage = result.statusMessage;
   1.410 +  this.additionalInformation = result.additionalInformation;
   1.411 +}
   1.412 +DOMMMIResult.prototype = {
   1.413 +  __exposedProps__: {serviceCode: 'r',
   1.414 +                     statusMessage: 'r',
   1.415 +                     additionalInformation: 'r'}
   1.416 +};
   1.417 +
   1.418 +function DOMCLIRStatus(option) {
   1.419 +  this.n = option.n;
   1.420 +  this.m = option.m;
   1.421 +}
   1.422 +DOMCLIRStatus.prototype = {
   1.423 +  __exposedProps__ : {n: 'r',
   1.424 +                      m: 'r'}
   1.425 +};
   1.426 +
   1.427 +function DOMMMIError() {
   1.428 +}
   1.429 +DOMMMIError.prototype = {
   1.430 +  classDescription: "DOMMMIError",
   1.431 +  classID:          DOMMMIERROR_CID,
   1.432 +  contractID:       "@mozilla.org/dom/mmi-error;1",
   1.433 +  QueryInterface:   XPCOMUtils.generateQI([Ci.nsISupports]),
   1.434 +  __init: function(serviceCode, name, message, additionalInformation) {
   1.435 +    this.__DOM_IMPL__.init(name, message);
   1.436 +    this.serviceCode = serviceCode;
   1.437 +    this.additionalInformation = additionalInformation;
   1.438 +  },
   1.439 +};
   1.440 +
   1.441 +function IccCardLockError() {
   1.442 +}
   1.443 +IccCardLockError.prototype = {
   1.444 +  classDescription: "IccCardLockError",
   1.445 +  classID:          ICCCARDLOCKERROR_CID,
   1.446 +  contractID:       "@mozilla.org/dom/icccardlock-error;1",
   1.447 +  QueryInterface:   XPCOMUtils.generateQI([Ci.nsISupports]),
   1.448 +  __init: function(lockType, errorMsg, retryCount) {
   1.449 +    this.__DOM_IMPL__.init(errorMsg);
   1.450 +    this.lockType = lockType;
   1.451 +    this.retryCount = retryCount;
   1.452 +  },
   1.453 +};
   1.454 +
   1.455 +function RILContentHelper() {
   1.456 +  this.updateDebugFlag();
   1.457 +
   1.458 +  this.numClients = gNumRadioInterfaces;
   1.459 +  if (DEBUG) debug("Number of clients: " + this.numClients);
   1.460 +
   1.461 +  this.rilContexts = [];
   1.462 +  this.voicemailInfos = [];
   1.463 +  this.voicemailStatuses = [];
   1.464 +  for (let clientId = 0; clientId < this.numClients; clientId++) {
   1.465 +    this.rilContexts[clientId] = {
   1.466 +      cardState:            RIL.GECKO_CARDSTATE_UNKNOWN,
   1.467 +      networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
   1.468 +      radioState:           null,
   1.469 +      iccInfo:              null,
   1.470 +      voiceConnectionInfo:  new MobileConnectionInfo(),
   1.471 +      dataConnectionInfo:   new MobileConnectionInfo()
   1.472 +    };
   1.473 +
   1.474 +    this.voicemailInfos[clientId] = new VoicemailInfo();
   1.475 +  }
   1.476 +
   1.477 +  this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
   1.478 +
   1.479 +  this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
   1.480 +  this._windowsMap = [];
   1.481 +  this._selectingNetworks = [];
   1.482 +  this._mobileConnectionListeners = [];
   1.483 +  this._cellBroadcastListeners = [];
   1.484 +  this._voicemailListeners = [];
   1.485 +  this._iccListeners = [];
   1.486 +
   1.487 +  Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
   1.488 +
   1.489 +  Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
   1.490 +  Services.prefs.addObserver(kPrefVoicemailDefaultServiceId, this, false);
   1.491 +}
   1.492 +
   1.493 +RILContentHelper.prototype = {
   1.494 +  __proto__: DOMRequestIpcHelper.prototype,
   1.495 +
   1.496 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
   1.497 +                                         Ci.nsICellBroadcastProvider,
   1.498 +                                         Ci.nsIVoicemailProvider,
   1.499 +                                         Ci.nsIIccProvider,
   1.500 +                                         Ci.nsIObserver,
   1.501 +                                         Ci.nsISupportsWeakReference,
   1.502 +                                         Ci.nsIObserver]),
   1.503 +  classID:   RILCONTENTHELPER_CID,
   1.504 +  classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
   1.505 +                                    classDescription: "RILContentHelper",
   1.506 +                                    interfaces: [Ci.nsIMobileConnectionProvider,
   1.507 +                                                 Ci.nsICellBroadcastProvider,
   1.508 +                                                 Ci.nsIVoicemailProvider,
   1.509 +                                                 Ci.nsIIccProvider]}),
   1.510 +
   1.511 +  updateDebugFlag: function() {
   1.512 +    try {
   1.513 +      DEBUG = RIL.DEBUG_CONTENT_HELPER ||
   1.514 +              Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
   1.515 +    } catch (e) {}
   1.516 +  },
   1.517 +
   1.518 +  // An utility function to copy objects.
   1.519 +  updateInfo: function(srcInfo, destInfo) {
   1.520 +    for (let key in srcInfo) {
   1.521 +      destInfo[key] = srcInfo[key];
   1.522 +    }
   1.523 +  },
   1.524 +
   1.525 +  updateConnectionInfo: function(srcInfo, destInfo) {
   1.526 +    for (let key in srcInfo) {
   1.527 +      if ((key != "network") && (key != "cell")) {
   1.528 +        destInfo[key] = srcInfo[key];
   1.529 +      }
   1.530 +    }
   1.531 +
   1.532 +    let srcCell = srcInfo.cell;
   1.533 +    if (!srcCell) {
   1.534 +      destInfo.cell = null;
   1.535 +    } else {
   1.536 +      let cell = destInfo.cell;
   1.537 +      if (!cell) {
   1.538 +        cell = destInfo.cell = new MobileCellInfo();
   1.539 +      }
   1.540 +
   1.541 +      this.updateInfo(srcCell, cell);
   1.542 +    }
   1.543 +
   1.544 +    let srcNetwork = srcInfo.network;
   1.545 +    if (!srcNetwork) {
   1.546 +      destInfo.network= null;
   1.547 +      return;
   1.548 +    }
   1.549 +
   1.550 +    let network = destInfo.network;
   1.551 +    if (!network) {
   1.552 +      network = destInfo.network = new MobileNetworkInfo();
   1.553 +    }
   1.554 +
   1.555 +    this.updateInfo(srcNetwork, network);
   1.556 +  },
   1.557 +
   1.558 +  /**
   1.559 +   * We need to consider below cases when update iccInfo:
   1.560 +   * 1. Should clear iccInfo to null if there is no card detected.
   1.561 +   * 2. Need to create corresponding object based on iccType.
   1.562 +   */
   1.563 +  updateIccInfo: function(clientId, newInfo) {
   1.564 +    let rilContext = this.rilContexts[clientId];
   1.565 +
   1.566 +    // Card is not detected, clear iccInfo to null.
   1.567 +    if (!newInfo || !newInfo.iccType || !newInfo.iccid) {
   1.568 +      if (rilContext.iccInfo) {
   1.569 +        rilContext.iccInfo = null;
   1.570 +        this._deliverEvent(clientId,
   1.571 +                           "_mobileConnectionListeners",
   1.572 +                           "notifyIccChanged",
   1.573 +                           null);
   1.574 +      }
   1.575 +      return;
   1.576 +    }
   1.577 +
   1.578 +    // If iccInfo is null, new corresponding object based on iccType.
   1.579 +    if (!rilContext.iccInfo) {
   1.580 +      if (newInfo.iccType === "ruim" || newInfo.iccType === "csim") {
   1.581 +        rilContext.iccInfo = new CdmaIccInfo();
   1.582 +      } else {
   1.583 +        rilContext.iccInfo = new GsmIccInfo();
   1.584 +      }
   1.585 +    }
   1.586 +    let changed = (rilContext.iccInfo.iccid != newInfo.iccid) ?
   1.587 +      true : false;
   1.588 +
   1.589 +    this.updateInfo(newInfo, rilContext.iccInfo);
   1.590 +
   1.591 +    // Deliver event after info is updated.
   1.592 +    if (changed) {
   1.593 +      this._deliverEvent(clientId,
   1.594 +                         "_mobileConnectionListeners",
   1.595 +                         "notifyIccChanged",
   1.596 +                         null);
   1.597 +    }
   1.598 +  },
   1.599 +
   1.600 +  _windowsMap: null,
   1.601 +
   1.602 +  rilContexts: null,
   1.603 +
   1.604 +  getRilContext: function(clientId) {
   1.605 +    // Update ril contexts by sending IPC message to chrome only when the first
   1.606 +    // time we require it. The information will be updated by following info
   1.607 +    // changed messages.
   1.608 +    this.getRilContext = function getRilContext(clientId) {
   1.609 +      return this.rilContexts[clientId];
   1.610 +    };
   1.611 +
   1.612 +    for (let cId = 0; cId < this.numClients; cId++) {
   1.613 +      let rilContext =
   1.614 +        cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: cId})[0];
   1.615 +      if (!rilContext) {
   1.616 +        if (DEBUG) debug("Received null rilContext from chrome process.");
   1.617 +        continue;
   1.618 +      }
   1.619 +      this.rilContexts[cId].cardState = rilContext.cardState;
   1.620 +      this.rilContexts[cId].networkSelectionMode = rilContext.networkSelectionMode;
   1.621 +      this.rilContexts[cId].radioState = rilContext.detailedRadioState;
   1.622 +      this.updateIccInfo(cId, rilContext.iccInfo);
   1.623 +      this.updateConnectionInfo(rilContext.voice, this.rilContexts[cId].voiceConnectionInfo);
   1.624 +      this.updateConnectionInfo(rilContext.data, this.rilContexts[cId].dataConnectionInfo);
   1.625 +    }
   1.626 +
   1.627 +    return this.rilContexts[clientId];
   1.628 +  },
   1.629 +
   1.630 +  /**
   1.631 +   * nsIIccProvider
   1.632 +   */
   1.633 +
   1.634 +  getIccInfo: function(clientId) {
   1.635 +    let context = this.getRilContext(clientId);
   1.636 +    return context && context.iccInfo;
   1.637 +  },
   1.638 +
   1.639 +  getCardState: function(clientId) {
   1.640 +    let context = this.getRilContext(clientId);
   1.641 +    return context && context.cardState;
   1.642 +  },
   1.643 +
   1.644 +  matchMvno: function(clientId, window, mvnoType, mvnoData) {
   1.645 +    if (window == null) {
   1.646 +      throw Components.Exception("Can't get window object",
   1.647 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.648 +    }
   1.649 +
   1.650 +    let request = Services.DOMRequest.createRequest(window);
   1.651 +    let requestId = this.getRequestId(request);
   1.652 +
   1.653 +    cpmm.sendAsyncMessage("RIL:MatchMvno", {
   1.654 +      clientId: clientId,
   1.655 +      data: {
   1.656 +        requestId: requestId,
   1.657 +        mvnoType: mvnoType,
   1.658 +        mvnoData: mvnoData
   1.659 +      }
   1.660 +    });
   1.661 +    return request;
   1.662 +  },
   1.663 +
   1.664 +  /**
   1.665 +   * nsIMobileConnectionProvider
   1.666 +   */
   1.667 +
   1.668 +  getLastKnownNetwork: function(clientId) {
   1.669 +    return cpmm.sendSyncMessage("RIL:GetLastKnownNetwork", {
   1.670 +      clientId: clientId
   1.671 +    })[0];
   1.672 +  },
   1.673 +
   1.674 +  getLastKnownHomeNetwork: function(clientId) {
   1.675 +    return cpmm.sendSyncMessage("RIL:GetLastKnownHomeNetwork", {
   1.676 +      clientId: clientId
   1.677 +    })[0];
   1.678 +  },
   1.679 +
   1.680 +  getVoiceConnectionInfo: function(clientId) {
   1.681 +    let context = this.getRilContext(clientId);
   1.682 +    return context && context.voiceConnectionInfo;
   1.683 +  },
   1.684 +
   1.685 +  getDataConnectionInfo: function(clientId) {
   1.686 +    let context = this.getRilContext(clientId);
   1.687 +    return context && context.dataConnectionInfo;
   1.688 +  },
   1.689 +
   1.690 +  getIccId: function(clientId) {
   1.691 +    let context = this.getRilContext(clientId);
   1.692 +    return context && context.iccInfo && context.iccInfo.iccid;
   1.693 +  },
   1.694 +
   1.695 +  getNetworkSelectionMode: function(clientId) {
   1.696 +    let context = this.getRilContext(clientId);
   1.697 +    return context && context.networkSelectionMode;
   1.698 +  },
   1.699 +
   1.700 +  getRadioState: function(clientId) {
   1.701 +    let context = this.getRilContext(clientId);
   1.702 +    return context && context.radioState;
   1.703 +  },
   1.704 +
   1.705 +  getSupportedNetworkTypes: function(clientId) {
   1.706 +    return cpmm.sendSyncMessage("RIL:GetSupportedNetworkTypes", {
   1.707 +      clientId: clientId
   1.708 +    })[0];
   1.709 +  },
   1.710 +
   1.711 +  /**
   1.712 +   * The networks that are currently trying to be selected (or "automatic").
   1.713 +   * This helps ensure that only one network per client is selected at a time.
   1.714 +   */
   1.715 +  _selectingNetworks: null,
   1.716 +
   1.717 +  getNetworks: function(clientId, window) {
   1.718 +    if (window == null) {
   1.719 +      throw Components.Exception("Can't get window object",
   1.720 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.721 +    }
   1.722 +
   1.723 +    let request = Services.DOMRequest.createRequest(window);
   1.724 +    let requestId = this.getRequestId(request);
   1.725 +
   1.726 +    cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", {
   1.727 +      clientId: clientId,
   1.728 +      data: {
   1.729 +        requestId: requestId
   1.730 +      }
   1.731 +    });
   1.732 +    return request;
   1.733 +  },
   1.734 +
   1.735 +  selectNetwork: function(clientId, window, network) {
   1.736 +    if (window == null) {
   1.737 +      throw Components.Exception("Can't get window object",
   1.738 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.739 +    }
   1.740 +
   1.741 +    if (this._selectingNetworks[clientId]) {
   1.742 +      throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
   1.743 +    }
   1.744 +
   1.745 +    if (!network) {
   1.746 +      throw new Error("Invalid network provided: " + network);
   1.747 +    }
   1.748 +
   1.749 +    if (isNaN(parseInt(network.mnc, 10))) {
   1.750 +      throw new Error("Invalid network MNC: " + network.mnc);
   1.751 +    }
   1.752 +
   1.753 +    if (isNaN(parseInt(network.mcc, 10))) {
   1.754 +      throw new Error("Invalid network MCC: " + network.mcc);
   1.755 +    }
   1.756 +
   1.757 +    let request = Services.DOMRequest.createRequest(window);
   1.758 +    let requestId = this.getRequestId(request);
   1.759 +
   1.760 +    if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
   1.761 +        this.rilContexts[clientId].voiceConnectionInfo.network === network) {
   1.762 +
   1.763 +      // Already manually selected this network, so schedule
   1.764 +      // onsuccess to be fired on the next tick
   1.765 +      this.dispatchFireRequestSuccess(requestId, null);
   1.766 +      return request;
   1.767 +    }
   1.768 +
   1.769 +    this._selectingNetworks[clientId] = network;
   1.770 +
   1.771 +    cpmm.sendAsyncMessage("RIL:SelectNetwork", {
   1.772 +      clientId: clientId,
   1.773 +      data: {
   1.774 +        requestId: requestId,
   1.775 +        mnc: network.mnc,
   1.776 +        mcc: network.mcc
   1.777 +      }
   1.778 +    });
   1.779 +
   1.780 +    return request;
   1.781 +  },
   1.782 +
   1.783 +  selectNetworkAutomatically: function(clientId, window) {
   1.784 +
   1.785 +    if (window == null) {
   1.786 +      throw Components.Exception("Can't get window object",
   1.787 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.788 +    }
   1.789 +
   1.790 +    if (this._selectingNetworks[clientId]) {
   1.791 +      throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
   1.792 +    }
   1.793 +
   1.794 +    let request = Services.DOMRequest.createRequest(window);
   1.795 +    let requestId = this.getRequestId(request);
   1.796 +
   1.797 +    if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
   1.798 +      // Already using automatic selection mode, so schedule
   1.799 +      // onsuccess to be be fired on the next tick
   1.800 +      this.dispatchFireRequestSuccess(requestId, null);
   1.801 +      return request;
   1.802 +    }
   1.803 +
   1.804 +    this._selectingNetworks[clientId] = "automatic";
   1.805 +    cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", {
   1.806 +      clientId: clientId,
   1.807 +      data: {
   1.808 +        requestId: requestId
   1.809 +      }
   1.810 +    });
   1.811 +    return request;
   1.812 +  },
   1.813 +
   1.814 +  setPreferredNetworkType: function(clientId, window, type) {
   1.815 +    if (window == null) {
   1.816 +      throw Components.Exception("Can't get window object",
   1.817 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.818 +    }
   1.819 +
   1.820 +    let request = Services.DOMRequest.createRequest(window);
   1.821 +    let requestId = this.getRequestId(request);
   1.822 +
   1.823 +    cpmm.sendAsyncMessage("RIL:SetPreferredNetworkType", {
   1.824 +      clientId: clientId,
   1.825 +      data: {
   1.826 +        requestId: requestId,
   1.827 +        type: type
   1.828 +      }
   1.829 +    });
   1.830 +    return request;
   1.831 +  },
   1.832 +
   1.833 +  getPreferredNetworkType: function(clientId, window) {
   1.834 +    if (window == null) {
   1.835 +      throw Components.Exception("Can't get window object",
   1.836 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.837 +    }
   1.838 +
   1.839 +    let request = Services.DOMRequest.createRequest(window);
   1.840 +    let requestId = this.getRequestId(request);
   1.841 +
   1.842 +    cpmm.sendAsyncMessage("RIL:GetPreferredNetworkType", {
   1.843 +      clientId: clientId,
   1.844 +      data: {
   1.845 +        requestId: requestId
   1.846 +      }
   1.847 +    });
   1.848 +    return request;
   1.849 +  },
   1.850 +
   1.851 +  setRoamingPreference: function(clientId, window, mode) {
   1.852 +    if (window == null) {
   1.853 +      throw Components.Exception("Can't get window object",
   1.854 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.855 +    }
   1.856 +
   1.857 +    let request = Services.DOMRequest.createRequest(window);
   1.858 +    let requestId = this.getRequestId(request);
   1.859 +
   1.860 +    if (!mode) {
   1.861 +      this.dispatchFireRequestError(requestId,
   1.862 +                                    RIL.GECKO_ERROR_INVALID_PARAMETER);
   1.863 +      return request;
   1.864 +    }
   1.865 +
   1.866 +    cpmm.sendAsyncMessage("RIL:SetRoamingPreference", {
   1.867 +      clientId: clientId,
   1.868 +      data: {
   1.869 +        requestId: requestId,
   1.870 +        mode: mode
   1.871 +      }
   1.872 +    });
   1.873 +    return request;
   1.874 +  },
   1.875 +
   1.876 +  getRoamingPreference: function(clientId, window) {
   1.877 +    if (window == null) {
   1.878 +      throw Components.Exception("Can't get window object",
   1.879 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.880 +    }
   1.881 +
   1.882 +    let request = Services.DOMRequest.createRequest(window);
   1.883 +    let requestId = this.getRequestId(request);
   1.884 +
   1.885 +    cpmm.sendAsyncMessage("RIL:GetRoamingPreference", {
   1.886 +      clientId: clientId,
   1.887 +      data: {
   1.888 +        requestId: requestId
   1.889 +      }
   1.890 +    });
   1.891 +    return request;
   1.892 +  },
   1.893 +
   1.894 +  setVoicePrivacyMode: function(clientId, window, enabled) {
   1.895 +    if (window == null) {
   1.896 +      throw Components.Exception("Can't get window object",
   1.897 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.898 +    }
   1.899 +
   1.900 +    let request = Services.DOMRequest.createRequest(window);
   1.901 +    let requestId = this.getRequestId(request);
   1.902 +
   1.903 +    cpmm.sendAsyncMessage("RIL:SetVoicePrivacyMode", {
   1.904 +      clientId: clientId,
   1.905 +      data: {
   1.906 +        requestId: requestId,
   1.907 +        enabled: enabled
   1.908 +      }
   1.909 +    });
   1.910 +    return request;
   1.911 +  },
   1.912 +
   1.913 +  getVoicePrivacyMode: function(clientId, window) {
   1.914 +    if (window == null) {
   1.915 +      throw Components.Exception("Can't get window object",
   1.916 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.917 +    }
   1.918 +
   1.919 +    let request = Services.DOMRequest.createRequest(window);
   1.920 +    let requestId = this.getRequestId(request);
   1.921 +
   1.922 +    cpmm.sendAsyncMessage("RIL:GetVoicePrivacyMode", {
   1.923 +      clientId: clientId,
   1.924 +      data: {
   1.925 +        requestId: requestId
   1.926 +      }
   1.927 +    });
   1.928 +    return request;
   1.929 +  },
   1.930 +
   1.931 +  getCardLockState: function(clientId, window, lockType) {
   1.932 +    if (window == null) {
   1.933 +      throw Components.Exception("Can't get window object",
   1.934 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.935 +    }
   1.936 +    let request = Services.DOMRequest.createRequest(window);
   1.937 +    let requestId = this.getRequestId(request);
   1.938 +    this._windowsMap[requestId] = window;
   1.939 +
   1.940 +    cpmm.sendAsyncMessage("RIL:GetCardLockState", {
   1.941 +      clientId: clientId,
   1.942 +      data: {
   1.943 +        lockType: lockType,
   1.944 +        requestId: requestId
   1.945 +      }
   1.946 +    });
   1.947 +    return request;
   1.948 +  },
   1.949 +
   1.950 +  unlockCardLock: function(clientId, window, info) {
   1.951 +    if (window == null) {
   1.952 +      throw Components.Exception("Can't get window object",
   1.953 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.954 +    }
   1.955 +    let request = Services.DOMRequest.createRequest(window);
   1.956 +    info.requestId = this.getRequestId(request);
   1.957 +    this._windowsMap[info.requestId] = window;
   1.958 +
   1.959 +    cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
   1.960 +      clientId: clientId,
   1.961 +      data: info
   1.962 +    });
   1.963 +    return request;
   1.964 +  },
   1.965 +
   1.966 +  setCardLock: function(clientId, window, info) {
   1.967 +    if (window == null) {
   1.968 +      throw Components.Exception("Can't get window object",
   1.969 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.970 +    }
   1.971 +    let request = Services.DOMRequest.createRequest(window);
   1.972 +    info.requestId = this.getRequestId(request);
   1.973 +    this._windowsMap[info.requestId] = window;
   1.974 +
   1.975 +    cpmm.sendAsyncMessage("RIL:SetCardLock", {
   1.976 +      clientId: clientId,
   1.977 +      data: info
   1.978 +    });
   1.979 +    return request;
   1.980 +  },
   1.981 +
   1.982 +  getCardLockRetryCount: function(clientId, window, lockType) {
   1.983 +    if (window == null) {
   1.984 +      throw Components.Exception("Can't get window object",
   1.985 +                                  Cr.NS_ERROR_UNEXPECTED);
   1.986 +    }
   1.987 +    let request = Services.DOMRequest.createRequest(window);
   1.988 +    let requestId = this.getRequestId(request);
   1.989 +    cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
   1.990 +      clientId: clientId,
   1.991 +      data: {
   1.992 +        lockType: lockType,
   1.993 +        requestId: requestId
   1.994 +      }
   1.995 +    });
   1.996 +    return request;
   1.997 +  },
   1.998 +
   1.999 +  sendMMI: function(clientId, window, mmi) {
  1.1000 +    if (DEBUG) debug("Sending MMI " + mmi);
  1.1001 +    if (!window) {
  1.1002 +      throw Components.Exception("Can't get window object",
  1.1003 +                                 Cr.NS_ERROR_UNEXPECTED);
  1.1004 +    }
  1.1005 +    let request = Services.DOMRequest.createRequest(window);
  1.1006 +    let requestId = this.getRequestId(request);
  1.1007 +    // We need to save the global window to get the proper MMIError
  1.1008 +    // constructor once we get the reply from the parent process.
  1.1009 +    this._windowsMap[requestId] = window;
  1.1010 +
  1.1011 +    cpmm.sendAsyncMessage("RIL:SendMMI", {
  1.1012 +      clientId: clientId,
  1.1013 +      data: {
  1.1014 +        mmi: mmi,
  1.1015 +        requestId: requestId
  1.1016 +      }
  1.1017 +    });
  1.1018 +    return request;
  1.1019 +  },
  1.1020 +
  1.1021 +  cancelMMI: function(clientId, window) {
  1.1022 +    if (DEBUG) debug("Cancel MMI");
  1.1023 +    if (!window) {
  1.1024 +      throw Components.Exception("Can't get window object",
  1.1025 +                                 Cr.NS_ERROR_UNEXPECTED);
  1.1026 +    }
  1.1027 +    let request = Services.DOMRequest.createRequest(window);
  1.1028 +    let requestId = this.getRequestId(request);
  1.1029 +    cpmm.sendAsyncMessage("RIL:CancelMMI", {
  1.1030 +      clientId: clientId,
  1.1031 +      data: {
  1.1032 +        requestId: requestId
  1.1033 +      }
  1.1034 +    });
  1.1035 +    return request;
  1.1036 +  },
  1.1037 +
  1.1038 +  sendStkResponse: function(clientId, window, command, response) {
  1.1039 +    if (window == null) {
  1.1040 +      throw Components.Exception("Can't get window object",
  1.1041 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1042 +    }
  1.1043 +    response.command = command;
  1.1044 +    cpmm.sendAsyncMessage("RIL:SendStkResponse", {
  1.1045 +      clientId: clientId,
  1.1046 +      data: response
  1.1047 +    });
  1.1048 +  },
  1.1049 +
  1.1050 +  sendStkMenuSelection: function(clientId, window, itemIdentifier,
  1.1051 +                                 helpRequested) {
  1.1052 +    if (window == null) {
  1.1053 +      throw Components.Exception("Can't get window object",
  1.1054 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1055 +    }
  1.1056 +    cpmm.sendAsyncMessage("RIL:SendStkMenuSelection", {
  1.1057 +      clientId: clientId,
  1.1058 +      data: {
  1.1059 +        itemIdentifier: itemIdentifier,
  1.1060 +        helpRequested: helpRequested
  1.1061 +      }
  1.1062 +    });
  1.1063 +  },
  1.1064 +
  1.1065 +  sendStkTimerExpiration: function(clientId, window, timer) {
  1.1066 +    if (window == null) {
  1.1067 +      throw Components.Exception("Can't get window object",
  1.1068 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1069 +    }
  1.1070 +    cpmm.sendAsyncMessage("RIL:SendStkTimerExpiration", {
  1.1071 +      clientId: clientId,
  1.1072 +      data: {
  1.1073 +        timer: timer
  1.1074 +      }
  1.1075 +    });
  1.1076 +  },
  1.1077 +
  1.1078 +  sendStkEventDownload: function(clientId, window, event) {
  1.1079 +    if (window == null) {
  1.1080 +      throw Components.Exception("Can't get window object",
  1.1081 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1082 +    }
  1.1083 +    cpmm.sendAsyncMessage("RIL:SendStkEventDownload", {
  1.1084 +      clientId: clientId,
  1.1085 +      data: {
  1.1086 +        event: event
  1.1087 +      }
  1.1088 +    });
  1.1089 +  },
  1.1090 +
  1.1091 +  iccOpenChannel: function(clientId, window, aid) {
  1.1092 +    if (window == null) {
  1.1093 +      throw Components.Exception("Can't get window object",
  1.1094 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1095 +    }
  1.1096 +
  1.1097 +    let request = Services.DOMRequest.createRequest(window);
  1.1098 +    let requestId = this.getRequestId(request);
  1.1099 +
  1.1100 +    cpmm.sendAsyncMessage("RIL:IccOpenChannel", {
  1.1101 +      clientId: clientId,
  1.1102 +      data: {
  1.1103 +        requestId: requestId,
  1.1104 +        aid: aid
  1.1105 +      }
  1.1106 +    });
  1.1107 +    return request;
  1.1108 +  },
  1.1109 +
  1.1110 +  iccExchangeAPDU: function(clientId, window, channel, apdu) {
  1.1111 +    if (window == null) {
  1.1112 +      throw Components.Exception("Can't get window object",
  1.1113 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1114 +    }
  1.1115 +
  1.1116 +    let request = Services.DOMRequest.createRequest(window);
  1.1117 +    let requestId = this.getRequestId(request);
  1.1118 +
  1.1119 +    //Potentially you need serialization here and can't pass the jsval through
  1.1120 +    cpmm.sendAsyncMessage("RIL:IccExchangeAPDU", {
  1.1121 +      clientId: clientId,
  1.1122 +      data: {
  1.1123 +        requestId: requestId,
  1.1124 +        channel: channel,
  1.1125 +        apdu: apdu
  1.1126 +      }
  1.1127 +    });
  1.1128 +    return request;
  1.1129 +  },
  1.1130 +
  1.1131 +  iccCloseChannel: function(clientId, window, channel) {
  1.1132 +    if (window == null) {
  1.1133 +      throw Components.Exception("Can't get window object",
  1.1134 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1135 +    }
  1.1136 +
  1.1137 +    let request = Services.DOMRequest.createRequest(window);
  1.1138 +    let requestId = this.getRequestId(request);
  1.1139 +
  1.1140 +    cpmm.sendAsyncMessage("RIL:IccCloseChannel", {
  1.1141 +      clientId: clientId,
  1.1142 +      data: {
  1.1143 +        requestId: requestId,
  1.1144 +        channel: channel
  1.1145 +      }
  1.1146 +    });
  1.1147 +    return request;
  1.1148 +  },
  1.1149 +
  1.1150 +  readContacts: function(clientId, window, contactType) {
  1.1151 +    if (window == null) {
  1.1152 +      throw Components.Exception("Can't get window object",
  1.1153 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1154 +    }
  1.1155 +
  1.1156 +    let request = Services.DOMRequest.createRequest(window);
  1.1157 +    let requestId = this.getRequestId(request);
  1.1158 +    this._windowsMap[requestId] = window;
  1.1159 +
  1.1160 +    cpmm.sendAsyncMessage("RIL:ReadIccContacts", {
  1.1161 +      clientId: clientId,
  1.1162 +      data: {
  1.1163 +        requestId: requestId,
  1.1164 +        contactType: contactType
  1.1165 +      }
  1.1166 +    });
  1.1167 +    return request;
  1.1168 +  },
  1.1169 +
  1.1170 +  updateContact: function(clientId, window, contactType, contact, pin2) {
  1.1171 +    if (window == null) {
  1.1172 +      throw Components.Exception("Can't get window object",
  1.1173 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1174 +    }
  1.1175 +
  1.1176 +    let request = Services.DOMRequest.createRequest(window);
  1.1177 +    let requestId = this.getRequestId(request);
  1.1178 +    this._windowsMap[requestId] = window;
  1.1179 +
  1.1180 +    // Parsing nsDOMContact to Icc Contact format
  1.1181 +    let iccContact = {};
  1.1182 +
  1.1183 +    if (Array.isArray(contact.name) && contact.name[0]) {
  1.1184 +      iccContact.alphaId = contact.name[0];
  1.1185 +    }
  1.1186 +
  1.1187 +    if (Array.isArray(contact.tel)) {
  1.1188 +      iccContact.number = contact.tel[0] && contact.tel[0].value;
  1.1189 +      let telArray = contact.tel.slice(1);
  1.1190 +      let length = telArray.length;
  1.1191 +      if (length > 0) {
  1.1192 +        iccContact.anr = [];
  1.1193 +      }
  1.1194 +      for (let i = 0; i < telArray.length; i++) {
  1.1195 +        iccContact.anr.push(telArray[i].value);
  1.1196 +      }
  1.1197 +    }
  1.1198 +
  1.1199 +    if (Array.isArray(contact.email) && contact.email[0]) {
  1.1200 +      iccContact.email = contact.email[0].value;
  1.1201 +    }
  1.1202 +
  1.1203 +    iccContact.contactId = contact.id;
  1.1204 +
  1.1205 +    cpmm.sendAsyncMessage("RIL:UpdateIccContact", {
  1.1206 +      clientId: clientId,
  1.1207 +      data: {
  1.1208 +        requestId: requestId,
  1.1209 +        contactType: contactType,
  1.1210 +        contact: iccContact,
  1.1211 +        pin2: pin2
  1.1212 +      }
  1.1213 +    });
  1.1214 +
  1.1215 +    return request;
  1.1216 +  },
  1.1217 +
  1.1218 +  getCallForwardingOption: function(clientId, window, reason) {
  1.1219 +    if (window == null) {
  1.1220 +      throw Components.Exception("Can't get window object",
  1.1221 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1222 +    }
  1.1223 +    let request = Services.DOMRequest.createRequest(window);
  1.1224 +    let requestId = this.getRequestId(request);
  1.1225 +
  1.1226 +    if (!this._isValidCFReason(reason)){
  1.1227 +      this.dispatchFireRequestError(requestId,
  1.1228 +                                    RIL.GECKO_ERROR_INVALID_PARAMETER);
  1.1229 +      return request;
  1.1230 +    }
  1.1231 +
  1.1232 +    cpmm.sendAsyncMessage("RIL:GetCallForwardingOptions", {
  1.1233 +      clientId: clientId,
  1.1234 +      data: {
  1.1235 +        requestId: requestId,
  1.1236 +        reason: reason
  1.1237 +      }
  1.1238 +    });
  1.1239 +
  1.1240 +    return request;
  1.1241 +  },
  1.1242 +
  1.1243 +  setCallForwardingOption: function(clientId, window, cfInfo) {
  1.1244 +    if (window == null) {
  1.1245 +      throw Components.Exception("Can't get window object",
  1.1246 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1247 +    }
  1.1248 +    let request = Services.DOMRequest.createRequest(window);
  1.1249 +    let requestId = this.getRequestId(request);
  1.1250 +
  1.1251 +    if (!cfInfo ||
  1.1252 +        !this._isValidCFReason(cfInfo.reason) ||
  1.1253 +        !this._isValidCFAction(cfInfo.action)){
  1.1254 +      this.dispatchFireRequestError(requestId,
  1.1255 +                                    RIL.GECKO_ERROR_INVALID_PARAMETER);
  1.1256 +      return request;
  1.1257 +    }
  1.1258 +
  1.1259 +    cpmm.sendAsyncMessage("RIL:SetCallForwardingOptions", {
  1.1260 +      clientId: clientId,
  1.1261 +      data: {
  1.1262 +        requestId: requestId,
  1.1263 +        active: cfInfo.active,
  1.1264 +        action: cfInfo.action,
  1.1265 +        reason: cfInfo.reason,
  1.1266 +        number: cfInfo.number,
  1.1267 +        timeSeconds: cfInfo.timeSeconds
  1.1268 +      }
  1.1269 +    });
  1.1270 +
  1.1271 +    return request;
  1.1272 +  },
  1.1273 +
  1.1274 +  getCallBarringOption: function(clientId, window, option) {
  1.1275 +    if (window == null) {
  1.1276 +      throw Components.Exception("Can't get window object",
  1.1277 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1278 +    }
  1.1279 +    let request = Services.DOMRequest.createRequest(window);
  1.1280 +    let requestId = this.getRequestId(request);
  1.1281 +
  1.1282 +    if (DEBUG) debug("getCallBarringOption: " + JSON.stringify(option));
  1.1283 +    if (!this._isValidCallBarringOptions(option)) {
  1.1284 +      this.dispatchFireRequestError(requestId,
  1.1285 +                                    RIL.GECKO_ERROR_INVALID_PARAMETER);
  1.1286 +      return request;
  1.1287 +    }
  1.1288 +
  1.1289 +    cpmm.sendAsyncMessage("RIL:GetCallBarringOptions", {
  1.1290 +      clientId: clientId,
  1.1291 +      data: {
  1.1292 +        requestId: requestId,
  1.1293 +        program: option.program,
  1.1294 +        password: option.password,
  1.1295 +        serviceClass: option.serviceClass
  1.1296 +      }
  1.1297 +    });
  1.1298 +    return request;
  1.1299 +  },
  1.1300 +
  1.1301 +  setCallBarringOption: function(clientId, window, option) {
  1.1302 +    if (window == null) {
  1.1303 +      throw Components.Exception("Can't get window object",
  1.1304 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1305 +    }
  1.1306 +    let request = Services.DOMRequest.createRequest(window);
  1.1307 +    let requestId = this.getRequestId(request);
  1.1308 +
  1.1309 +    if (DEBUG) debug("setCallBarringOption: " + JSON.stringify(option));
  1.1310 +    if (!this._isValidCallBarringOptions(option, true)) {
  1.1311 +      this.dispatchFireRequestError(requestId,
  1.1312 +                                    RIL.GECKO_ERROR_INVALID_PARAMETER);
  1.1313 +      return request;
  1.1314 +    }
  1.1315 +
  1.1316 +    cpmm.sendAsyncMessage("RIL:SetCallBarringOptions", {
  1.1317 +      clientId: clientId,
  1.1318 +      data: {
  1.1319 +        requestId: requestId,
  1.1320 +        program: option.program,
  1.1321 +        enabled: option.enabled,
  1.1322 +        password: option.password,
  1.1323 +        serviceClass: option.serviceClass
  1.1324 +      }
  1.1325 +    });
  1.1326 +    return request;
  1.1327 +  },
  1.1328 +
  1.1329 +  changeCallBarringPassword: function(clientId, window, info) {
  1.1330 +    if (window == null) {
  1.1331 +      throw Components.Exception("Can't get window object",
  1.1332 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1333 +    }
  1.1334 +    let request = Services.DOMRequest.createRequest(window);
  1.1335 +    let requestId = this.getRequestId(request);
  1.1336 +
  1.1337 +    // Checking valid PIN for supplementary services. See TS.22.004 clause 5.2.
  1.1338 +    if (info.pin == null || !info.pin.match(/^\d{4}$/) ||
  1.1339 +        info.newPin == null || !info.newPin.match(/^\d{4}$/)) {
  1.1340 +      this.dispatchFireRequestError(requestId, "InvalidPassword");
  1.1341 +      return request;
  1.1342 +    }
  1.1343 +
  1.1344 +    if (DEBUG) debug("changeCallBarringPassword: " + JSON.stringify(info));
  1.1345 +    info.requestId = requestId;
  1.1346 +    cpmm.sendAsyncMessage("RIL:ChangeCallBarringPassword", {
  1.1347 +      clientId: clientId,
  1.1348 +      data: info
  1.1349 +    });
  1.1350 +
  1.1351 +    return request;
  1.1352 +  },
  1.1353 +
  1.1354 +  getCallWaitingOption: function(clientId, window) {
  1.1355 +    if (window == null) {
  1.1356 +      throw Components.Exception("Can't get window object",
  1.1357 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1358 +    }
  1.1359 +    let request = Services.DOMRequest.createRequest(window);
  1.1360 +    let requestId = this.getRequestId(request);
  1.1361 +
  1.1362 +    cpmm.sendAsyncMessage("RIL:GetCallWaitingOptions", {
  1.1363 +      clientId: clientId,
  1.1364 +      data: {
  1.1365 +        requestId: requestId
  1.1366 +      }
  1.1367 +    });
  1.1368 +
  1.1369 +    return request;
  1.1370 +  },
  1.1371 +
  1.1372 +  setCallWaitingOption: function(clientId, window, enabled) {
  1.1373 +    if (window == null) {
  1.1374 +      throw Components.Exception("Can't get window object",
  1.1375 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1376 +    }
  1.1377 +    let request = Services.DOMRequest.createRequest(window);
  1.1378 +    let requestId = this.getRequestId(request);
  1.1379 +
  1.1380 +    cpmm.sendAsyncMessage("RIL:SetCallWaitingOptions", {
  1.1381 +      clientId: clientId,
  1.1382 +      data: {
  1.1383 +        requestId: requestId,
  1.1384 +        enabled: enabled
  1.1385 +      }
  1.1386 +    });
  1.1387 +
  1.1388 +    return request;
  1.1389 +  },
  1.1390 +
  1.1391 +  getCallingLineIdRestriction: function(clientId, window) {
  1.1392 +    if (window == null) {
  1.1393 +      throw Components.Exception("Can't get window object",
  1.1394 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1395 +    }
  1.1396 +    let request = Services.DOMRequest.createRequest(window);
  1.1397 +    let requestId = this.getRequestId(request);
  1.1398 +
  1.1399 +    cpmm.sendAsyncMessage("RIL:GetCallingLineIdRestriction", {
  1.1400 +      clientId: clientId,
  1.1401 +      data: {
  1.1402 +        requestId: requestId
  1.1403 +      }
  1.1404 +    });
  1.1405 +
  1.1406 +    return request;
  1.1407 +  },
  1.1408 +
  1.1409 +  setCallingLineIdRestriction: function(clientId, window, clirMode) {
  1.1410 +
  1.1411 +    if (window == null) {
  1.1412 +      throw Components.Exception("Can't get window object",
  1.1413 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1414 +    }
  1.1415 +    let request = Services.DOMRequest.createRequest(window);
  1.1416 +    let requestId = this.getRequestId(request);
  1.1417 +
  1.1418 +    cpmm.sendAsyncMessage("RIL:SetCallingLineIdRestriction", {
  1.1419 +      clientId: clientId,
  1.1420 +      data: {
  1.1421 +        requestId: requestId,
  1.1422 +        clirMode: clirMode
  1.1423 +      }
  1.1424 +    });
  1.1425 +
  1.1426 +    return request;
  1.1427 +  },
  1.1428 +
  1.1429 +  exitEmergencyCbMode: function(clientId, window) {
  1.1430 +    if (window == null) {
  1.1431 +      throw Components.Exception("Can't get window object",
  1.1432 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1433 +    }
  1.1434 +    let request = Services.DOMRequest.createRequest(window);
  1.1435 +    let requestId = this.getRequestId(request);
  1.1436 +
  1.1437 +    cpmm.sendAsyncMessage("RIL:ExitEmergencyCbMode", {
  1.1438 +      clientId: clientId,
  1.1439 +      data: {
  1.1440 +        requestId: requestId,
  1.1441 +      }
  1.1442 +    });
  1.1443 +
  1.1444 +    return request;
  1.1445 +  },
  1.1446 +
  1.1447 +  setRadioEnabled: function(clientId, window, enabled) {
  1.1448 +    if (window == null) {
  1.1449 +      throw Components.Exception("Can't get window object",
  1.1450 +                                  Cr.NS_ERROR_UNEXPECTED);
  1.1451 +    }
  1.1452 +    let request = Services.DOMRequest.createRequest(window);
  1.1453 +    let requestId = this.getRequestId(request);
  1.1454 +
  1.1455 +    cpmm.sendAsyncMessage("RIL:SetRadioEnabled", {
  1.1456 +      clientId: clientId,
  1.1457 +      data: {
  1.1458 +        requestId: requestId,
  1.1459 +        enabled: enabled,
  1.1460 +      }
  1.1461 +    });
  1.1462 +
  1.1463 +    return request;
  1.1464 +  },
  1.1465 +
  1.1466 +  _mobileConnectionListeners: null,
  1.1467 +  _cellBroadcastListeners: null,
  1.1468 +  _voicemailListeners: null,
  1.1469 +  _iccListeners: null,
  1.1470 +
  1.1471 +  voicemailInfos: null,
  1.1472 +  voicemailStatuses: null,
  1.1473 +
  1.1474 +  voicemailDefaultServiceId: 0,
  1.1475 +  getVoicemailDefaultServiceId: function() {
  1.1476 +    let id = Services.prefs.getIntPref(kPrefVoicemailDefaultServiceId);
  1.1477 +
  1.1478 +    if (id >= gNumRadioInterfaces || id < 0) {
  1.1479 +      id = 0;
  1.1480 +    }
  1.1481 +
  1.1482 +    return id;
  1.1483 +  },
  1.1484 +
  1.1485 +  getVoicemailInfo: function(clientId) {
  1.1486 +    // Get voicemail infomation by IPC only on first time.
  1.1487 +    this.getVoicemailInfo = function getVoicemailInfo(clientId) {
  1.1488 +      return this.voicemailInfos[clientId];
  1.1489 +    };
  1.1490 +
  1.1491 +    for (let cId = 0; cId < gNumRadioInterfaces; cId++) {
  1.1492 +      let voicemailInfo =
  1.1493 +        cpmm.sendSyncMessage("RIL:GetVoicemailInfo", {clientId: cId})[0];
  1.1494 +      if (voicemailInfo) {
  1.1495 +        this.updateInfo(voicemailInfo, this.voicemailInfos[cId]);
  1.1496 +      }
  1.1497 +    }
  1.1498 +
  1.1499 +    return this.voicemailInfos[clientId];
  1.1500 +  },
  1.1501 +
  1.1502 +  getVoicemailNumber: function(clientId) {
  1.1503 +    return this.getVoicemailInfo(clientId).number;
  1.1504 +  },
  1.1505 +
  1.1506 +  getVoicemailDisplayName: function(clientId) {
  1.1507 +    return this.getVoicemailInfo(clientId).displayName;
  1.1508 +  },
  1.1509 +
  1.1510 +  getVoicemailStatus: function(clientId) {
  1.1511 +    return this.voicemailStatuses[clientId];
  1.1512 +  },
  1.1513 +
  1.1514 +  registerListener: function(listenerType, clientId, listener) {
  1.1515 +    if (!this[listenerType]) {
  1.1516 +      return;
  1.1517 +    }
  1.1518 +    let listeners = this[listenerType][clientId];
  1.1519 +    if (!listeners) {
  1.1520 +      listeners = this[listenerType][clientId] = [];
  1.1521 +    }
  1.1522 +
  1.1523 +    if (listeners.indexOf(listener) != -1) {
  1.1524 +      throw new Error("Already registered this listener!");
  1.1525 +    }
  1.1526 +
  1.1527 +    listeners.push(listener);
  1.1528 +    if (DEBUG) debug("Registered " + listenerType + " listener: " + listener);
  1.1529 +  },
  1.1530 +
  1.1531 +  unregisterListener: function(listenerType, clientId, listener) {
  1.1532 +    if (!this[listenerType]) {
  1.1533 +      return;
  1.1534 +    }
  1.1535 +    let listeners = this[listenerType][clientId];
  1.1536 +    if (!listeners) {
  1.1537 +      return;
  1.1538 +    }
  1.1539 +
  1.1540 +    let index = listeners.indexOf(listener);
  1.1541 +    if (index != -1) {
  1.1542 +      listeners.splice(index, 1);
  1.1543 +      if (DEBUG) debug("Unregistered listener: " + listener);
  1.1544 +    }
  1.1545 +  },
  1.1546 +
  1.1547 +  registerMobileConnectionMsg: function(clientId, listener) {
  1.1548 +    if (DEBUG) debug("Registering for mobile connection related messages");
  1.1549 +    this.registerListener("_mobileConnectionListeners", clientId, listener);
  1.1550 +    cpmm.sendAsyncMessage("RIL:RegisterMobileConnectionMsg");
  1.1551 +  },
  1.1552 +
  1.1553 +  unregisterMobileConnectionMsg: function(clientId, listener) {
  1.1554 +    this.unregisterListener("_mobileConnectionListeners", clientId, listener);
  1.1555 +  },
  1.1556 +
  1.1557 +  registerVoicemailMsg: function(listener) {
  1.1558 +    if (DEBUG) debug("Registering for voicemail-related messages");
  1.1559 +    // To follow the listener registration scheme, we add a dummy clientId 0.
  1.1560 +    // All voicemail events are routed to listener for client id 0.
  1.1561 +    // See |handleVoicemailNotification|.
  1.1562 +    this.registerListener("_voicemailListeners", 0, listener);
  1.1563 +    cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
  1.1564 +  },
  1.1565 +
  1.1566 +  unregisterVoicemailMsg: function(listener) {
  1.1567 +    // To follow the listener unregistration scheme, we add a dummy clientId 0.
  1.1568 +    // All voicemail events are routed to listener for client id 0.
  1.1569 +    // See |handleVoicemailNotification|.
  1.1570 +    this.unregisterListener("_voicemailListeners", 0, listener);
  1.1571 +  },
  1.1572 +
  1.1573 +  registerCellBroadcastMsg: function(listener) {
  1.1574 +    if (DEBUG) debug("Registering for Cell Broadcast related messages");
  1.1575 +    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
  1.1576 +    this.registerListener("_cellBroadcastListeners", 0, listener);
  1.1577 +    cpmm.sendAsyncMessage("RIL:RegisterCellBroadcastMsg");
  1.1578 +  },
  1.1579 +
  1.1580 +  unregisterCellBroadcastMsg: function(listener) {
  1.1581 +    //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
  1.1582 +    this.unregisterListener("_cellBroadcastListeners", 0, listener);
  1.1583 +  },
  1.1584 +
  1.1585 +  registerIccMsg: function(clientId, listener) {
  1.1586 +    if (DEBUG) debug("Registering for ICC related messages");
  1.1587 +    this.registerListener("_iccListeners", clientId, listener);
  1.1588 +    cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
  1.1589 +  },
  1.1590 +
  1.1591 +  unregisterIccMsg: function(clientId, listener) {
  1.1592 +    this.unregisterListener("_iccListeners", clientId, listener);
  1.1593 +  },
  1.1594 +
  1.1595 +  // nsIObserver
  1.1596 +
  1.1597 +  observe: function(subject, topic, data) {
  1.1598 +    switch (topic) {
  1.1599 +      case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
  1.1600 +        if (data == kPrefRilDebuggingEnabled) {
  1.1601 +          this.updateDebugFlag();
  1.1602 +        } else if (data == kPrefVoicemailDefaultServiceId) {
  1.1603 +          this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
  1.1604 +        }
  1.1605 +        break;
  1.1606 +
  1.1607 +      case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
  1.1608 +        this.destroyDOMRequestHelper();
  1.1609 +        Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
  1.1610 +        break;
  1.1611 +    }
  1.1612 +  },
  1.1613 +
  1.1614 +  // nsIMessageListener
  1.1615 +
  1.1616 +  fireRequestSuccess: function(requestId, result) {
  1.1617 +    let request = this.takeRequest(requestId);
  1.1618 +    if (!request) {
  1.1619 +      if (DEBUG) {
  1.1620 +        debug("not firing success for id: " + requestId +
  1.1621 +              ", result: " + JSON.stringify(result));
  1.1622 +      }
  1.1623 +      return;
  1.1624 +    }
  1.1625 +
  1.1626 +    if (DEBUG) {
  1.1627 +      debug("fire request success, id: " + requestId +
  1.1628 +            ", result: " + JSON.stringify(result));
  1.1629 +    }
  1.1630 +    Services.DOMRequest.fireSuccess(request, result);
  1.1631 +  },
  1.1632 +
  1.1633 +  dispatchFireRequestSuccess: function(requestId, result) {
  1.1634 +    let currentThread = Services.tm.currentThread;
  1.1635 +
  1.1636 +    currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result),
  1.1637 +                           Ci.nsIThread.DISPATCH_NORMAL);
  1.1638 +  },
  1.1639 +
  1.1640 +  fireRequestError: function(requestId, error) {
  1.1641 +    let request = this.takeRequest(requestId);
  1.1642 +    if (!request) {
  1.1643 +      if (DEBUG) {
  1.1644 +        debug("not firing error for id: " + requestId +
  1.1645 +              ", error: " + JSON.stringify(error));
  1.1646 +      }
  1.1647 +      return;
  1.1648 +    }
  1.1649 +
  1.1650 +    if (DEBUG) {
  1.1651 +      debug("fire request error, id: " + requestId +
  1.1652 +            ", result: " + JSON.stringify(error));
  1.1653 +    }
  1.1654 +    Services.DOMRequest.fireError(request, error);
  1.1655 +  },
  1.1656 +
  1.1657 +  dispatchFireRequestError: function(requestId, error) {
  1.1658 +    let currentThread = Services.tm.currentThread;
  1.1659 +
  1.1660 +    currentThread.dispatch(this.fireRequestError.bind(this, requestId, error),
  1.1661 +                           Ci.nsIThread.DISPATCH_NORMAL);
  1.1662 +  },
  1.1663 +
  1.1664 +  fireRequestDetailedError: function(requestId, detailedError) {
  1.1665 +    let request = this.takeRequest(requestId);
  1.1666 +    if (!request) {
  1.1667 +      if (DEBUG) {
  1.1668 +        debug("not firing detailed error for id: " + requestId +
  1.1669 +              ", detailedError: " + JSON.stringify(detailedError));
  1.1670 +      }
  1.1671 +      return;
  1.1672 +    }
  1.1673 +
  1.1674 +    Services.DOMRequest.fireDetailedError(request, detailedError);
  1.1675 +  },
  1.1676 +
  1.1677 +  receiveMessage: function(msg) {
  1.1678 +    let request;
  1.1679 +    if (DEBUG) {
  1.1680 +      debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
  1.1681 +    }
  1.1682 +
  1.1683 +    let data = msg.json.data;
  1.1684 +    let clientId = msg.json.clientId;
  1.1685 +    switch (msg.name) {
  1.1686 +      case "RIL:CardStateChanged":
  1.1687 +        if (this.rilContexts[clientId].cardState != data.cardState) {
  1.1688 +          this.rilContexts[clientId].cardState = data.cardState;
  1.1689 +          this._deliverEvent(clientId,
  1.1690 +                             "_iccListeners",
  1.1691 +                             "notifyCardStateChanged",
  1.1692 +                             null);
  1.1693 +        }
  1.1694 +        break;
  1.1695 +      case "RIL:IccInfoChanged":
  1.1696 +        this.updateIccInfo(clientId, data);
  1.1697 +        this._deliverEvent(clientId,
  1.1698 +                           "_iccListeners",
  1.1699 +                           "notifyIccInfoChanged",
  1.1700 +                           null);
  1.1701 +        break;
  1.1702 +      case "RIL:VoiceInfoChanged":
  1.1703 +        this.updateConnectionInfo(data,
  1.1704 +                                  this.rilContexts[clientId].voiceConnectionInfo);
  1.1705 +        this._deliverEvent(clientId,
  1.1706 +                           "_mobileConnectionListeners",
  1.1707 +                           "notifyVoiceChanged",
  1.1708 +                           null);
  1.1709 +        break;
  1.1710 +      case "RIL:DataInfoChanged":
  1.1711 +        this.updateConnectionInfo(data,
  1.1712 +                                  this.rilContexts[clientId].dataConnectionInfo);
  1.1713 +        this._deliverEvent(clientId,
  1.1714 +                           "_mobileConnectionListeners",
  1.1715 +                           "notifyDataChanged",
  1.1716 +                           null);
  1.1717 +        break;
  1.1718 +      case "RIL:OtaStatusChanged":
  1.1719 +        this._deliverEvent(clientId,
  1.1720 +                           "_mobileConnectionListeners",
  1.1721 +                           "notifyOtaStatusChanged",
  1.1722 +                           [data]);
  1.1723 +        break;
  1.1724 +      case "RIL:GetAvailableNetworks":
  1.1725 +        this.handleGetAvailableNetworks(data);
  1.1726 +        break;
  1.1727 +      case "RIL:NetworkSelectionModeChanged":
  1.1728 +        this.rilContexts[clientId].networkSelectionMode = data.mode;
  1.1729 +        break;
  1.1730 +      case "RIL:SelectNetwork":
  1.1731 +        this.handleSelectNetwork(clientId, data,
  1.1732 +                                 RIL.GECKO_NETWORK_SELECTION_MANUAL);
  1.1733 +        break;
  1.1734 +      case "RIL:SelectNetworkAuto":
  1.1735 +        this.handleSelectNetwork(clientId, data,
  1.1736 +                                 RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
  1.1737 +        break;
  1.1738 +      case "RIL:SetPreferredNetworkType":
  1.1739 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1740 +        break;
  1.1741 +      case "RIL:GetPreferredNetworkType":
  1.1742 +        this.handleSimpleRequest(data.requestId, data.errorMsg, data.type);
  1.1743 +        break;
  1.1744 +      case "RIL:VoicemailNotification":
  1.1745 +        this.handleVoicemailNotification(clientId, data);
  1.1746 +        break;
  1.1747 +      case "RIL:VoicemailInfoChanged":
  1.1748 +        this.updateInfo(data, this.voicemailInfos[clientId]);
  1.1749 +        break;
  1.1750 +      case "RIL:CardLockResult": {
  1.1751 +        let requestId = data.requestId;
  1.1752 +        let requestWindow = this._windowsMap[requestId];
  1.1753 +        delete this._windowsMap[requestId];
  1.1754 +
  1.1755 +        if (data.success) {
  1.1756 +          let result = new MobileIccCardLockResult(data);
  1.1757 +          this.fireRequestSuccess(requestId, result);
  1.1758 +        } else {
  1.1759 +          if (data.rilMessageType == "iccSetCardLock" ||
  1.1760 +              data.rilMessageType == "iccUnlockCardLock") {
  1.1761 +            let cardLockError = new requestWindow.IccCardLockError(data.lockType,
  1.1762 +                                                                   data.errorMsg,
  1.1763 +                                                                   data.retryCount);
  1.1764 +            this.fireRequestDetailedError(requestId, cardLockError);
  1.1765 +          } else {
  1.1766 +            this.fireRequestError(requestId, data.errorMsg);
  1.1767 +          }
  1.1768 +        }
  1.1769 +        break;
  1.1770 +      }
  1.1771 +      case "RIL:CardLockRetryCount":
  1.1772 +        if (data.success) {
  1.1773 +          let result = new MobileIccCardLockRetryCount(data);
  1.1774 +          this.fireRequestSuccess(data.requestId, result);
  1.1775 +        } else {
  1.1776 +          this.fireRequestError(data.requestId, data.errorMsg);
  1.1777 +        }
  1.1778 +        break;
  1.1779 +      case "RIL:USSDReceived":
  1.1780 +        this._deliverEvent(clientId,
  1.1781 +                           "_mobileConnectionListeners",
  1.1782 +                           "notifyUssdReceived",
  1.1783 +                           [data.message, data.sessionEnded]);
  1.1784 +        break;
  1.1785 +      case "RIL:SendMMI":
  1.1786 +      case "RIL:CancelMMI":
  1.1787 +        this.handleSendCancelMMI(data);
  1.1788 +        break;
  1.1789 +      case "RIL:StkCommand":
  1.1790 +        this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
  1.1791 +                           [JSON.stringify(data)]);
  1.1792 +        break;
  1.1793 +      case "RIL:StkSessionEnd":
  1.1794 +        this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
  1.1795 +        break;
  1.1796 +      case "RIL:IccOpenChannel":
  1.1797 +        this.handleSimpleRequest(data.requestId, data.errorMsg,
  1.1798 +                                 data.channel);
  1.1799 +        break;
  1.1800 +      case "RIL:IccCloseChannel":
  1.1801 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1802 +        break;
  1.1803 +      case "RIL:IccExchangeAPDU":
  1.1804 +        this.handleIccExchangeAPDU(data);
  1.1805 +        break;
  1.1806 +      case "RIL:ReadIccContacts":
  1.1807 +        this.handleReadIccContacts(data);
  1.1808 +        break;
  1.1809 +      case "RIL:UpdateIccContact":
  1.1810 +        this.handleUpdateIccContact(data);
  1.1811 +        break;
  1.1812 +      case "RIL:MatchMvno":
  1.1813 +        this.handleSimpleRequest(data.requestId, data.errorMsg, data.result);
  1.1814 +        break;
  1.1815 +      case "RIL:DataError":
  1.1816 +        this.updateConnectionInfo(data, this.rilContexts[clientId].dataConnectionInfo);
  1.1817 +        this._deliverEvent(clientId, "_mobileConnectionListeners", "notifyDataError",
  1.1818 +                           [data.errorMsg]);
  1.1819 +        break;
  1.1820 +      case "RIL:GetCallForwardingOptions":
  1.1821 +        this.handleGetCallForwardingOptions(data);
  1.1822 +        break;
  1.1823 +      case "RIL:SetCallForwardingOptions":
  1.1824 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1825 +        break;
  1.1826 +      case "RIL:GetCallBarringOptions":
  1.1827 +        this.handleGetCallBarringOptions(data);
  1.1828 +        break;
  1.1829 +      case "RIL:SetCallBarringOptions":
  1.1830 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1831 +        break;
  1.1832 +      case "RIL:ChangeCallBarringPassword":
  1.1833 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1834 +        break;
  1.1835 +      case "RIL:GetCallWaitingOptions":
  1.1836 +        this.handleSimpleRequest(data.requestId, data.errorMsg,
  1.1837 +                                 data.enabled);
  1.1838 +        break;
  1.1839 +      case "RIL:SetCallWaitingOptions":
  1.1840 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1841 +        break;
  1.1842 +      case "RIL:CfStateChanged":
  1.1843 +        this._deliverEvent(clientId,
  1.1844 +                           "_mobileConnectionListeners",
  1.1845 +                           "notifyCFStateChange",
  1.1846 +                           [data.success, data.action,
  1.1847 +                            data.reason, data.number,
  1.1848 +                            data.timeSeconds, data.serviceClass]);
  1.1849 +        break;
  1.1850 +      case "RIL:GetCallingLineIdRestriction":
  1.1851 +        this.handleGetCallingLineIdRestriction(data);
  1.1852 +        break;
  1.1853 +      case "RIL:SetCallingLineIdRestriction":
  1.1854 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1855 +        break;
  1.1856 +      case "RIL:CellBroadcastReceived": {
  1.1857 +        let message = new CellBroadcastMessage(data);
  1.1858 +        this._deliverEvent(clientId,
  1.1859 +                           "_cellBroadcastListeners",
  1.1860 +                           "notifyMessageReceived",
  1.1861 +                           [message]);
  1.1862 +        break;
  1.1863 +      }
  1.1864 +      case "RIL:SetRoamingPreference":
  1.1865 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1866 +        break;
  1.1867 +      case "RIL:GetRoamingPreference":
  1.1868 +        this.handleSimpleRequest(data.requestId, data.errorMsg,
  1.1869 +                                 data.mode);
  1.1870 +        break;
  1.1871 +      case "RIL:ExitEmergencyCbMode":
  1.1872 +        this.handleExitEmergencyCbMode(data);
  1.1873 +        break;
  1.1874 +      case "RIL:EmergencyCbModeChanged":
  1.1875 +        this._deliverEvent(clientId,
  1.1876 +                           "_mobileConnectionListeners",
  1.1877 +                           "notifyEmergencyCbModeChanged",
  1.1878 +                           [data.active, data.timeoutMs]);
  1.1879 +        break;
  1.1880 +      case "RIL:SetRadioEnabled":
  1.1881 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1882 +        break;
  1.1883 +      case "RIL:RadioStateChanged":
  1.1884 +        this.rilContexts[clientId].radioState = data;
  1.1885 +        this._deliverEvent(clientId,
  1.1886 +                           "_mobileConnectionListeners",
  1.1887 +                           "notifyRadioStateChanged",
  1.1888 +                           null);
  1.1889 +        break;
  1.1890 +      case "RIL:SetVoicePrivacyMode":
  1.1891 +        this.handleSimpleRequest(data.requestId, data.errorMsg, null);
  1.1892 +        break;
  1.1893 +      case "RIL:GetVoicePrivacyMode":
  1.1894 +        this.handleSimpleRequest(data.requestId, data.errorMsg,
  1.1895 +                                 data.enabled);
  1.1896 +        break;
  1.1897 +    }
  1.1898 +  },
  1.1899 +
  1.1900 +  handleSimpleRequest: function(requestId, errorMsg, result) {
  1.1901 +    if (errorMsg) {
  1.1902 +      this.fireRequestError(requestId, errorMsg);
  1.1903 +    } else {
  1.1904 +      this.fireRequestSuccess(requestId, result);
  1.1905 +    }
  1.1906 +  },
  1.1907 +
  1.1908 +  handleGetAvailableNetworks: function(message) {
  1.1909 +    if (DEBUG) debug("handleGetAvailableNetworks: " + JSON.stringify(message));
  1.1910 +    if (message.errorMsg) {
  1.1911 +      if (DEBUG) {
  1.1912 +        debug("Received error from getAvailableNetworks: " + message.errorMsg);
  1.1913 +      }
  1.1914 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.1915 +      return;
  1.1916 +    }
  1.1917 +
  1.1918 +    let networks = message.networks;
  1.1919 +    for (let i = 0; i < networks.length; i++) {
  1.1920 +      let network = networks[i];
  1.1921 +      let info = new MobileNetworkInfo();
  1.1922 +      this.updateInfo(network, info);
  1.1923 +      networks[i] = info;
  1.1924 +    }
  1.1925 +
  1.1926 +    this.fireRequestSuccess(message.requestId, networks);
  1.1927 +  },
  1.1928 +
  1.1929 +  handleSelectNetwork: function(clientId, message, mode) {
  1.1930 +    this._selectingNetworks[clientId] = null;
  1.1931 +    this.rilContexts[clientId].networkSelectionMode = mode;
  1.1932 +
  1.1933 +    if (message.errorMsg) {
  1.1934 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.1935 +    } else {
  1.1936 +      this.fireRequestSuccess(message.requestId, null);
  1.1937 +    }
  1.1938 +  },
  1.1939 +
  1.1940 +  handleIccExchangeAPDU: function(message) {
  1.1941 +    if (message.errorMsg) {
  1.1942 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.1943 +    } else {
  1.1944 +      var result = [message.sw1, message.sw2, message.simResponse];
  1.1945 +      this.fireRequestSuccess(message.requestId, result);
  1.1946 +    }
  1.1947 +  },
  1.1948 +
  1.1949 +  handleReadIccContacts: function(message) {
  1.1950 +    if (message.errorMsg) {
  1.1951 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.1952 +      return;
  1.1953 +    }
  1.1954 +
  1.1955 +    let window = this._windowsMap[message.requestId];
  1.1956 +    delete this._windowsMap[message.requestId];
  1.1957 +    let contacts = message.contacts;
  1.1958 +    let result = contacts.map(function(c) {
  1.1959 +      let prop = {name: [c.alphaId], tel: [{value: c.number}]};
  1.1960 +
  1.1961 +      if (c.email) {
  1.1962 +        prop.email = [{value: c.email}];
  1.1963 +      }
  1.1964 +
  1.1965 +      // ANR - Additional Number
  1.1966 +      let anrLen = c.anr ? c.anr.length : 0;
  1.1967 +      for (let i = 0; i < anrLen; i++) {
  1.1968 +        prop.tel.push({value: c.anr[i]});
  1.1969 +      }
  1.1970 +
  1.1971 +      let contact = new window.mozContact(prop);
  1.1972 +      contact.id = c.contactId;
  1.1973 +      return contact;
  1.1974 +    });
  1.1975 +
  1.1976 +    this.fireRequestSuccess(message.requestId, result);
  1.1977 +  },
  1.1978 +
  1.1979 +  handleUpdateIccContact: function(message) {
  1.1980 +    if (message.errorMsg) {
  1.1981 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.1982 +      return;
  1.1983 +    }
  1.1984 +
  1.1985 +    let window = this._windowsMap[message.requestId];
  1.1986 +    delete this._windowsMap[message.requestId];
  1.1987 +    let iccContact = message.contact;
  1.1988 +    let prop = {name: [iccContact.alphaId], tel: [{value: iccContact.number}]};
  1.1989 +    if (iccContact.email) {
  1.1990 +      prop.email = [{value: iccContact.email}];
  1.1991 +    }
  1.1992 +
  1.1993 +    // ANR - Additional Number
  1.1994 +    let anrLen = iccContact.anr ? iccContact.anr.length : 0;
  1.1995 +    for (let i = 0; i < anrLen; i++) {
  1.1996 +      prop.tel.push({value: iccContact.anr[i]});
  1.1997 +    }
  1.1998 +
  1.1999 +    let contact = new window.mozContact(prop);
  1.2000 +    contact.id = iccContact.contactId;
  1.2001 +
  1.2002 +    this.fireRequestSuccess(message.requestId, contact);
  1.2003 +  },
  1.2004 +
  1.2005 +  handleVoicemailNotification: function(clientId, message) {
  1.2006 +    let changed = false;
  1.2007 +    if (!this.voicemailStatuses[clientId]) {
  1.2008 +      this.voicemailStatuses[clientId] = new VoicemailStatus(clientId);
  1.2009 +    }
  1.2010 +
  1.2011 +    let voicemailStatus = this.voicemailStatuses[clientId];
  1.2012 +    if (voicemailStatus.hasMessages != message.active) {
  1.2013 +      changed = true;
  1.2014 +      voicemailStatus.hasMessages = message.active;
  1.2015 +    }
  1.2016 +
  1.2017 +    if (voicemailStatus.messageCount != message.msgCount) {
  1.2018 +      changed = true;
  1.2019 +      voicemailStatus.messageCount = message.msgCount;
  1.2020 +    } else if (message.msgCount == -1) {
  1.2021 +      // For MWI using DCS the message count is not available
  1.2022 +      changed = true;
  1.2023 +    }
  1.2024 +
  1.2025 +    if (voicemailStatus.returnNumber != message.returnNumber) {
  1.2026 +      changed = true;
  1.2027 +      voicemailStatus.returnNumber = message.returnNumber;
  1.2028 +    }
  1.2029 +
  1.2030 +    if (voicemailStatus.returnMessage != message.returnMessage) {
  1.2031 +      changed = true;
  1.2032 +      voicemailStatus.returnMessage = message.returnMessage;
  1.2033 +    }
  1.2034 +
  1.2035 +    if (changed) {
  1.2036 +      // To follow the event delivering scheme, we add a dummy clientId 0.
  1.2037 +      // All voicemail events are routed to listener for client id 0.
  1.2038 +      this._deliverEvent(0,
  1.2039 +                         "_voicemailListeners",
  1.2040 +                         "notifyStatusChanged",
  1.2041 +                         [voicemailStatus]);
  1.2042 +    }
  1.2043 +  },
  1.2044 +
  1.2045 +  _cfRulesToMobileCfInfo: function(rules) {
  1.2046 +    for (let i = 0; i < rules.length; i++) {
  1.2047 +      let rule = rules[i];
  1.2048 +      let info = new MobileCFInfo();
  1.2049 +      this.updateInfo(rule, info);
  1.2050 +      rules[i] = info;
  1.2051 +    }
  1.2052 +  },
  1.2053 +
  1.2054 +  handleGetCallForwardingOptions: function(message) {
  1.2055 +    if (message.errorMsg) {
  1.2056 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.2057 +      return;
  1.2058 +    }
  1.2059 +
  1.2060 +    this._cfRulesToMobileCfInfo(message.rules);
  1.2061 +    this.fireRequestSuccess(message.requestId, message.rules);
  1.2062 +  },
  1.2063 +
  1.2064 +  handleGetCallBarringOptions: function(message) {
  1.2065 +    if (!message.success) {
  1.2066 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.2067 +    } else {
  1.2068 +      let options = new CallBarringOptions(message);
  1.2069 +      this.fireRequestSuccess(message.requestId, options);
  1.2070 +    }
  1.2071 +  },
  1.2072 +
  1.2073 +  handleGetCallingLineIdRestriction: function(message) {
  1.2074 +    if (message.errorMsg) {
  1.2075 +      this.fireRequestError(message.requestId, message.errorMsg);
  1.2076 +      return;
  1.2077 +    }
  1.2078 +
  1.2079 +    let status = new DOMCLIRStatus(message);
  1.2080 +    this.fireRequestSuccess(message.requestId, status);
  1.2081 +  },
  1.2082 +
  1.2083 +  handleExitEmergencyCbMode: function(message) {
  1.2084 +    let requestId = message.requestId;
  1.2085 +    let request = this.takeRequest(requestId);
  1.2086 +    if (!request) {
  1.2087 +      return;
  1.2088 +    }
  1.2089 +
  1.2090 +    if (!message.success) {
  1.2091 +      Services.DOMRequest.fireError(request, message.errorMsg);
  1.2092 +      return;
  1.2093 +    }
  1.2094 +    Services.DOMRequest.fireSuccess(request, null);
  1.2095 +  },
  1.2096 +
  1.2097 +  handleSendCancelMMI: function(message) {
  1.2098 +    if (DEBUG) debug("handleSendCancelMMI " + JSON.stringify(message));
  1.2099 +    let request = this.takeRequest(message.requestId);
  1.2100 +    let requestWindow = this._windowsMap[message.requestId];
  1.2101 +    delete this._windowsMap[message.requestId];
  1.2102 +    if (!request) {
  1.2103 +      return;
  1.2104 +    }
  1.2105 +
  1.2106 +    let success = message.success;
  1.2107 +
  1.2108 +    // We expect to have an IMEI at this point if the request was supposed
  1.2109 +    // to query for the IMEI, so getting a successful reply from the RIL
  1.2110 +    // without containing an actual IMEI number is considered an error.
  1.2111 +    if (message.mmiServiceCode === RIL.MMI_KS_SC_IMEI &&
  1.2112 +        !message.statusMessage) {
  1.2113 +        message.errorMsg = message.errorMsg ?
  1.2114 +          message.errorMsg : RIL.GECKO_ERROR_GENERIC_FAILURE;
  1.2115 +        success = false;
  1.2116 +    }
  1.2117 +
  1.2118 +    // MMI query call forwarding options request returns a set of rules that
  1.2119 +    // will be exposed in the form of an array of nsIDOMMozMobileCFInfo
  1.2120 +    // instances.
  1.2121 +    if (message.mmiServiceCode === RIL.MMI_KS_SC_CALL_FORWARDING &&
  1.2122 +        message.additionalInformation) {
  1.2123 +      this._cfRulesToMobileCfInfo(message.additionalInformation);
  1.2124 +    }
  1.2125 +
  1.2126 +    let result = {
  1.2127 +      serviceCode: message.mmiServiceCode,
  1.2128 +      additionalInformation: message.additionalInformation
  1.2129 +    };
  1.2130 +
  1.2131 +    if (success) {
  1.2132 +      result.statusMessage = message.statusMessage;
  1.2133 +      let mmiResult = new DOMMMIResult(result);
  1.2134 +      Services.DOMRequest.fireSuccess(request, mmiResult);
  1.2135 +    } else {
  1.2136 +      let mmiError = new requestWindow.DOMMMIError(result.serviceCode,
  1.2137 +                                                   message.errorMsg,
  1.2138 +                                                   null,
  1.2139 +                                                   result.additionalInformation);
  1.2140 +      Services.DOMRequest.fireDetailedError(request, mmiError);
  1.2141 +    }
  1.2142 +  },
  1.2143 +
  1.2144 +  _deliverEvent: function(clientId, listenerType, name, args) {
  1.2145 +    if (!this[listenerType]) {
  1.2146 +      return;
  1.2147 +    }
  1.2148 +    let thisListeners = this[listenerType][clientId];
  1.2149 +    if (!thisListeners) {
  1.2150 +      return;
  1.2151 +    }
  1.2152 +
  1.2153 +    let listeners = thisListeners.slice();
  1.2154 +    for (let listener of listeners) {
  1.2155 +      if (thisListeners.indexOf(listener) == -1) {
  1.2156 +        continue;
  1.2157 +      }
  1.2158 +      let handler = listener[name];
  1.2159 +      if (typeof handler != "function") {
  1.2160 +        throw new Error("No handler for " + name);
  1.2161 +      }
  1.2162 +      try {
  1.2163 +        handler.apply(listener, args);
  1.2164 +      } catch (e) {
  1.2165 +        if (DEBUG) debug("listener for " + name + " threw an exception: " + e);
  1.2166 +      }
  1.2167 +    }
  1.2168 +  },
  1.2169 +
  1.2170 +  /**
  1.2171 +   * Helper for guarding us again invalid reason values for call forwarding.
  1.2172 +   */
  1.2173 +  _isValidCFReason: function(reason) {
  1.2174 +    switch (reason) {
  1.2175 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_UNCONDITIONAL:
  1.2176 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_MOBILE_BUSY:
  1.2177 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_NO_REPLY:
  1.2178 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_NOT_REACHABLE:
  1.2179 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_ALL_CALL_FORWARDING:
  1.2180 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING:
  1.2181 +        return true;
  1.2182 +      default:
  1.2183 +        return false;
  1.2184 +    }
  1.2185 +  },
  1.2186 +
  1.2187 +  /**
  1.2188 +   * Helper for guarding us again invalid action values for call forwarding.
  1.2189 +   */
  1.2190 +  _isValidCFAction: function(action) {
  1.2191 +    switch (action) {
  1.2192 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_DISABLE:
  1.2193 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_ENABLE:
  1.2194 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_REGISTRATION:
  1.2195 +      case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_ERASURE:
  1.2196 +        return true;
  1.2197 +      default:
  1.2198 +        return false;
  1.2199 +    }
  1.2200 +  },
  1.2201 +
  1.2202 +  /**
  1.2203 +   * Helper for guarding us against invalid program values for call barring.
  1.2204 +   */
  1.2205 +  _isValidCallBarringProgram: function(program) {
  1.2206 +    switch (program) {
  1.2207 +      case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING:
  1.2208 +      case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL:
  1.2209 +      case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME:
  1.2210 +      case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING:
  1.2211 +      case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING:
  1.2212 +        return true;
  1.2213 +      default:
  1.2214 +        return false;
  1.2215 +    }
  1.2216 +  },
  1.2217 +
  1.2218 +  /**
  1.2219 +   * Helper for guarding us against invalid options for call barring.
  1.2220 +   */
  1.2221 +  _isValidCallBarringOptions: function(options, usedForSetting) {
  1.2222 +    if (!options ||
  1.2223 +        options.serviceClass == null ||
  1.2224 +        !this._isValidCallBarringProgram(options.program)) {
  1.2225 +      return false;
  1.2226 +    }
  1.2227 +
  1.2228 +    // For setting callbarring options, |enabled| and |password| are required.
  1.2229 +    if (usedForSetting && (options.enabled == null || options.password == null)) {
  1.2230 +      return false;
  1.2231 +    }
  1.2232 +
  1.2233 +    return true;
  1.2234 +  }
  1.2235 +};
  1.2236 +
  1.2237 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper,
  1.2238 +                                                     DOMMMIError,
  1.2239 +                                                     IccCardLockError]);

mercurial