dom/system/gonk/RILContentHelper.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* Copyright 2012 Mozilla Foundation and Mozilla contributors
michael@0 2 *
michael@0 3 * Licensed under the Apache License, Version 2.0 (the "License");
michael@0 4 * you may not use this file except in compliance with the License.
michael@0 5 * You may obtain a copy of the License at
michael@0 6 *
michael@0 7 * http://www.apache.org/licenses/LICENSE-2.0
michael@0 8 *
michael@0 9 * Unless required by applicable law or agreed to in writing, software
michael@0 10 * distributed under the License is distributed on an "AS IS" BASIS,
michael@0 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
michael@0 12 * See the License for the specific language governing permissions and
michael@0 13 * limitations under the License.
michael@0 14 */
michael@0 15
michael@0 16 "use strict";
michael@0 17
michael@0 18 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
michael@0 19
michael@0 20 Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
michael@0 21 Cu.import("resource://gre/modules/Services.jsm");
michael@0 22 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 23
michael@0 24 var RIL = {};
michael@0 25 Cu.import("resource://gre/modules/ril_consts.js", RIL);
michael@0 26
michael@0 27 const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
michael@0 28
michael@0 29 const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
michael@0 30
michael@0 31 const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
michael@0 32 const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
michael@0 33 const kPrefVoicemailDefaultServiceId = "dom.voicemail.defaultServiceId";
michael@0 34
michael@0 35 let DEBUG;
michael@0 36 function debug(s) {
michael@0 37 dump("-*- RILContentHelper: " + s + "\n");
michael@0 38 }
michael@0 39
michael@0 40 const RILCONTENTHELPER_CID =
michael@0 41 Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
michael@0 42 const GSMICCINFO_CID =
michael@0 43 Components.ID("{e0fa785b-ad3f-46ed-bc56-fcb0d6fe4fa8}");
michael@0 44 const CDMAICCINFO_CID =
michael@0 45 Components.ID("{3d1f844f-9ec5-48fb-8907-aed2e5421709}");
michael@0 46 const MOBILECONNECTIONINFO_CID =
michael@0 47 Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
michael@0 48 const MOBILENETWORKINFO_CID =
michael@0 49 Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
michael@0 50 const MOBILECELLINFO_CID =
michael@0 51 Components.ID("{ae724dd4-ccaf-4006-98f1-6ce66a092464}");
michael@0 52 const VOICEMAILSTATUS_CID=
michael@0 53 Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
michael@0 54 const MOBILECFINFO_CID=
michael@0 55 Components.ID("{a4756f16-e728-4d9f-8baa-8464f894888a}");
michael@0 56 const CELLBROADCASTMESSAGE_CID =
michael@0 57 Components.ID("{29474c96-3099-486f-bb4a-3c9a1da834e4}");
michael@0 58 const CELLBROADCASTETWSINFO_CID =
michael@0 59 Components.ID("{59f176ee-9dcd-4005-9d47-f6be0cd08e17}");
michael@0 60 const DOMMMIERROR_CID =
michael@0 61 Components.ID("{6b204c42-7928-4e71-89ad-f90cd82aff96}");
michael@0 62 const ICCCARDLOCKERROR_CID =
michael@0 63 Components.ID("{08a71987-408c-44ff-93fd-177c0a85c3dd}");
michael@0 64
michael@0 65 const RIL_IPC_MSG_NAMES = [
michael@0 66 "RIL:CardStateChanged",
michael@0 67 "RIL:IccInfoChanged",
michael@0 68 "RIL:VoiceInfoChanged",
michael@0 69 "RIL:DataInfoChanged",
michael@0 70 "RIL:GetAvailableNetworks",
michael@0 71 "RIL:NetworkSelectionModeChanged",
michael@0 72 "RIL:SelectNetwork",
michael@0 73 "RIL:SelectNetworkAuto",
michael@0 74 "RIL:SetPreferredNetworkType",
michael@0 75 "RIL:GetPreferredNetworkType",
michael@0 76 "RIL:EmergencyCbModeChanged",
michael@0 77 "RIL:VoicemailNotification",
michael@0 78 "RIL:VoicemailInfoChanged",
michael@0 79 "RIL:CardLockResult",
michael@0 80 "RIL:CardLockRetryCount",
michael@0 81 "RIL:USSDReceived",
michael@0 82 "RIL:SendMMI",
michael@0 83 "RIL:CancelMMI",
michael@0 84 "RIL:StkCommand",
michael@0 85 "RIL:StkSessionEnd",
michael@0 86 "RIL:DataError",
michael@0 87 "RIL:SetCallForwardingOptions",
michael@0 88 "RIL:GetCallForwardingOptions",
michael@0 89 "RIL:SetCallBarringOptions",
michael@0 90 "RIL:GetCallBarringOptions",
michael@0 91 "RIL:ChangeCallBarringPassword",
michael@0 92 "RIL:SetCallWaitingOptions",
michael@0 93 "RIL:GetCallWaitingOptions",
michael@0 94 "RIL:SetCallingLineIdRestriction",
michael@0 95 "RIL:GetCallingLineIdRestriction",
michael@0 96 "RIL:CellBroadcastReceived",
michael@0 97 "RIL:CfStateChanged",
michael@0 98 "RIL:IccOpenChannel",
michael@0 99 "RIL:IccCloseChannel",
michael@0 100 "RIL:IccExchangeAPDU",
michael@0 101 "RIL:ReadIccContacts",
michael@0 102 "RIL:UpdateIccContact",
michael@0 103 "RIL:SetRoamingPreference",
michael@0 104 "RIL:GetRoamingPreference",
michael@0 105 "RIL:ExitEmergencyCbMode",
michael@0 106 "RIL:SetRadioEnabled",
michael@0 107 "RIL:RadioStateChanged",
michael@0 108 "RIL:SetVoicePrivacyMode",
michael@0 109 "RIL:GetVoicePrivacyMode",
michael@0 110 "RIL:OtaStatusChanged",
michael@0 111 "RIL:MatchMvno"
michael@0 112 ];
michael@0 113
michael@0 114 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
michael@0 115 "@mozilla.org/childprocessmessagemanager;1",
michael@0 116 "nsISyncMessageSender");
michael@0 117
michael@0 118 XPCOMUtils.defineLazyGetter(this, "gNumRadioInterfaces", function() {
michael@0 119 let appInfo = Cc["@mozilla.org/xre/app-info;1"];
michael@0 120 let isParentProcess = !appInfo || appInfo.getService(Ci.nsIXULRuntime)
michael@0 121 .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
michael@0 122
michael@0 123 if (isParentProcess) {
michael@0 124 let ril = Cc["@mozilla.org/ril;1"].getService(Ci.nsIRadioInterfaceLayer);
michael@0 125 return ril.numRadioInterfaces;
michael@0 126 }
michael@0 127
michael@0 128 return Services.prefs.getIntPref(kPrefRilNumRadioInterfaces);
michael@0 129 });
michael@0 130
michael@0 131 function MobileIccCardLockResult(options) {
michael@0 132 this.lockType = options.lockType;
michael@0 133 this.enabled = options.enabled;
michael@0 134 this.retryCount = options.retryCount;
michael@0 135 this.success = options.success;
michael@0 136 }
michael@0 137 MobileIccCardLockResult.prototype = {
michael@0 138 __exposedProps__ : {lockType: 'r',
michael@0 139 enabled: 'r',
michael@0 140 retryCount: 'r',
michael@0 141 success: 'r'}
michael@0 142 };
michael@0 143
michael@0 144 function MobileIccCardLockRetryCount(options) {
michael@0 145 this.lockType = options.lockType;
michael@0 146 this.retryCount = options.retryCount;
michael@0 147 this.success = options.success;
michael@0 148 }
michael@0 149 MobileIccCardLockRetryCount.prototype = {
michael@0 150 __exposedProps__ : {lockType: 'r',
michael@0 151 retryCount: 'r',
michael@0 152 success: 'r'}
michael@0 153 };
michael@0 154
michael@0 155 function IccInfo() {}
michael@0 156 IccInfo.prototype = {
michael@0 157 iccType: null,
michael@0 158 iccid: null,
michael@0 159 mcc: null,
michael@0 160 mnc: null,
michael@0 161 spn: null,
michael@0 162 isDisplayNetworkNameRequired: null,
michael@0 163 isDisplaySpnRequired: null
michael@0 164 };
michael@0 165
michael@0 166 function GsmIccInfo() {}
michael@0 167 GsmIccInfo.prototype = {
michael@0 168 __proto__: IccInfo.prototype,
michael@0 169 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozGsmIccInfo]),
michael@0 170 classID: GSMICCINFO_CID,
michael@0 171 classInfo: XPCOMUtils.generateCI({
michael@0 172 classID: GSMICCINFO_CID,
michael@0 173 classDescription: "MozGsmIccInfo",
michael@0 174 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 175 interfaces: [Ci.nsIDOMMozGsmIccInfo]
michael@0 176 }),
michael@0 177
michael@0 178 // nsIDOMMozGsmIccInfo
michael@0 179
michael@0 180 msisdn: null
michael@0 181 };
michael@0 182
michael@0 183 function CdmaIccInfo() {}
michael@0 184 CdmaIccInfo.prototype = {
michael@0 185 __proto__: IccInfo.prototype,
michael@0 186 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCdmaIccInfo]),
michael@0 187 classID: CDMAICCINFO_CID,
michael@0 188 classInfo: XPCOMUtils.generateCI({
michael@0 189 classID: CDMAICCINFO_CID,
michael@0 190 classDescription: "MozCdmaIccInfo",
michael@0 191 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 192 interfaces: [Ci.nsIDOMMozCdmaIccInfo]
michael@0 193 }),
michael@0 194
michael@0 195 // nsIDOMMozCdmaIccInfo
michael@0 196
michael@0 197 mdn: null,
michael@0 198 prlVersion: 0
michael@0 199 };
michael@0 200
michael@0 201 function VoicemailInfo() {}
michael@0 202 VoicemailInfo.prototype = {
michael@0 203 number: null,
michael@0 204 displayName: null
michael@0 205 };
michael@0 206
michael@0 207 function MobileConnectionInfo() {}
michael@0 208 MobileConnectionInfo.prototype = {
michael@0 209 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileConnectionInfo]),
michael@0 210 classID: MOBILECONNECTIONINFO_CID,
michael@0 211 classInfo: XPCOMUtils.generateCI({
michael@0 212 classID: MOBILECONNECTIONINFO_CID,
michael@0 213 classDescription: "MobileConnectionInfo",
michael@0 214 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 215 interfaces: [Ci.nsIDOMMozMobileConnectionInfo]
michael@0 216 }),
michael@0 217
michael@0 218 // nsIDOMMozMobileConnectionInfo
michael@0 219
michael@0 220 connected: false,
michael@0 221 state: null,
michael@0 222 emergencyCallsOnly: false,
michael@0 223 roaming: false,
michael@0 224 network: null,
michael@0 225 cell: null,
michael@0 226 type: null,
michael@0 227 signalStrength: null,
michael@0 228 relSignalStrength: null
michael@0 229 };
michael@0 230
michael@0 231 function MobileNetworkInfo() {}
michael@0 232 MobileNetworkInfo.prototype = {
michael@0 233 __exposedProps__ : {shortName: 'r',
michael@0 234 longName: 'r',
michael@0 235 mcc: 'r',
michael@0 236 mnc: 'r',
michael@0 237 state: 'r'},
michael@0 238
michael@0 239 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileNetworkInfo]),
michael@0 240 classID: MOBILENETWORKINFO_CID,
michael@0 241 classInfo: XPCOMUtils.generateCI({
michael@0 242 classID: MOBILENETWORKINFO_CID,
michael@0 243 classDescription: "MobileNetworkInfo",
michael@0 244 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 245 interfaces: [Ci.nsIDOMMozMobileNetworkInfo]
michael@0 246 }),
michael@0 247
michael@0 248 // nsIDOMMozMobileNetworkInfo
michael@0 249
michael@0 250 shortName: null,
michael@0 251 longName: null,
michael@0 252 mcc: null,
michael@0 253 mnc: null,
michael@0 254 state: null
michael@0 255 };
michael@0 256
michael@0 257 function MobileCellInfo() {}
michael@0 258 MobileCellInfo.prototype = {
michael@0 259 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileCellInfo]),
michael@0 260 classID: MOBILECELLINFO_CID,
michael@0 261 classInfo: XPCOMUtils.generateCI({
michael@0 262 classID: MOBILECELLINFO_CID,
michael@0 263 classDescription: "MobileCellInfo",
michael@0 264 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 265 interfaces: [Ci.nsIDOMMozMobileCellInfo]
michael@0 266 }),
michael@0 267
michael@0 268 // nsIDOMMozMobileCellInfo
michael@0 269
michael@0 270 gsmLocationAreaCode: -1,
michael@0 271 gsmCellId: -1,
michael@0 272 cdmaBaseStationId: -1,
michael@0 273 cdmaBaseStationLatitude: -2147483648,
michael@0 274 cdmaBaseStationLongitude: -2147483648,
michael@0 275 cdmaSystemId: -1,
michael@0 276 cdmaNetworkId: -1
michael@0 277 };
michael@0 278
michael@0 279 function VoicemailStatus(clientId) {
michael@0 280 this.serviceId = clientId;
michael@0 281 }
michael@0 282 VoicemailStatus.prototype = {
michael@0 283 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
michael@0 284 classID: VOICEMAILSTATUS_CID,
michael@0 285 classInfo: XPCOMUtils.generateCI({
michael@0 286 classID: VOICEMAILSTATUS_CID,
michael@0 287 classDescription: "VoicemailStatus",
michael@0 288 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 289 interfaces: [Ci.nsIDOMMozVoicemailStatus]
michael@0 290 }),
michael@0 291
michael@0 292 // nsIDOMMozVoicemailStatus
michael@0 293
michael@0 294 serviceId: -1,
michael@0 295 hasMessages: false,
michael@0 296 messageCount: -1, // Count unknown.
michael@0 297 returnNumber: null,
michael@0 298 returnMessage: null
michael@0 299 };
michael@0 300
michael@0 301 function MobileCFInfo() {}
michael@0 302 MobileCFInfo.prototype = {
michael@0 303 __exposedProps__ : {active: 'r',
michael@0 304 action: 'r',
michael@0 305 reason: 'r',
michael@0 306 number: 'r',
michael@0 307 timeSeconds: 'r',
michael@0 308 serviceClass: 'r'},
michael@0 309 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileCFInfo]),
michael@0 310 classID: MOBILECFINFO_CID,
michael@0 311 classInfo: XPCOMUtils.generateCI({
michael@0 312 classID: MOBILECFINFO_CID,
michael@0 313 classDescription: "MobileCFInfo",
michael@0 314 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 315 interfaces: [Ci.nsIDOMMozMobileCFInfo]
michael@0 316 }),
michael@0 317
michael@0 318 // nsIDOMMozMobileCFInfo
michael@0 319
michael@0 320 active: false,
michael@0 321 action: -1,
michael@0 322 reason: -1,
michael@0 323 number: null,
michael@0 324 timeSeconds: 0,
michael@0 325 serviceClass: -1
michael@0 326 };
michael@0 327
michael@0 328 function CellBroadcastMessage(pdu) {
michael@0 329 this.gsmGeographicalScope = RIL.CB_GSM_GEOGRAPHICAL_SCOPE_NAMES[pdu.geographicalScope];
michael@0 330 this.messageCode = pdu.messageCode;
michael@0 331 this.messageId = pdu.messageId;
michael@0 332 this.language = pdu.language;
michael@0 333 this.body = pdu.fullBody;
michael@0 334 this.messageClass = pdu.messageClass;
michael@0 335 this.timestamp = new Date(pdu.timestamp);
michael@0 336
michael@0 337 if (pdu.etws != null) {
michael@0 338 this.etws = new CellBroadcastEtwsInfo(pdu.etws);
michael@0 339 }
michael@0 340
michael@0 341 this.cdmaServiceCategory = pdu.serviceCategory;
michael@0 342 }
michael@0 343 CellBroadcastMessage.prototype = {
michael@0 344 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastMessage]),
michael@0 345 classID: CELLBROADCASTMESSAGE_CID,
michael@0 346 classInfo: XPCOMUtils.generateCI({
michael@0 347 classID: CELLBROADCASTMESSAGE_CID,
michael@0 348 classDescription: "CellBroadcastMessage",
michael@0 349 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 350 interfaces: [Ci.nsIDOMMozCellBroadcastMessage]
michael@0 351 }),
michael@0 352
michael@0 353 // nsIDOMMozCellBroadcastMessage
michael@0 354
michael@0 355 gsmGeographicalScope: null,
michael@0 356 messageCode: null,
michael@0 357 messageId: null,
michael@0 358 language: null,
michael@0 359 body: null,
michael@0 360 messageClass: null,
michael@0 361 timestamp: null,
michael@0 362
michael@0 363 etws: null,
michael@0 364 cdmaServiceCategory: null
michael@0 365 };
michael@0 366
michael@0 367 function CellBroadcastEtwsInfo(etwsInfo) {
michael@0 368 if (etwsInfo.warningType != null) {
michael@0 369 this.warningType = RIL.CB_ETWS_WARNING_TYPE_NAMES[etwsInfo.warningType];
michael@0 370 }
michael@0 371 this.emergencyUserAlert = etwsInfo.emergencyUserAlert;
michael@0 372 this.popup = etwsInfo.popup;
michael@0 373 }
michael@0 374 CellBroadcastEtwsInfo.prototype = {
michael@0 375 QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozCellBroadcastEtwsInfo]),
michael@0 376 classID: CELLBROADCASTETWSINFO_CID,
michael@0 377 classInfo: XPCOMUtils.generateCI({
michael@0 378 classID: CELLBROADCASTETWSINFO_CID,
michael@0 379 classDescription: "CellBroadcastEtwsInfo",
michael@0 380 flags: Ci.nsIClassInfo.DOM_OBJECT,
michael@0 381 interfaces: [Ci.nsIDOMMozCellBroadcastEtwsInfo]
michael@0 382 }),
michael@0 383
michael@0 384 // nsIDOMMozCellBroadcastEtwsInfo
michael@0 385
michael@0 386 warningType: null,
michael@0 387 emergencyUserAlert: null,
michael@0 388 popup: null
michael@0 389 };
michael@0 390
michael@0 391 function CallBarringOptions(options) {
michael@0 392 this.program = options.program;
michael@0 393 this.enabled = options.enabled;
michael@0 394 this.password = options.password;
michael@0 395 this.serviceClass = options.serviceClass;
michael@0 396 }
michael@0 397 CallBarringOptions.prototype = {
michael@0 398 __exposedProps__ : {program: 'r',
michael@0 399 enabled: 'r',
michael@0 400 password: 'r',
michael@0 401 serviceClass: 'r'}
michael@0 402 };
michael@0 403
michael@0 404 function DOMMMIResult(result) {
michael@0 405 this.serviceCode = result.serviceCode;
michael@0 406 this.statusMessage = result.statusMessage;
michael@0 407 this.additionalInformation = result.additionalInformation;
michael@0 408 }
michael@0 409 DOMMMIResult.prototype = {
michael@0 410 __exposedProps__: {serviceCode: 'r',
michael@0 411 statusMessage: 'r',
michael@0 412 additionalInformation: 'r'}
michael@0 413 };
michael@0 414
michael@0 415 function DOMCLIRStatus(option) {
michael@0 416 this.n = option.n;
michael@0 417 this.m = option.m;
michael@0 418 }
michael@0 419 DOMCLIRStatus.prototype = {
michael@0 420 __exposedProps__ : {n: 'r',
michael@0 421 m: 'r'}
michael@0 422 };
michael@0 423
michael@0 424 function DOMMMIError() {
michael@0 425 }
michael@0 426 DOMMMIError.prototype = {
michael@0 427 classDescription: "DOMMMIError",
michael@0 428 classID: DOMMMIERROR_CID,
michael@0 429 contractID: "@mozilla.org/dom/mmi-error;1",
michael@0 430 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
michael@0 431 __init: function(serviceCode, name, message, additionalInformation) {
michael@0 432 this.__DOM_IMPL__.init(name, message);
michael@0 433 this.serviceCode = serviceCode;
michael@0 434 this.additionalInformation = additionalInformation;
michael@0 435 },
michael@0 436 };
michael@0 437
michael@0 438 function IccCardLockError() {
michael@0 439 }
michael@0 440 IccCardLockError.prototype = {
michael@0 441 classDescription: "IccCardLockError",
michael@0 442 classID: ICCCARDLOCKERROR_CID,
michael@0 443 contractID: "@mozilla.org/dom/icccardlock-error;1",
michael@0 444 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
michael@0 445 __init: function(lockType, errorMsg, retryCount) {
michael@0 446 this.__DOM_IMPL__.init(errorMsg);
michael@0 447 this.lockType = lockType;
michael@0 448 this.retryCount = retryCount;
michael@0 449 },
michael@0 450 };
michael@0 451
michael@0 452 function RILContentHelper() {
michael@0 453 this.updateDebugFlag();
michael@0 454
michael@0 455 this.numClients = gNumRadioInterfaces;
michael@0 456 if (DEBUG) debug("Number of clients: " + this.numClients);
michael@0 457
michael@0 458 this.rilContexts = [];
michael@0 459 this.voicemailInfos = [];
michael@0 460 this.voicemailStatuses = [];
michael@0 461 for (let clientId = 0; clientId < this.numClients; clientId++) {
michael@0 462 this.rilContexts[clientId] = {
michael@0 463 cardState: RIL.GECKO_CARDSTATE_UNKNOWN,
michael@0 464 networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
michael@0 465 radioState: null,
michael@0 466 iccInfo: null,
michael@0 467 voiceConnectionInfo: new MobileConnectionInfo(),
michael@0 468 dataConnectionInfo: new MobileConnectionInfo()
michael@0 469 };
michael@0 470
michael@0 471 this.voicemailInfos[clientId] = new VoicemailInfo();
michael@0 472 }
michael@0 473
michael@0 474 this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
michael@0 475
michael@0 476 this.initDOMRequestHelper(/* aWindow */ null, RIL_IPC_MSG_NAMES);
michael@0 477 this._windowsMap = [];
michael@0 478 this._selectingNetworks = [];
michael@0 479 this._mobileConnectionListeners = [];
michael@0 480 this._cellBroadcastListeners = [];
michael@0 481 this._voicemailListeners = [];
michael@0 482 this._iccListeners = [];
michael@0 483
michael@0 484 Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
michael@0 485
michael@0 486 Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
michael@0 487 Services.prefs.addObserver(kPrefVoicemailDefaultServiceId, this, false);
michael@0 488 }
michael@0 489
michael@0 490 RILContentHelper.prototype = {
michael@0 491 __proto__: DOMRequestIpcHelper.prototype,
michael@0 492
michael@0 493 QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
michael@0 494 Ci.nsICellBroadcastProvider,
michael@0 495 Ci.nsIVoicemailProvider,
michael@0 496 Ci.nsIIccProvider,
michael@0 497 Ci.nsIObserver,
michael@0 498 Ci.nsISupportsWeakReference,
michael@0 499 Ci.nsIObserver]),
michael@0 500 classID: RILCONTENTHELPER_CID,
michael@0 501 classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
michael@0 502 classDescription: "RILContentHelper",
michael@0 503 interfaces: [Ci.nsIMobileConnectionProvider,
michael@0 504 Ci.nsICellBroadcastProvider,
michael@0 505 Ci.nsIVoicemailProvider,
michael@0 506 Ci.nsIIccProvider]}),
michael@0 507
michael@0 508 updateDebugFlag: function() {
michael@0 509 try {
michael@0 510 DEBUG = RIL.DEBUG_CONTENT_HELPER ||
michael@0 511 Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
michael@0 512 } catch (e) {}
michael@0 513 },
michael@0 514
michael@0 515 // An utility function to copy objects.
michael@0 516 updateInfo: function(srcInfo, destInfo) {
michael@0 517 for (let key in srcInfo) {
michael@0 518 destInfo[key] = srcInfo[key];
michael@0 519 }
michael@0 520 },
michael@0 521
michael@0 522 updateConnectionInfo: function(srcInfo, destInfo) {
michael@0 523 for (let key in srcInfo) {
michael@0 524 if ((key != "network") && (key != "cell")) {
michael@0 525 destInfo[key] = srcInfo[key];
michael@0 526 }
michael@0 527 }
michael@0 528
michael@0 529 let srcCell = srcInfo.cell;
michael@0 530 if (!srcCell) {
michael@0 531 destInfo.cell = null;
michael@0 532 } else {
michael@0 533 let cell = destInfo.cell;
michael@0 534 if (!cell) {
michael@0 535 cell = destInfo.cell = new MobileCellInfo();
michael@0 536 }
michael@0 537
michael@0 538 this.updateInfo(srcCell, cell);
michael@0 539 }
michael@0 540
michael@0 541 let srcNetwork = srcInfo.network;
michael@0 542 if (!srcNetwork) {
michael@0 543 destInfo.network= null;
michael@0 544 return;
michael@0 545 }
michael@0 546
michael@0 547 let network = destInfo.network;
michael@0 548 if (!network) {
michael@0 549 network = destInfo.network = new MobileNetworkInfo();
michael@0 550 }
michael@0 551
michael@0 552 this.updateInfo(srcNetwork, network);
michael@0 553 },
michael@0 554
michael@0 555 /**
michael@0 556 * We need to consider below cases when update iccInfo:
michael@0 557 * 1. Should clear iccInfo to null if there is no card detected.
michael@0 558 * 2. Need to create corresponding object based on iccType.
michael@0 559 */
michael@0 560 updateIccInfo: function(clientId, newInfo) {
michael@0 561 let rilContext = this.rilContexts[clientId];
michael@0 562
michael@0 563 // Card is not detected, clear iccInfo to null.
michael@0 564 if (!newInfo || !newInfo.iccType || !newInfo.iccid) {
michael@0 565 if (rilContext.iccInfo) {
michael@0 566 rilContext.iccInfo = null;
michael@0 567 this._deliverEvent(clientId,
michael@0 568 "_mobileConnectionListeners",
michael@0 569 "notifyIccChanged",
michael@0 570 null);
michael@0 571 }
michael@0 572 return;
michael@0 573 }
michael@0 574
michael@0 575 // If iccInfo is null, new corresponding object based on iccType.
michael@0 576 if (!rilContext.iccInfo) {
michael@0 577 if (newInfo.iccType === "ruim" || newInfo.iccType === "csim") {
michael@0 578 rilContext.iccInfo = new CdmaIccInfo();
michael@0 579 } else {
michael@0 580 rilContext.iccInfo = new GsmIccInfo();
michael@0 581 }
michael@0 582 }
michael@0 583 let changed = (rilContext.iccInfo.iccid != newInfo.iccid) ?
michael@0 584 true : false;
michael@0 585
michael@0 586 this.updateInfo(newInfo, rilContext.iccInfo);
michael@0 587
michael@0 588 // Deliver event after info is updated.
michael@0 589 if (changed) {
michael@0 590 this._deliverEvent(clientId,
michael@0 591 "_mobileConnectionListeners",
michael@0 592 "notifyIccChanged",
michael@0 593 null);
michael@0 594 }
michael@0 595 },
michael@0 596
michael@0 597 _windowsMap: null,
michael@0 598
michael@0 599 rilContexts: null,
michael@0 600
michael@0 601 getRilContext: function(clientId) {
michael@0 602 // Update ril contexts by sending IPC message to chrome only when the first
michael@0 603 // time we require it. The information will be updated by following info
michael@0 604 // changed messages.
michael@0 605 this.getRilContext = function getRilContext(clientId) {
michael@0 606 return this.rilContexts[clientId];
michael@0 607 };
michael@0 608
michael@0 609 for (let cId = 0; cId < this.numClients; cId++) {
michael@0 610 let rilContext =
michael@0 611 cpmm.sendSyncMessage("RIL:GetRilContext", {clientId: cId})[0];
michael@0 612 if (!rilContext) {
michael@0 613 if (DEBUG) debug("Received null rilContext from chrome process.");
michael@0 614 continue;
michael@0 615 }
michael@0 616 this.rilContexts[cId].cardState = rilContext.cardState;
michael@0 617 this.rilContexts[cId].networkSelectionMode = rilContext.networkSelectionMode;
michael@0 618 this.rilContexts[cId].radioState = rilContext.detailedRadioState;
michael@0 619 this.updateIccInfo(cId, rilContext.iccInfo);
michael@0 620 this.updateConnectionInfo(rilContext.voice, this.rilContexts[cId].voiceConnectionInfo);
michael@0 621 this.updateConnectionInfo(rilContext.data, this.rilContexts[cId].dataConnectionInfo);
michael@0 622 }
michael@0 623
michael@0 624 return this.rilContexts[clientId];
michael@0 625 },
michael@0 626
michael@0 627 /**
michael@0 628 * nsIIccProvider
michael@0 629 */
michael@0 630
michael@0 631 getIccInfo: function(clientId) {
michael@0 632 let context = this.getRilContext(clientId);
michael@0 633 return context && context.iccInfo;
michael@0 634 },
michael@0 635
michael@0 636 getCardState: function(clientId) {
michael@0 637 let context = this.getRilContext(clientId);
michael@0 638 return context && context.cardState;
michael@0 639 },
michael@0 640
michael@0 641 matchMvno: function(clientId, window, mvnoType, mvnoData) {
michael@0 642 if (window == null) {
michael@0 643 throw Components.Exception("Can't get window object",
michael@0 644 Cr.NS_ERROR_UNEXPECTED);
michael@0 645 }
michael@0 646
michael@0 647 let request = Services.DOMRequest.createRequest(window);
michael@0 648 let requestId = this.getRequestId(request);
michael@0 649
michael@0 650 cpmm.sendAsyncMessage("RIL:MatchMvno", {
michael@0 651 clientId: clientId,
michael@0 652 data: {
michael@0 653 requestId: requestId,
michael@0 654 mvnoType: mvnoType,
michael@0 655 mvnoData: mvnoData
michael@0 656 }
michael@0 657 });
michael@0 658 return request;
michael@0 659 },
michael@0 660
michael@0 661 /**
michael@0 662 * nsIMobileConnectionProvider
michael@0 663 */
michael@0 664
michael@0 665 getLastKnownNetwork: function(clientId) {
michael@0 666 return cpmm.sendSyncMessage("RIL:GetLastKnownNetwork", {
michael@0 667 clientId: clientId
michael@0 668 })[0];
michael@0 669 },
michael@0 670
michael@0 671 getLastKnownHomeNetwork: function(clientId) {
michael@0 672 return cpmm.sendSyncMessage("RIL:GetLastKnownHomeNetwork", {
michael@0 673 clientId: clientId
michael@0 674 })[0];
michael@0 675 },
michael@0 676
michael@0 677 getVoiceConnectionInfo: function(clientId) {
michael@0 678 let context = this.getRilContext(clientId);
michael@0 679 return context && context.voiceConnectionInfo;
michael@0 680 },
michael@0 681
michael@0 682 getDataConnectionInfo: function(clientId) {
michael@0 683 let context = this.getRilContext(clientId);
michael@0 684 return context && context.dataConnectionInfo;
michael@0 685 },
michael@0 686
michael@0 687 getIccId: function(clientId) {
michael@0 688 let context = this.getRilContext(clientId);
michael@0 689 return context && context.iccInfo && context.iccInfo.iccid;
michael@0 690 },
michael@0 691
michael@0 692 getNetworkSelectionMode: function(clientId) {
michael@0 693 let context = this.getRilContext(clientId);
michael@0 694 return context && context.networkSelectionMode;
michael@0 695 },
michael@0 696
michael@0 697 getRadioState: function(clientId) {
michael@0 698 let context = this.getRilContext(clientId);
michael@0 699 return context && context.radioState;
michael@0 700 },
michael@0 701
michael@0 702 getSupportedNetworkTypes: function(clientId) {
michael@0 703 return cpmm.sendSyncMessage("RIL:GetSupportedNetworkTypes", {
michael@0 704 clientId: clientId
michael@0 705 })[0];
michael@0 706 },
michael@0 707
michael@0 708 /**
michael@0 709 * The networks that are currently trying to be selected (or "automatic").
michael@0 710 * This helps ensure that only one network per client is selected at a time.
michael@0 711 */
michael@0 712 _selectingNetworks: null,
michael@0 713
michael@0 714 getNetworks: function(clientId, window) {
michael@0 715 if (window == null) {
michael@0 716 throw Components.Exception("Can't get window object",
michael@0 717 Cr.NS_ERROR_UNEXPECTED);
michael@0 718 }
michael@0 719
michael@0 720 let request = Services.DOMRequest.createRequest(window);
michael@0 721 let requestId = this.getRequestId(request);
michael@0 722
michael@0 723 cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", {
michael@0 724 clientId: clientId,
michael@0 725 data: {
michael@0 726 requestId: requestId
michael@0 727 }
michael@0 728 });
michael@0 729 return request;
michael@0 730 },
michael@0 731
michael@0 732 selectNetwork: function(clientId, window, network) {
michael@0 733 if (window == null) {
michael@0 734 throw Components.Exception("Can't get window object",
michael@0 735 Cr.NS_ERROR_UNEXPECTED);
michael@0 736 }
michael@0 737
michael@0 738 if (this._selectingNetworks[clientId]) {
michael@0 739 throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
michael@0 740 }
michael@0 741
michael@0 742 if (!network) {
michael@0 743 throw new Error("Invalid network provided: " + network);
michael@0 744 }
michael@0 745
michael@0 746 if (isNaN(parseInt(network.mnc, 10))) {
michael@0 747 throw new Error("Invalid network MNC: " + network.mnc);
michael@0 748 }
michael@0 749
michael@0 750 if (isNaN(parseInt(network.mcc, 10))) {
michael@0 751 throw new Error("Invalid network MCC: " + network.mcc);
michael@0 752 }
michael@0 753
michael@0 754 let request = Services.DOMRequest.createRequest(window);
michael@0 755 let requestId = this.getRequestId(request);
michael@0 756
michael@0 757 if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL &&
michael@0 758 this.rilContexts[clientId].voiceConnectionInfo.network === network) {
michael@0 759
michael@0 760 // Already manually selected this network, so schedule
michael@0 761 // onsuccess to be fired on the next tick
michael@0 762 this.dispatchFireRequestSuccess(requestId, null);
michael@0 763 return request;
michael@0 764 }
michael@0 765
michael@0 766 this._selectingNetworks[clientId] = network;
michael@0 767
michael@0 768 cpmm.sendAsyncMessage("RIL:SelectNetwork", {
michael@0 769 clientId: clientId,
michael@0 770 data: {
michael@0 771 requestId: requestId,
michael@0 772 mnc: network.mnc,
michael@0 773 mcc: network.mcc
michael@0 774 }
michael@0 775 });
michael@0 776
michael@0 777 return request;
michael@0 778 },
michael@0 779
michael@0 780 selectNetworkAutomatically: function(clientId, window) {
michael@0 781
michael@0 782 if (window == null) {
michael@0 783 throw Components.Exception("Can't get window object",
michael@0 784 Cr.NS_ERROR_UNEXPECTED);
michael@0 785 }
michael@0 786
michael@0 787 if (this._selectingNetworks[clientId]) {
michael@0 788 throw new Error("Already selecting a network: " + this._selectingNetworks[clientId]);
michael@0 789 }
michael@0 790
michael@0 791 let request = Services.DOMRequest.createRequest(window);
michael@0 792 let requestId = this.getRequestId(request);
michael@0 793
michael@0 794 if (this.rilContexts[clientId].networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
michael@0 795 // Already using automatic selection mode, so schedule
michael@0 796 // onsuccess to be be fired on the next tick
michael@0 797 this.dispatchFireRequestSuccess(requestId, null);
michael@0 798 return request;
michael@0 799 }
michael@0 800
michael@0 801 this._selectingNetworks[clientId] = "automatic";
michael@0 802 cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", {
michael@0 803 clientId: clientId,
michael@0 804 data: {
michael@0 805 requestId: requestId
michael@0 806 }
michael@0 807 });
michael@0 808 return request;
michael@0 809 },
michael@0 810
michael@0 811 setPreferredNetworkType: function(clientId, window, type) {
michael@0 812 if (window == null) {
michael@0 813 throw Components.Exception("Can't get window object",
michael@0 814 Cr.NS_ERROR_UNEXPECTED);
michael@0 815 }
michael@0 816
michael@0 817 let request = Services.DOMRequest.createRequest(window);
michael@0 818 let requestId = this.getRequestId(request);
michael@0 819
michael@0 820 cpmm.sendAsyncMessage("RIL:SetPreferredNetworkType", {
michael@0 821 clientId: clientId,
michael@0 822 data: {
michael@0 823 requestId: requestId,
michael@0 824 type: type
michael@0 825 }
michael@0 826 });
michael@0 827 return request;
michael@0 828 },
michael@0 829
michael@0 830 getPreferredNetworkType: function(clientId, window) {
michael@0 831 if (window == null) {
michael@0 832 throw Components.Exception("Can't get window object",
michael@0 833 Cr.NS_ERROR_UNEXPECTED);
michael@0 834 }
michael@0 835
michael@0 836 let request = Services.DOMRequest.createRequest(window);
michael@0 837 let requestId = this.getRequestId(request);
michael@0 838
michael@0 839 cpmm.sendAsyncMessage("RIL:GetPreferredNetworkType", {
michael@0 840 clientId: clientId,
michael@0 841 data: {
michael@0 842 requestId: requestId
michael@0 843 }
michael@0 844 });
michael@0 845 return request;
michael@0 846 },
michael@0 847
michael@0 848 setRoamingPreference: function(clientId, window, mode) {
michael@0 849 if (window == null) {
michael@0 850 throw Components.Exception("Can't get window object",
michael@0 851 Cr.NS_ERROR_UNEXPECTED);
michael@0 852 }
michael@0 853
michael@0 854 let request = Services.DOMRequest.createRequest(window);
michael@0 855 let requestId = this.getRequestId(request);
michael@0 856
michael@0 857 if (!mode) {
michael@0 858 this.dispatchFireRequestError(requestId,
michael@0 859 RIL.GECKO_ERROR_INVALID_PARAMETER);
michael@0 860 return request;
michael@0 861 }
michael@0 862
michael@0 863 cpmm.sendAsyncMessage("RIL:SetRoamingPreference", {
michael@0 864 clientId: clientId,
michael@0 865 data: {
michael@0 866 requestId: requestId,
michael@0 867 mode: mode
michael@0 868 }
michael@0 869 });
michael@0 870 return request;
michael@0 871 },
michael@0 872
michael@0 873 getRoamingPreference: function(clientId, window) {
michael@0 874 if (window == null) {
michael@0 875 throw Components.Exception("Can't get window object",
michael@0 876 Cr.NS_ERROR_UNEXPECTED);
michael@0 877 }
michael@0 878
michael@0 879 let request = Services.DOMRequest.createRequest(window);
michael@0 880 let requestId = this.getRequestId(request);
michael@0 881
michael@0 882 cpmm.sendAsyncMessage("RIL:GetRoamingPreference", {
michael@0 883 clientId: clientId,
michael@0 884 data: {
michael@0 885 requestId: requestId
michael@0 886 }
michael@0 887 });
michael@0 888 return request;
michael@0 889 },
michael@0 890
michael@0 891 setVoicePrivacyMode: function(clientId, window, enabled) {
michael@0 892 if (window == null) {
michael@0 893 throw Components.Exception("Can't get window object",
michael@0 894 Cr.NS_ERROR_UNEXPECTED);
michael@0 895 }
michael@0 896
michael@0 897 let request = Services.DOMRequest.createRequest(window);
michael@0 898 let requestId = this.getRequestId(request);
michael@0 899
michael@0 900 cpmm.sendAsyncMessage("RIL:SetVoicePrivacyMode", {
michael@0 901 clientId: clientId,
michael@0 902 data: {
michael@0 903 requestId: requestId,
michael@0 904 enabled: enabled
michael@0 905 }
michael@0 906 });
michael@0 907 return request;
michael@0 908 },
michael@0 909
michael@0 910 getVoicePrivacyMode: function(clientId, window) {
michael@0 911 if (window == null) {
michael@0 912 throw Components.Exception("Can't get window object",
michael@0 913 Cr.NS_ERROR_UNEXPECTED);
michael@0 914 }
michael@0 915
michael@0 916 let request = Services.DOMRequest.createRequest(window);
michael@0 917 let requestId = this.getRequestId(request);
michael@0 918
michael@0 919 cpmm.sendAsyncMessage("RIL:GetVoicePrivacyMode", {
michael@0 920 clientId: clientId,
michael@0 921 data: {
michael@0 922 requestId: requestId
michael@0 923 }
michael@0 924 });
michael@0 925 return request;
michael@0 926 },
michael@0 927
michael@0 928 getCardLockState: function(clientId, window, lockType) {
michael@0 929 if (window == null) {
michael@0 930 throw Components.Exception("Can't get window object",
michael@0 931 Cr.NS_ERROR_UNEXPECTED);
michael@0 932 }
michael@0 933 let request = Services.DOMRequest.createRequest(window);
michael@0 934 let requestId = this.getRequestId(request);
michael@0 935 this._windowsMap[requestId] = window;
michael@0 936
michael@0 937 cpmm.sendAsyncMessage("RIL:GetCardLockState", {
michael@0 938 clientId: clientId,
michael@0 939 data: {
michael@0 940 lockType: lockType,
michael@0 941 requestId: requestId
michael@0 942 }
michael@0 943 });
michael@0 944 return request;
michael@0 945 },
michael@0 946
michael@0 947 unlockCardLock: function(clientId, window, info) {
michael@0 948 if (window == null) {
michael@0 949 throw Components.Exception("Can't get window object",
michael@0 950 Cr.NS_ERROR_UNEXPECTED);
michael@0 951 }
michael@0 952 let request = Services.DOMRequest.createRequest(window);
michael@0 953 info.requestId = this.getRequestId(request);
michael@0 954 this._windowsMap[info.requestId] = window;
michael@0 955
michael@0 956 cpmm.sendAsyncMessage("RIL:UnlockCardLock", {
michael@0 957 clientId: clientId,
michael@0 958 data: info
michael@0 959 });
michael@0 960 return request;
michael@0 961 },
michael@0 962
michael@0 963 setCardLock: function(clientId, window, info) {
michael@0 964 if (window == null) {
michael@0 965 throw Components.Exception("Can't get window object",
michael@0 966 Cr.NS_ERROR_UNEXPECTED);
michael@0 967 }
michael@0 968 let request = Services.DOMRequest.createRequest(window);
michael@0 969 info.requestId = this.getRequestId(request);
michael@0 970 this._windowsMap[info.requestId] = window;
michael@0 971
michael@0 972 cpmm.sendAsyncMessage("RIL:SetCardLock", {
michael@0 973 clientId: clientId,
michael@0 974 data: info
michael@0 975 });
michael@0 976 return request;
michael@0 977 },
michael@0 978
michael@0 979 getCardLockRetryCount: function(clientId, window, lockType) {
michael@0 980 if (window == null) {
michael@0 981 throw Components.Exception("Can't get window object",
michael@0 982 Cr.NS_ERROR_UNEXPECTED);
michael@0 983 }
michael@0 984 let request = Services.DOMRequest.createRequest(window);
michael@0 985 let requestId = this.getRequestId(request);
michael@0 986 cpmm.sendAsyncMessage("RIL:GetCardLockRetryCount", {
michael@0 987 clientId: clientId,
michael@0 988 data: {
michael@0 989 lockType: lockType,
michael@0 990 requestId: requestId
michael@0 991 }
michael@0 992 });
michael@0 993 return request;
michael@0 994 },
michael@0 995
michael@0 996 sendMMI: function(clientId, window, mmi) {
michael@0 997 if (DEBUG) debug("Sending MMI " + mmi);
michael@0 998 if (!window) {
michael@0 999 throw Components.Exception("Can't get window object",
michael@0 1000 Cr.NS_ERROR_UNEXPECTED);
michael@0 1001 }
michael@0 1002 let request = Services.DOMRequest.createRequest(window);
michael@0 1003 let requestId = this.getRequestId(request);
michael@0 1004 // We need to save the global window to get the proper MMIError
michael@0 1005 // constructor once we get the reply from the parent process.
michael@0 1006 this._windowsMap[requestId] = window;
michael@0 1007
michael@0 1008 cpmm.sendAsyncMessage("RIL:SendMMI", {
michael@0 1009 clientId: clientId,
michael@0 1010 data: {
michael@0 1011 mmi: mmi,
michael@0 1012 requestId: requestId
michael@0 1013 }
michael@0 1014 });
michael@0 1015 return request;
michael@0 1016 },
michael@0 1017
michael@0 1018 cancelMMI: function(clientId, window) {
michael@0 1019 if (DEBUG) debug("Cancel MMI");
michael@0 1020 if (!window) {
michael@0 1021 throw Components.Exception("Can't get window object",
michael@0 1022 Cr.NS_ERROR_UNEXPECTED);
michael@0 1023 }
michael@0 1024 let request = Services.DOMRequest.createRequest(window);
michael@0 1025 let requestId = this.getRequestId(request);
michael@0 1026 cpmm.sendAsyncMessage("RIL:CancelMMI", {
michael@0 1027 clientId: clientId,
michael@0 1028 data: {
michael@0 1029 requestId: requestId
michael@0 1030 }
michael@0 1031 });
michael@0 1032 return request;
michael@0 1033 },
michael@0 1034
michael@0 1035 sendStkResponse: function(clientId, window, command, response) {
michael@0 1036 if (window == null) {
michael@0 1037 throw Components.Exception("Can't get window object",
michael@0 1038 Cr.NS_ERROR_UNEXPECTED);
michael@0 1039 }
michael@0 1040 response.command = command;
michael@0 1041 cpmm.sendAsyncMessage("RIL:SendStkResponse", {
michael@0 1042 clientId: clientId,
michael@0 1043 data: response
michael@0 1044 });
michael@0 1045 },
michael@0 1046
michael@0 1047 sendStkMenuSelection: function(clientId, window, itemIdentifier,
michael@0 1048 helpRequested) {
michael@0 1049 if (window == null) {
michael@0 1050 throw Components.Exception("Can't get window object",
michael@0 1051 Cr.NS_ERROR_UNEXPECTED);
michael@0 1052 }
michael@0 1053 cpmm.sendAsyncMessage("RIL:SendStkMenuSelection", {
michael@0 1054 clientId: clientId,
michael@0 1055 data: {
michael@0 1056 itemIdentifier: itemIdentifier,
michael@0 1057 helpRequested: helpRequested
michael@0 1058 }
michael@0 1059 });
michael@0 1060 },
michael@0 1061
michael@0 1062 sendStkTimerExpiration: function(clientId, window, timer) {
michael@0 1063 if (window == null) {
michael@0 1064 throw Components.Exception("Can't get window object",
michael@0 1065 Cr.NS_ERROR_UNEXPECTED);
michael@0 1066 }
michael@0 1067 cpmm.sendAsyncMessage("RIL:SendStkTimerExpiration", {
michael@0 1068 clientId: clientId,
michael@0 1069 data: {
michael@0 1070 timer: timer
michael@0 1071 }
michael@0 1072 });
michael@0 1073 },
michael@0 1074
michael@0 1075 sendStkEventDownload: function(clientId, window, event) {
michael@0 1076 if (window == null) {
michael@0 1077 throw Components.Exception("Can't get window object",
michael@0 1078 Cr.NS_ERROR_UNEXPECTED);
michael@0 1079 }
michael@0 1080 cpmm.sendAsyncMessage("RIL:SendStkEventDownload", {
michael@0 1081 clientId: clientId,
michael@0 1082 data: {
michael@0 1083 event: event
michael@0 1084 }
michael@0 1085 });
michael@0 1086 },
michael@0 1087
michael@0 1088 iccOpenChannel: function(clientId, window, aid) {
michael@0 1089 if (window == null) {
michael@0 1090 throw Components.Exception("Can't get window object",
michael@0 1091 Cr.NS_ERROR_UNEXPECTED);
michael@0 1092 }
michael@0 1093
michael@0 1094 let request = Services.DOMRequest.createRequest(window);
michael@0 1095 let requestId = this.getRequestId(request);
michael@0 1096
michael@0 1097 cpmm.sendAsyncMessage("RIL:IccOpenChannel", {
michael@0 1098 clientId: clientId,
michael@0 1099 data: {
michael@0 1100 requestId: requestId,
michael@0 1101 aid: aid
michael@0 1102 }
michael@0 1103 });
michael@0 1104 return request;
michael@0 1105 },
michael@0 1106
michael@0 1107 iccExchangeAPDU: function(clientId, window, channel, apdu) {
michael@0 1108 if (window == null) {
michael@0 1109 throw Components.Exception("Can't get window object",
michael@0 1110 Cr.NS_ERROR_UNEXPECTED);
michael@0 1111 }
michael@0 1112
michael@0 1113 let request = Services.DOMRequest.createRequest(window);
michael@0 1114 let requestId = this.getRequestId(request);
michael@0 1115
michael@0 1116 //Potentially you need serialization here and can't pass the jsval through
michael@0 1117 cpmm.sendAsyncMessage("RIL:IccExchangeAPDU", {
michael@0 1118 clientId: clientId,
michael@0 1119 data: {
michael@0 1120 requestId: requestId,
michael@0 1121 channel: channel,
michael@0 1122 apdu: apdu
michael@0 1123 }
michael@0 1124 });
michael@0 1125 return request;
michael@0 1126 },
michael@0 1127
michael@0 1128 iccCloseChannel: function(clientId, window, channel) {
michael@0 1129 if (window == null) {
michael@0 1130 throw Components.Exception("Can't get window object",
michael@0 1131 Cr.NS_ERROR_UNEXPECTED);
michael@0 1132 }
michael@0 1133
michael@0 1134 let request = Services.DOMRequest.createRequest(window);
michael@0 1135 let requestId = this.getRequestId(request);
michael@0 1136
michael@0 1137 cpmm.sendAsyncMessage("RIL:IccCloseChannel", {
michael@0 1138 clientId: clientId,
michael@0 1139 data: {
michael@0 1140 requestId: requestId,
michael@0 1141 channel: channel
michael@0 1142 }
michael@0 1143 });
michael@0 1144 return request;
michael@0 1145 },
michael@0 1146
michael@0 1147 readContacts: function(clientId, window, contactType) {
michael@0 1148 if (window == null) {
michael@0 1149 throw Components.Exception("Can't get window object",
michael@0 1150 Cr.NS_ERROR_UNEXPECTED);
michael@0 1151 }
michael@0 1152
michael@0 1153 let request = Services.DOMRequest.createRequest(window);
michael@0 1154 let requestId = this.getRequestId(request);
michael@0 1155 this._windowsMap[requestId] = window;
michael@0 1156
michael@0 1157 cpmm.sendAsyncMessage("RIL:ReadIccContacts", {
michael@0 1158 clientId: clientId,
michael@0 1159 data: {
michael@0 1160 requestId: requestId,
michael@0 1161 contactType: contactType
michael@0 1162 }
michael@0 1163 });
michael@0 1164 return request;
michael@0 1165 },
michael@0 1166
michael@0 1167 updateContact: function(clientId, window, contactType, contact, pin2) {
michael@0 1168 if (window == null) {
michael@0 1169 throw Components.Exception("Can't get window object",
michael@0 1170 Cr.NS_ERROR_UNEXPECTED);
michael@0 1171 }
michael@0 1172
michael@0 1173 let request = Services.DOMRequest.createRequest(window);
michael@0 1174 let requestId = this.getRequestId(request);
michael@0 1175 this._windowsMap[requestId] = window;
michael@0 1176
michael@0 1177 // Parsing nsDOMContact to Icc Contact format
michael@0 1178 let iccContact = {};
michael@0 1179
michael@0 1180 if (Array.isArray(contact.name) && contact.name[0]) {
michael@0 1181 iccContact.alphaId = contact.name[0];
michael@0 1182 }
michael@0 1183
michael@0 1184 if (Array.isArray(contact.tel)) {
michael@0 1185 iccContact.number = contact.tel[0] && contact.tel[0].value;
michael@0 1186 let telArray = contact.tel.slice(1);
michael@0 1187 let length = telArray.length;
michael@0 1188 if (length > 0) {
michael@0 1189 iccContact.anr = [];
michael@0 1190 }
michael@0 1191 for (let i = 0; i < telArray.length; i++) {
michael@0 1192 iccContact.anr.push(telArray[i].value);
michael@0 1193 }
michael@0 1194 }
michael@0 1195
michael@0 1196 if (Array.isArray(contact.email) && contact.email[0]) {
michael@0 1197 iccContact.email = contact.email[0].value;
michael@0 1198 }
michael@0 1199
michael@0 1200 iccContact.contactId = contact.id;
michael@0 1201
michael@0 1202 cpmm.sendAsyncMessage("RIL:UpdateIccContact", {
michael@0 1203 clientId: clientId,
michael@0 1204 data: {
michael@0 1205 requestId: requestId,
michael@0 1206 contactType: contactType,
michael@0 1207 contact: iccContact,
michael@0 1208 pin2: pin2
michael@0 1209 }
michael@0 1210 });
michael@0 1211
michael@0 1212 return request;
michael@0 1213 },
michael@0 1214
michael@0 1215 getCallForwardingOption: function(clientId, window, reason) {
michael@0 1216 if (window == null) {
michael@0 1217 throw Components.Exception("Can't get window object",
michael@0 1218 Cr.NS_ERROR_UNEXPECTED);
michael@0 1219 }
michael@0 1220 let request = Services.DOMRequest.createRequest(window);
michael@0 1221 let requestId = this.getRequestId(request);
michael@0 1222
michael@0 1223 if (!this._isValidCFReason(reason)){
michael@0 1224 this.dispatchFireRequestError(requestId,
michael@0 1225 RIL.GECKO_ERROR_INVALID_PARAMETER);
michael@0 1226 return request;
michael@0 1227 }
michael@0 1228
michael@0 1229 cpmm.sendAsyncMessage("RIL:GetCallForwardingOptions", {
michael@0 1230 clientId: clientId,
michael@0 1231 data: {
michael@0 1232 requestId: requestId,
michael@0 1233 reason: reason
michael@0 1234 }
michael@0 1235 });
michael@0 1236
michael@0 1237 return request;
michael@0 1238 },
michael@0 1239
michael@0 1240 setCallForwardingOption: function(clientId, window, cfInfo) {
michael@0 1241 if (window == null) {
michael@0 1242 throw Components.Exception("Can't get window object",
michael@0 1243 Cr.NS_ERROR_UNEXPECTED);
michael@0 1244 }
michael@0 1245 let request = Services.DOMRequest.createRequest(window);
michael@0 1246 let requestId = this.getRequestId(request);
michael@0 1247
michael@0 1248 if (!cfInfo ||
michael@0 1249 !this._isValidCFReason(cfInfo.reason) ||
michael@0 1250 !this._isValidCFAction(cfInfo.action)){
michael@0 1251 this.dispatchFireRequestError(requestId,
michael@0 1252 RIL.GECKO_ERROR_INVALID_PARAMETER);
michael@0 1253 return request;
michael@0 1254 }
michael@0 1255
michael@0 1256 cpmm.sendAsyncMessage("RIL:SetCallForwardingOptions", {
michael@0 1257 clientId: clientId,
michael@0 1258 data: {
michael@0 1259 requestId: requestId,
michael@0 1260 active: cfInfo.active,
michael@0 1261 action: cfInfo.action,
michael@0 1262 reason: cfInfo.reason,
michael@0 1263 number: cfInfo.number,
michael@0 1264 timeSeconds: cfInfo.timeSeconds
michael@0 1265 }
michael@0 1266 });
michael@0 1267
michael@0 1268 return request;
michael@0 1269 },
michael@0 1270
michael@0 1271 getCallBarringOption: function(clientId, window, option) {
michael@0 1272 if (window == null) {
michael@0 1273 throw Components.Exception("Can't get window object",
michael@0 1274 Cr.NS_ERROR_UNEXPECTED);
michael@0 1275 }
michael@0 1276 let request = Services.DOMRequest.createRequest(window);
michael@0 1277 let requestId = this.getRequestId(request);
michael@0 1278
michael@0 1279 if (DEBUG) debug("getCallBarringOption: " + JSON.stringify(option));
michael@0 1280 if (!this._isValidCallBarringOptions(option)) {
michael@0 1281 this.dispatchFireRequestError(requestId,
michael@0 1282 RIL.GECKO_ERROR_INVALID_PARAMETER);
michael@0 1283 return request;
michael@0 1284 }
michael@0 1285
michael@0 1286 cpmm.sendAsyncMessage("RIL:GetCallBarringOptions", {
michael@0 1287 clientId: clientId,
michael@0 1288 data: {
michael@0 1289 requestId: requestId,
michael@0 1290 program: option.program,
michael@0 1291 password: option.password,
michael@0 1292 serviceClass: option.serviceClass
michael@0 1293 }
michael@0 1294 });
michael@0 1295 return request;
michael@0 1296 },
michael@0 1297
michael@0 1298 setCallBarringOption: function(clientId, window, option) {
michael@0 1299 if (window == null) {
michael@0 1300 throw Components.Exception("Can't get window object",
michael@0 1301 Cr.NS_ERROR_UNEXPECTED);
michael@0 1302 }
michael@0 1303 let request = Services.DOMRequest.createRequest(window);
michael@0 1304 let requestId = this.getRequestId(request);
michael@0 1305
michael@0 1306 if (DEBUG) debug("setCallBarringOption: " + JSON.stringify(option));
michael@0 1307 if (!this._isValidCallBarringOptions(option, true)) {
michael@0 1308 this.dispatchFireRequestError(requestId,
michael@0 1309 RIL.GECKO_ERROR_INVALID_PARAMETER);
michael@0 1310 return request;
michael@0 1311 }
michael@0 1312
michael@0 1313 cpmm.sendAsyncMessage("RIL:SetCallBarringOptions", {
michael@0 1314 clientId: clientId,
michael@0 1315 data: {
michael@0 1316 requestId: requestId,
michael@0 1317 program: option.program,
michael@0 1318 enabled: option.enabled,
michael@0 1319 password: option.password,
michael@0 1320 serviceClass: option.serviceClass
michael@0 1321 }
michael@0 1322 });
michael@0 1323 return request;
michael@0 1324 },
michael@0 1325
michael@0 1326 changeCallBarringPassword: function(clientId, window, info) {
michael@0 1327 if (window == null) {
michael@0 1328 throw Components.Exception("Can't get window object",
michael@0 1329 Cr.NS_ERROR_UNEXPECTED);
michael@0 1330 }
michael@0 1331 let request = Services.DOMRequest.createRequest(window);
michael@0 1332 let requestId = this.getRequestId(request);
michael@0 1333
michael@0 1334 // Checking valid PIN for supplementary services. See TS.22.004 clause 5.2.
michael@0 1335 if (info.pin == null || !info.pin.match(/^\d{4}$/) ||
michael@0 1336 info.newPin == null || !info.newPin.match(/^\d{4}$/)) {
michael@0 1337 this.dispatchFireRequestError(requestId, "InvalidPassword");
michael@0 1338 return request;
michael@0 1339 }
michael@0 1340
michael@0 1341 if (DEBUG) debug("changeCallBarringPassword: " + JSON.stringify(info));
michael@0 1342 info.requestId = requestId;
michael@0 1343 cpmm.sendAsyncMessage("RIL:ChangeCallBarringPassword", {
michael@0 1344 clientId: clientId,
michael@0 1345 data: info
michael@0 1346 });
michael@0 1347
michael@0 1348 return request;
michael@0 1349 },
michael@0 1350
michael@0 1351 getCallWaitingOption: function(clientId, window) {
michael@0 1352 if (window == null) {
michael@0 1353 throw Components.Exception("Can't get window object",
michael@0 1354 Cr.NS_ERROR_UNEXPECTED);
michael@0 1355 }
michael@0 1356 let request = Services.DOMRequest.createRequest(window);
michael@0 1357 let requestId = this.getRequestId(request);
michael@0 1358
michael@0 1359 cpmm.sendAsyncMessage("RIL:GetCallWaitingOptions", {
michael@0 1360 clientId: clientId,
michael@0 1361 data: {
michael@0 1362 requestId: requestId
michael@0 1363 }
michael@0 1364 });
michael@0 1365
michael@0 1366 return request;
michael@0 1367 },
michael@0 1368
michael@0 1369 setCallWaitingOption: function(clientId, window, enabled) {
michael@0 1370 if (window == null) {
michael@0 1371 throw Components.Exception("Can't get window object",
michael@0 1372 Cr.NS_ERROR_UNEXPECTED);
michael@0 1373 }
michael@0 1374 let request = Services.DOMRequest.createRequest(window);
michael@0 1375 let requestId = this.getRequestId(request);
michael@0 1376
michael@0 1377 cpmm.sendAsyncMessage("RIL:SetCallWaitingOptions", {
michael@0 1378 clientId: clientId,
michael@0 1379 data: {
michael@0 1380 requestId: requestId,
michael@0 1381 enabled: enabled
michael@0 1382 }
michael@0 1383 });
michael@0 1384
michael@0 1385 return request;
michael@0 1386 },
michael@0 1387
michael@0 1388 getCallingLineIdRestriction: function(clientId, window) {
michael@0 1389 if (window == null) {
michael@0 1390 throw Components.Exception("Can't get window object",
michael@0 1391 Cr.NS_ERROR_UNEXPECTED);
michael@0 1392 }
michael@0 1393 let request = Services.DOMRequest.createRequest(window);
michael@0 1394 let requestId = this.getRequestId(request);
michael@0 1395
michael@0 1396 cpmm.sendAsyncMessage("RIL:GetCallingLineIdRestriction", {
michael@0 1397 clientId: clientId,
michael@0 1398 data: {
michael@0 1399 requestId: requestId
michael@0 1400 }
michael@0 1401 });
michael@0 1402
michael@0 1403 return request;
michael@0 1404 },
michael@0 1405
michael@0 1406 setCallingLineIdRestriction: function(clientId, window, clirMode) {
michael@0 1407
michael@0 1408 if (window == null) {
michael@0 1409 throw Components.Exception("Can't get window object",
michael@0 1410 Cr.NS_ERROR_UNEXPECTED);
michael@0 1411 }
michael@0 1412 let request = Services.DOMRequest.createRequest(window);
michael@0 1413 let requestId = this.getRequestId(request);
michael@0 1414
michael@0 1415 cpmm.sendAsyncMessage("RIL:SetCallingLineIdRestriction", {
michael@0 1416 clientId: clientId,
michael@0 1417 data: {
michael@0 1418 requestId: requestId,
michael@0 1419 clirMode: clirMode
michael@0 1420 }
michael@0 1421 });
michael@0 1422
michael@0 1423 return request;
michael@0 1424 },
michael@0 1425
michael@0 1426 exitEmergencyCbMode: function(clientId, window) {
michael@0 1427 if (window == null) {
michael@0 1428 throw Components.Exception("Can't get window object",
michael@0 1429 Cr.NS_ERROR_UNEXPECTED);
michael@0 1430 }
michael@0 1431 let request = Services.DOMRequest.createRequest(window);
michael@0 1432 let requestId = this.getRequestId(request);
michael@0 1433
michael@0 1434 cpmm.sendAsyncMessage("RIL:ExitEmergencyCbMode", {
michael@0 1435 clientId: clientId,
michael@0 1436 data: {
michael@0 1437 requestId: requestId,
michael@0 1438 }
michael@0 1439 });
michael@0 1440
michael@0 1441 return request;
michael@0 1442 },
michael@0 1443
michael@0 1444 setRadioEnabled: function(clientId, window, enabled) {
michael@0 1445 if (window == null) {
michael@0 1446 throw Components.Exception("Can't get window object",
michael@0 1447 Cr.NS_ERROR_UNEXPECTED);
michael@0 1448 }
michael@0 1449 let request = Services.DOMRequest.createRequest(window);
michael@0 1450 let requestId = this.getRequestId(request);
michael@0 1451
michael@0 1452 cpmm.sendAsyncMessage("RIL:SetRadioEnabled", {
michael@0 1453 clientId: clientId,
michael@0 1454 data: {
michael@0 1455 requestId: requestId,
michael@0 1456 enabled: enabled,
michael@0 1457 }
michael@0 1458 });
michael@0 1459
michael@0 1460 return request;
michael@0 1461 },
michael@0 1462
michael@0 1463 _mobileConnectionListeners: null,
michael@0 1464 _cellBroadcastListeners: null,
michael@0 1465 _voicemailListeners: null,
michael@0 1466 _iccListeners: null,
michael@0 1467
michael@0 1468 voicemailInfos: null,
michael@0 1469 voicemailStatuses: null,
michael@0 1470
michael@0 1471 voicemailDefaultServiceId: 0,
michael@0 1472 getVoicemailDefaultServiceId: function() {
michael@0 1473 let id = Services.prefs.getIntPref(kPrefVoicemailDefaultServiceId);
michael@0 1474
michael@0 1475 if (id >= gNumRadioInterfaces || id < 0) {
michael@0 1476 id = 0;
michael@0 1477 }
michael@0 1478
michael@0 1479 return id;
michael@0 1480 },
michael@0 1481
michael@0 1482 getVoicemailInfo: function(clientId) {
michael@0 1483 // Get voicemail infomation by IPC only on first time.
michael@0 1484 this.getVoicemailInfo = function getVoicemailInfo(clientId) {
michael@0 1485 return this.voicemailInfos[clientId];
michael@0 1486 };
michael@0 1487
michael@0 1488 for (let cId = 0; cId < gNumRadioInterfaces; cId++) {
michael@0 1489 let voicemailInfo =
michael@0 1490 cpmm.sendSyncMessage("RIL:GetVoicemailInfo", {clientId: cId})[0];
michael@0 1491 if (voicemailInfo) {
michael@0 1492 this.updateInfo(voicemailInfo, this.voicemailInfos[cId]);
michael@0 1493 }
michael@0 1494 }
michael@0 1495
michael@0 1496 return this.voicemailInfos[clientId];
michael@0 1497 },
michael@0 1498
michael@0 1499 getVoicemailNumber: function(clientId) {
michael@0 1500 return this.getVoicemailInfo(clientId).number;
michael@0 1501 },
michael@0 1502
michael@0 1503 getVoicemailDisplayName: function(clientId) {
michael@0 1504 return this.getVoicemailInfo(clientId).displayName;
michael@0 1505 },
michael@0 1506
michael@0 1507 getVoicemailStatus: function(clientId) {
michael@0 1508 return this.voicemailStatuses[clientId];
michael@0 1509 },
michael@0 1510
michael@0 1511 registerListener: function(listenerType, clientId, listener) {
michael@0 1512 if (!this[listenerType]) {
michael@0 1513 return;
michael@0 1514 }
michael@0 1515 let listeners = this[listenerType][clientId];
michael@0 1516 if (!listeners) {
michael@0 1517 listeners = this[listenerType][clientId] = [];
michael@0 1518 }
michael@0 1519
michael@0 1520 if (listeners.indexOf(listener) != -1) {
michael@0 1521 throw new Error("Already registered this listener!");
michael@0 1522 }
michael@0 1523
michael@0 1524 listeners.push(listener);
michael@0 1525 if (DEBUG) debug("Registered " + listenerType + " listener: " + listener);
michael@0 1526 },
michael@0 1527
michael@0 1528 unregisterListener: function(listenerType, clientId, listener) {
michael@0 1529 if (!this[listenerType]) {
michael@0 1530 return;
michael@0 1531 }
michael@0 1532 let listeners = this[listenerType][clientId];
michael@0 1533 if (!listeners) {
michael@0 1534 return;
michael@0 1535 }
michael@0 1536
michael@0 1537 let index = listeners.indexOf(listener);
michael@0 1538 if (index != -1) {
michael@0 1539 listeners.splice(index, 1);
michael@0 1540 if (DEBUG) debug("Unregistered listener: " + listener);
michael@0 1541 }
michael@0 1542 },
michael@0 1543
michael@0 1544 registerMobileConnectionMsg: function(clientId, listener) {
michael@0 1545 if (DEBUG) debug("Registering for mobile connection related messages");
michael@0 1546 this.registerListener("_mobileConnectionListeners", clientId, listener);
michael@0 1547 cpmm.sendAsyncMessage("RIL:RegisterMobileConnectionMsg");
michael@0 1548 },
michael@0 1549
michael@0 1550 unregisterMobileConnectionMsg: function(clientId, listener) {
michael@0 1551 this.unregisterListener("_mobileConnectionListeners", clientId, listener);
michael@0 1552 },
michael@0 1553
michael@0 1554 registerVoicemailMsg: function(listener) {
michael@0 1555 if (DEBUG) debug("Registering for voicemail-related messages");
michael@0 1556 // To follow the listener registration scheme, we add a dummy clientId 0.
michael@0 1557 // All voicemail events are routed to listener for client id 0.
michael@0 1558 // See |handleVoicemailNotification|.
michael@0 1559 this.registerListener("_voicemailListeners", 0, listener);
michael@0 1560 cpmm.sendAsyncMessage("RIL:RegisterVoicemailMsg");
michael@0 1561 },
michael@0 1562
michael@0 1563 unregisterVoicemailMsg: function(listener) {
michael@0 1564 // To follow the listener unregistration scheme, we add a dummy clientId 0.
michael@0 1565 // All voicemail events are routed to listener for client id 0.
michael@0 1566 // See |handleVoicemailNotification|.
michael@0 1567 this.unregisterListener("_voicemailListeners", 0, listener);
michael@0 1568 },
michael@0 1569
michael@0 1570 registerCellBroadcastMsg: function(listener) {
michael@0 1571 if (DEBUG) debug("Registering for Cell Broadcast related messages");
michael@0 1572 //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
michael@0 1573 this.registerListener("_cellBroadcastListeners", 0, listener);
michael@0 1574 cpmm.sendAsyncMessage("RIL:RegisterCellBroadcastMsg");
michael@0 1575 },
michael@0 1576
michael@0 1577 unregisterCellBroadcastMsg: function(listener) {
michael@0 1578 //TODO: Bug 921326 - Cellbroadcast API: support multiple sim cards
michael@0 1579 this.unregisterListener("_cellBroadcastListeners", 0, listener);
michael@0 1580 },
michael@0 1581
michael@0 1582 registerIccMsg: function(clientId, listener) {
michael@0 1583 if (DEBUG) debug("Registering for ICC related messages");
michael@0 1584 this.registerListener("_iccListeners", clientId, listener);
michael@0 1585 cpmm.sendAsyncMessage("RIL:RegisterIccMsg");
michael@0 1586 },
michael@0 1587
michael@0 1588 unregisterIccMsg: function(clientId, listener) {
michael@0 1589 this.unregisterListener("_iccListeners", clientId, listener);
michael@0 1590 },
michael@0 1591
michael@0 1592 // nsIObserver
michael@0 1593
michael@0 1594 observe: function(subject, topic, data) {
michael@0 1595 switch (topic) {
michael@0 1596 case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
michael@0 1597 if (data == kPrefRilDebuggingEnabled) {
michael@0 1598 this.updateDebugFlag();
michael@0 1599 } else if (data == kPrefVoicemailDefaultServiceId) {
michael@0 1600 this.voicemailDefaultServiceId = this.getVoicemailDefaultServiceId();
michael@0 1601 }
michael@0 1602 break;
michael@0 1603
michael@0 1604 case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
michael@0 1605 this.destroyDOMRequestHelper();
michael@0 1606 Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
michael@0 1607 break;
michael@0 1608 }
michael@0 1609 },
michael@0 1610
michael@0 1611 // nsIMessageListener
michael@0 1612
michael@0 1613 fireRequestSuccess: function(requestId, result) {
michael@0 1614 let request = this.takeRequest(requestId);
michael@0 1615 if (!request) {
michael@0 1616 if (DEBUG) {
michael@0 1617 debug("not firing success for id: " + requestId +
michael@0 1618 ", result: " + JSON.stringify(result));
michael@0 1619 }
michael@0 1620 return;
michael@0 1621 }
michael@0 1622
michael@0 1623 if (DEBUG) {
michael@0 1624 debug("fire request success, id: " + requestId +
michael@0 1625 ", result: " + JSON.stringify(result));
michael@0 1626 }
michael@0 1627 Services.DOMRequest.fireSuccess(request, result);
michael@0 1628 },
michael@0 1629
michael@0 1630 dispatchFireRequestSuccess: function(requestId, result) {
michael@0 1631 let currentThread = Services.tm.currentThread;
michael@0 1632
michael@0 1633 currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result),
michael@0 1634 Ci.nsIThread.DISPATCH_NORMAL);
michael@0 1635 },
michael@0 1636
michael@0 1637 fireRequestError: function(requestId, error) {
michael@0 1638 let request = this.takeRequest(requestId);
michael@0 1639 if (!request) {
michael@0 1640 if (DEBUG) {
michael@0 1641 debug("not firing error for id: " + requestId +
michael@0 1642 ", error: " + JSON.stringify(error));
michael@0 1643 }
michael@0 1644 return;
michael@0 1645 }
michael@0 1646
michael@0 1647 if (DEBUG) {
michael@0 1648 debug("fire request error, id: " + requestId +
michael@0 1649 ", result: " + JSON.stringify(error));
michael@0 1650 }
michael@0 1651 Services.DOMRequest.fireError(request, error);
michael@0 1652 },
michael@0 1653
michael@0 1654 dispatchFireRequestError: function(requestId, error) {
michael@0 1655 let currentThread = Services.tm.currentThread;
michael@0 1656
michael@0 1657 currentThread.dispatch(this.fireRequestError.bind(this, requestId, error),
michael@0 1658 Ci.nsIThread.DISPATCH_NORMAL);
michael@0 1659 },
michael@0 1660
michael@0 1661 fireRequestDetailedError: function(requestId, detailedError) {
michael@0 1662 let request = this.takeRequest(requestId);
michael@0 1663 if (!request) {
michael@0 1664 if (DEBUG) {
michael@0 1665 debug("not firing detailed error for id: " + requestId +
michael@0 1666 ", detailedError: " + JSON.stringify(detailedError));
michael@0 1667 }
michael@0 1668 return;
michael@0 1669 }
michael@0 1670
michael@0 1671 Services.DOMRequest.fireDetailedError(request, detailedError);
michael@0 1672 },
michael@0 1673
michael@0 1674 receiveMessage: function(msg) {
michael@0 1675 let request;
michael@0 1676 if (DEBUG) {
michael@0 1677 debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
michael@0 1678 }
michael@0 1679
michael@0 1680 let data = msg.json.data;
michael@0 1681 let clientId = msg.json.clientId;
michael@0 1682 switch (msg.name) {
michael@0 1683 case "RIL:CardStateChanged":
michael@0 1684 if (this.rilContexts[clientId].cardState != data.cardState) {
michael@0 1685 this.rilContexts[clientId].cardState = data.cardState;
michael@0 1686 this._deliverEvent(clientId,
michael@0 1687 "_iccListeners",
michael@0 1688 "notifyCardStateChanged",
michael@0 1689 null);
michael@0 1690 }
michael@0 1691 break;
michael@0 1692 case "RIL:IccInfoChanged":
michael@0 1693 this.updateIccInfo(clientId, data);
michael@0 1694 this._deliverEvent(clientId,
michael@0 1695 "_iccListeners",
michael@0 1696 "notifyIccInfoChanged",
michael@0 1697 null);
michael@0 1698 break;
michael@0 1699 case "RIL:VoiceInfoChanged":
michael@0 1700 this.updateConnectionInfo(data,
michael@0 1701 this.rilContexts[clientId].voiceConnectionInfo);
michael@0 1702 this._deliverEvent(clientId,
michael@0 1703 "_mobileConnectionListeners",
michael@0 1704 "notifyVoiceChanged",
michael@0 1705 null);
michael@0 1706 break;
michael@0 1707 case "RIL:DataInfoChanged":
michael@0 1708 this.updateConnectionInfo(data,
michael@0 1709 this.rilContexts[clientId].dataConnectionInfo);
michael@0 1710 this._deliverEvent(clientId,
michael@0 1711 "_mobileConnectionListeners",
michael@0 1712 "notifyDataChanged",
michael@0 1713 null);
michael@0 1714 break;
michael@0 1715 case "RIL:OtaStatusChanged":
michael@0 1716 this._deliverEvent(clientId,
michael@0 1717 "_mobileConnectionListeners",
michael@0 1718 "notifyOtaStatusChanged",
michael@0 1719 [data]);
michael@0 1720 break;
michael@0 1721 case "RIL:GetAvailableNetworks":
michael@0 1722 this.handleGetAvailableNetworks(data);
michael@0 1723 break;
michael@0 1724 case "RIL:NetworkSelectionModeChanged":
michael@0 1725 this.rilContexts[clientId].networkSelectionMode = data.mode;
michael@0 1726 break;
michael@0 1727 case "RIL:SelectNetwork":
michael@0 1728 this.handleSelectNetwork(clientId, data,
michael@0 1729 RIL.GECKO_NETWORK_SELECTION_MANUAL);
michael@0 1730 break;
michael@0 1731 case "RIL:SelectNetworkAuto":
michael@0 1732 this.handleSelectNetwork(clientId, data,
michael@0 1733 RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
michael@0 1734 break;
michael@0 1735 case "RIL:SetPreferredNetworkType":
michael@0 1736 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1737 break;
michael@0 1738 case "RIL:GetPreferredNetworkType":
michael@0 1739 this.handleSimpleRequest(data.requestId, data.errorMsg, data.type);
michael@0 1740 break;
michael@0 1741 case "RIL:VoicemailNotification":
michael@0 1742 this.handleVoicemailNotification(clientId, data);
michael@0 1743 break;
michael@0 1744 case "RIL:VoicemailInfoChanged":
michael@0 1745 this.updateInfo(data, this.voicemailInfos[clientId]);
michael@0 1746 break;
michael@0 1747 case "RIL:CardLockResult": {
michael@0 1748 let requestId = data.requestId;
michael@0 1749 let requestWindow = this._windowsMap[requestId];
michael@0 1750 delete this._windowsMap[requestId];
michael@0 1751
michael@0 1752 if (data.success) {
michael@0 1753 let result = new MobileIccCardLockResult(data);
michael@0 1754 this.fireRequestSuccess(requestId, result);
michael@0 1755 } else {
michael@0 1756 if (data.rilMessageType == "iccSetCardLock" ||
michael@0 1757 data.rilMessageType == "iccUnlockCardLock") {
michael@0 1758 let cardLockError = new requestWindow.IccCardLockError(data.lockType,
michael@0 1759 data.errorMsg,
michael@0 1760 data.retryCount);
michael@0 1761 this.fireRequestDetailedError(requestId, cardLockError);
michael@0 1762 } else {
michael@0 1763 this.fireRequestError(requestId, data.errorMsg);
michael@0 1764 }
michael@0 1765 }
michael@0 1766 break;
michael@0 1767 }
michael@0 1768 case "RIL:CardLockRetryCount":
michael@0 1769 if (data.success) {
michael@0 1770 let result = new MobileIccCardLockRetryCount(data);
michael@0 1771 this.fireRequestSuccess(data.requestId, result);
michael@0 1772 } else {
michael@0 1773 this.fireRequestError(data.requestId, data.errorMsg);
michael@0 1774 }
michael@0 1775 break;
michael@0 1776 case "RIL:USSDReceived":
michael@0 1777 this._deliverEvent(clientId,
michael@0 1778 "_mobileConnectionListeners",
michael@0 1779 "notifyUssdReceived",
michael@0 1780 [data.message, data.sessionEnded]);
michael@0 1781 break;
michael@0 1782 case "RIL:SendMMI":
michael@0 1783 case "RIL:CancelMMI":
michael@0 1784 this.handleSendCancelMMI(data);
michael@0 1785 break;
michael@0 1786 case "RIL:StkCommand":
michael@0 1787 this._deliverEvent(clientId, "_iccListeners", "notifyStkCommand",
michael@0 1788 [JSON.stringify(data)]);
michael@0 1789 break;
michael@0 1790 case "RIL:StkSessionEnd":
michael@0 1791 this._deliverEvent(clientId, "_iccListeners", "notifyStkSessionEnd", null);
michael@0 1792 break;
michael@0 1793 case "RIL:IccOpenChannel":
michael@0 1794 this.handleSimpleRequest(data.requestId, data.errorMsg,
michael@0 1795 data.channel);
michael@0 1796 break;
michael@0 1797 case "RIL:IccCloseChannel":
michael@0 1798 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1799 break;
michael@0 1800 case "RIL:IccExchangeAPDU":
michael@0 1801 this.handleIccExchangeAPDU(data);
michael@0 1802 break;
michael@0 1803 case "RIL:ReadIccContacts":
michael@0 1804 this.handleReadIccContacts(data);
michael@0 1805 break;
michael@0 1806 case "RIL:UpdateIccContact":
michael@0 1807 this.handleUpdateIccContact(data);
michael@0 1808 break;
michael@0 1809 case "RIL:MatchMvno":
michael@0 1810 this.handleSimpleRequest(data.requestId, data.errorMsg, data.result);
michael@0 1811 break;
michael@0 1812 case "RIL:DataError":
michael@0 1813 this.updateConnectionInfo(data, this.rilContexts[clientId].dataConnectionInfo);
michael@0 1814 this._deliverEvent(clientId, "_mobileConnectionListeners", "notifyDataError",
michael@0 1815 [data.errorMsg]);
michael@0 1816 break;
michael@0 1817 case "RIL:GetCallForwardingOptions":
michael@0 1818 this.handleGetCallForwardingOptions(data);
michael@0 1819 break;
michael@0 1820 case "RIL:SetCallForwardingOptions":
michael@0 1821 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1822 break;
michael@0 1823 case "RIL:GetCallBarringOptions":
michael@0 1824 this.handleGetCallBarringOptions(data);
michael@0 1825 break;
michael@0 1826 case "RIL:SetCallBarringOptions":
michael@0 1827 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1828 break;
michael@0 1829 case "RIL:ChangeCallBarringPassword":
michael@0 1830 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1831 break;
michael@0 1832 case "RIL:GetCallWaitingOptions":
michael@0 1833 this.handleSimpleRequest(data.requestId, data.errorMsg,
michael@0 1834 data.enabled);
michael@0 1835 break;
michael@0 1836 case "RIL:SetCallWaitingOptions":
michael@0 1837 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1838 break;
michael@0 1839 case "RIL:CfStateChanged":
michael@0 1840 this._deliverEvent(clientId,
michael@0 1841 "_mobileConnectionListeners",
michael@0 1842 "notifyCFStateChange",
michael@0 1843 [data.success, data.action,
michael@0 1844 data.reason, data.number,
michael@0 1845 data.timeSeconds, data.serviceClass]);
michael@0 1846 break;
michael@0 1847 case "RIL:GetCallingLineIdRestriction":
michael@0 1848 this.handleGetCallingLineIdRestriction(data);
michael@0 1849 break;
michael@0 1850 case "RIL:SetCallingLineIdRestriction":
michael@0 1851 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1852 break;
michael@0 1853 case "RIL:CellBroadcastReceived": {
michael@0 1854 let message = new CellBroadcastMessage(data);
michael@0 1855 this._deliverEvent(clientId,
michael@0 1856 "_cellBroadcastListeners",
michael@0 1857 "notifyMessageReceived",
michael@0 1858 [message]);
michael@0 1859 break;
michael@0 1860 }
michael@0 1861 case "RIL:SetRoamingPreference":
michael@0 1862 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1863 break;
michael@0 1864 case "RIL:GetRoamingPreference":
michael@0 1865 this.handleSimpleRequest(data.requestId, data.errorMsg,
michael@0 1866 data.mode);
michael@0 1867 break;
michael@0 1868 case "RIL:ExitEmergencyCbMode":
michael@0 1869 this.handleExitEmergencyCbMode(data);
michael@0 1870 break;
michael@0 1871 case "RIL:EmergencyCbModeChanged":
michael@0 1872 this._deliverEvent(clientId,
michael@0 1873 "_mobileConnectionListeners",
michael@0 1874 "notifyEmergencyCbModeChanged",
michael@0 1875 [data.active, data.timeoutMs]);
michael@0 1876 break;
michael@0 1877 case "RIL:SetRadioEnabled":
michael@0 1878 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1879 break;
michael@0 1880 case "RIL:RadioStateChanged":
michael@0 1881 this.rilContexts[clientId].radioState = data;
michael@0 1882 this._deliverEvent(clientId,
michael@0 1883 "_mobileConnectionListeners",
michael@0 1884 "notifyRadioStateChanged",
michael@0 1885 null);
michael@0 1886 break;
michael@0 1887 case "RIL:SetVoicePrivacyMode":
michael@0 1888 this.handleSimpleRequest(data.requestId, data.errorMsg, null);
michael@0 1889 break;
michael@0 1890 case "RIL:GetVoicePrivacyMode":
michael@0 1891 this.handleSimpleRequest(data.requestId, data.errorMsg,
michael@0 1892 data.enabled);
michael@0 1893 break;
michael@0 1894 }
michael@0 1895 },
michael@0 1896
michael@0 1897 handleSimpleRequest: function(requestId, errorMsg, result) {
michael@0 1898 if (errorMsg) {
michael@0 1899 this.fireRequestError(requestId, errorMsg);
michael@0 1900 } else {
michael@0 1901 this.fireRequestSuccess(requestId, result);
michael@0 1902 }
michael@0 1903 },
michael@0 1904
michael@0 1905 handleGetAvailableNetworks: function(message) {
michael@0 1906 if (DEBUG) debug("handleGetAvailableNetworks: " + JSON.stringify(message));
michael@0 1907 if (message.errorMsg) {
michael@0 1908 if (DEBUG) {
michael@0 1909 debug("Received error from getAvailableNetworks: " + message.errorMsg);
michael@0 1910 }
michael@0 1911 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 1912 return;
michael@0 1913 }
michael@0 1914
michael@0 1915 let networks = message.networks;
michael@0 1916 for (let i = 0; i < networks.length; i++) {
michael@0 1917 let network = networks[i];
michael@0 1918 let info = new MobileNetworkInfo();
michael@0 1919 this.updateInfo(network, info);
michael@0 1920 networks[i] = info;
michael@0 1921 }
michael@0 1922
michael@0 1923 this.fireRequestSuccess(message.requestId, networks);
michael@0 1924 },
michael@0 1925
michael@0 1926 handleSelectNetwork: function(clientId, message, mode) {
michael@0 1927 this._selectingNetworks[clientId] = null;
michael@0 1928 this.rilContexts[clientId].networkSelectionMode = mode;
michael@0 1929
michael@0 1930 if (message.errorMsg) {
michael@0 1931 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 1932 } else {
michael@0 1933 this.fireRequestSuccess(message.requestId, null);
michael@0 1934 }
michael@0 1935 },
michael@0 1936
michael@0 1937 handleIccExchangeAPDU: function(message) {
michael@0 1938 if (message.errorMsg) {
michael@0 1939 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 1940 } else {
michael@0 1941 var result = [message.sw1, message.sw2, message.simResponse];
michael@0 1942 this.fireRequestSuccess(message.requestId, result);
michael@0 1943 }
michael@0 1944 },
michael@0 1945
michael@0 1946 handleReadIccContacts: function(message) {
michael@0 1947 if (message.errorMsg) {
michael@0 1948 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 1949 return;
michael@0 1950 }
michael@0 1951
michael@0 1952 let window = this._windowsMap[message.requestId];
michael@0 1953 delete this._windowsMap[message.requestId];
michael@0 1954 let contacts = message.contacts;
michael@0 1955 let result = contacts.map(function(c) {
michael@0 1956 let prop = {name: [c.alphaId], tel: [{value: c.number}]};
michael@0 1957
michael@0 1958 if (c.email) {
michael@0 1959 prop.email = [{value: c.email}];
michael@0 1960 }
michael@0 1961
michael@0 1962 // ANR - Additional Number
michael@0 1963 let anrLen = c.anr ? c.anr.length : 0;
michael@0 1964 for (let i = 0; i < anrLen; i++) {
michael@0 1965 prop.tel.push({value: c.anr[i]});
michael@0 1966 }
michael@0 1967
michael@0 1968 let contact = new window.mozContact(prop);
michael@0 1969 contact.id = c.contactId;
michael@0 1970 return contact;
michael@0 1971 });
michael@0 1972
michael@0 1973 this.fireRequestSuccess(message.requestId, result);
michael@0 1974 },
michael@0 1975
michael@0 1976 handleUpdateIccContact: function(message) {
michael@0 1977 if (message.errorMsg) {
michael@0 1978 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 1979 return;
michael@0 1980 }
michael@0 1981
michael@0 1982 let window = this._windowsMap[message.requestId];
michael@0 1983 delete this._windowsMap[message.requestId];
michael@0 1984 let iccContact = message.contact;
michael@0 1985 let prop = {name: [iccContact.alphaId], tel: [{value: iccContact.number}]};
michael@0 1986 if (iccContact.email) {
michael@0 1987 prop.email = [{value: iccContact.email}];
michael@0 1988 }
michael@0 1989
michael@0 1990 // ANR - Additional Number
michael@0 1991 let anrLen = iccContact.anr ? iccContact.anr.length : 0;
michael@0 1992 for (let i = 0; i < anrLen; i++) {
michael@0 1993 prop.tel.push({value: iccContact.anr[i]});
michael@0 1994 }
michael@0 1995
michael@0 1996 let contact = new window.mozContact(prop);
michael@0 1997 contact.id = iccContact.contactId;
michael@0 1998
michael@0 1999 this.fireRequestSuccess(message.requestId, contact);
michael@0 2000 },
michael@0 2001
michael@0 2002 handleVoicemailNotification: function(clientId, message) {
michael@0 2003 let changed = false;
michael@0 2004 if (!this.voicemailStatuses[clientId]) {
michael@0 2005 this.voicemailStatuses[clientId] = new VoicemailStatus(clientId);
michael@0 2006 }
michael@0 2007
michael@0 2008 let voicemailStatus = this.voicemailStatuses[clientId];
michael@0 2009 if (voicemailStatus.hasMessages != message.active) {
michael@0 2010 changed = true;
michael@0 2011 voicemailStatus.hasMessages = message.active;
michael@0 2012 }
michael@0 2013
michael@0 2014 if (voicemailStatus.messageCount != message.msgCount) {
michael@0 2015 changed = true;
michael@0 2016 voicemailStatus.messageCount = message.msgCount;
michael@0 2017 } else if (message.msgCount == -1) {
michael@0 2018 // For MWI using DCS the message count is not available
michael@0 2019 changed = true;
michael@0 2020 }
michael@0 2021
michael@0 2022 if (voicemailStatus.returnNumber != message.returnNumber) {
michael@0 2023 changed = true;
michael@0 2024 voicemailStatus.returnNumber = message.returnNumber;
michael@0 2025 }
michael@0 2026
michael@0 2027 if (voicemailStatus.returnMessage != message.returnMessage) {
michael@0 2028 changed = true;
michael@0 2029 voicemailStatus.returnMessage = message.returnMessage;
michael@0 2030 }
michael@0 2031
michael@0 2032 if (changed) {
michael@0 2033 // To follow the event delivering scheme, we add a dummy clientId 0.
michael@0 2034 // All voicemail events are routed to listener for client id 0.
michael@0 2035 this._deliverEvent(0,
michael@0 2036 "_voicemailListeners",
michael@0 2037 "notifyStatusChanged",
michael@0 2038 [voicemailStatus]);
michael@0 2039 }
michael@0 2040 },
michael@0 2041
michael@0 2042 _cfRulesToMobileCfInfo: function(rules) {
michael@0 2043 for (let i = 0; i < rules.length; i++) {
michael@0 2044 let rule = rules[i];
michael@0 2045 let info = new MobileCFInfo();
michael@0 2046 this.updateInfo(rule, info);
michael@0 2047 rules[i] = info;
michael@0 2048 }
michael@0 2049 },
michael@0 2050
michael@0 2051 handleGetCallForwardingOptions: function(message) {
michael@0 2052 if (message.errorMsg) {
michael@0 2053 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 2054 return;
michael@0 2055 }
michael@0 2056
michael@0 2057 this._cfRulesToMobileCfInfo(message.rules);
michael@0 2058 this.fireRequestSuccess(message.requestId, message.rules);
michael@0 2059 },
michael@0 2060
michael@0 2061 handleGetCallBarringOptions: function(message) {
michael@0 2062 if (!message.success) {
michael@0 2063 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 2064 } else {
michael@0 2065 let options = new CallBarringOptions(message);
michael@0 2066 this.fireRequestSuccess(message.requestId, options);
michael@0 2067 }
michael@0 2068 },
michael@0 2069
michael@0 2070 handleGetCallingLineIdRestriction: function(message) {
michael@0 2071 if (message.errorMsg) {
michael@0 2072 this.fireRequestError(message.requestId, message.errorMsg);
michael@0 2073 return;
michael@0 2074 }
michael@0 2075
michael@0 2076 let status = new DOMCLIRStatus(message);
michael@0 2077 this.fireRequestSuccess(message.requestId, status);
michael@0 2078 },
michael@0 2079
michael@0 2080 handleExitEmergencyCbMode: function(message) {
michael@0 2081 let requestId = message.requestId;
michael@0 2082 let request = this.takeRequest(requestId);
michael@0 2083 if (!request) {
michael@0 2084 return;
michael@0 2085 }
michael@0 2086
michael@0 2087 if (!message.success) {
michael@0 2088 Services.DOMRequest.fireError(request, message.errorMsg);
michael@0 2089 return;
michael@0 2090 }
michael@0 2091 Services.DOMRequest.fireSuccess(request, null);
michael@0 2092 },
michael@0 2093
michael@0 2094 handleSendCancelMMI: function(message) {
michael@0 2095 if (DEBUG) debug("handleSendCancelMMI " + JSON.stringify(message));
michael@0 2096 let request = this.takeRequest(message.requestId);
michael@0 2097 let requestWindow = this._windowsMap[message.requestId];
michael@0 2098 delete this._windowsMap[message.requestId];
michael@0 2099 if (!request) {
michael@0 2100 return;
michael@0 2101 }
michael@0 2102
michael@0 2103 let success = message.success;
michael@0 2104
michael@0 2105 // We expect to have an IMEI at this point if the request was supposed
michael@0 2106 // to query for the IMEI, so getting a successful reply from the RIL
michael@0 2107 // without containing an actual IMEI number is considered an error.
michael@0 2108 if (message.mmiServiceCode === RIL.MMI_KS_SC_IMEI &&
michael@0 2109 !message.statusMessage) {
michael@0 2110 message.errorMsg = message.errorMsg ?
michael@0 2111 message.errorMsg : RIL.GECKO_ERROR_GENERIC_FAILURE;
michael@0 2112 success = false;
michael@0 2113 }
michael@0 2114
michael@0 2115 // MMI query call forwarding options request returns a set of rules that
michael@0 2116 // will be exposed in the form of an array of nsIDOMMozMobileCFInfo
michael@0 2117 // instances.
michael@0 2118 if (message.mmiServiceCode === RIL.MMI_KS_SC_CALL_FORWARDING &&
michael@0 2119 message.additionalInformation) {
michael@0 2120 this._cfRulesToMobileCfInfo(message.additionalInformation);
michael@0 2121 }
michael@0 2122
michael@0 2123 let result = {
michael@0 2124 serviceCode: message.mmiServiceCode,
michael@0 2125 additionalInformation: message.additionalInformation
michael@0 2126 };
michael@0 2127
michael@0 2128 if (success) {
michael@0 2129 result.statusMessage = message.statusMessage;
michael@0 2130 let mmiResult = new DOMMMIResult(result);
michael@0 2131 Services.DOMRequest.fireSuccess(request, mmiResult);
michael@0 2132 } else {
michael@0 2133 let mmiError = new requestWindow.DOMMMIError(result.serviceCode,
michael@0 2134 message.errorMsg,
michael@0 2135 null,
michael@0 2136 result.additionalInformation);
michael@0 2137 Services.DOMRequest.fireDetailedError(request, mmiError);
michael@0 2138 }
michael@0 2139 },
michael@0 2140
michael@0 2141 _deliverEvent: function(clientId, listenerType, name, args) {
michael@0 2142 if (!this[listenerType]) {
michael@0 2143 return;
michael@0 2144 }
michael@0 2145 let thisListeners = this[listenerType][clientId];
michael@0 2146 if (!thisListeners) {
michael@0 2147 return;
michael@0 2148 }
michael@0 2149
michael@0 2150 let listeners = thisListeners.slice();
michael@0 2151 for (let listener of listeners) {
michael@0 2152 if (thisListeners.indexOf(listener) == -1) {
michael@0 2153 continue;
michael@0 2154 }
michael@0 2155 let handler = listener[name];
michael@0 2156 if (typeof handler != "function") {
michael@0 2157 throw new Error("No handler for " + name);
michael@0 2158 }
michael@0 2159 try {
michael@0 2160 handler.apply(listener, args);
michael@0 2161 } catch (e) {
michael@0 2162 if (DEBUG) debug("listener for " + name + " threw an exception: " + e);
michael@0 2163 }
michael@0 2164 }
michael@0 2165 },
michael@0 2166
michael@0 2167 /**
michael@0 2168 * Helper for guarding us again invalid reason values for call forwarding.
michael@0 2169 */
michael@0 2170 _isValidCFReason: function(reason) {
michael@0 2171 switch (reason) {
michael@0 2172 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_UNCONDITIONAL:
michael@0 2173 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_MOBILE_BUSY:
michael@0 2174 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_NO_REPLY:
michael@0 2175 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_NOT_REACHABLE:
michael@0 2176 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_ALL_CALL_FORWARDING:
michael@0 2177 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_REASON_ALL_CONDITIONAL_CALL_FORWARDING:
michael@0 2178 return true;
michael@0 2179 default:
michael@0 2180 return false;
michael@0 2181 }
michael@0 2182 },
michael@0 2183
michael@0 2184 /**
michael@0 2185 * Helper for guarding us again invalid action values for call forwarding.
michael@0 2186 */
michael@0 2187 _isValidCFAction: function(action) {
michael@0 2188 switch (action) {
michael@0 2189 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_DISABLE:
michael@0 2190 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_ENABLE:
michael@0 2191 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_REGISTRATION:
michael@0 2192 case Ci.nsIDOMMozMobileCFInfo.CALL_FORWARD_ACTION_ERASURE:
michael@0 2193 return true;
michael@0 2194 default:
michael@0 2195 return false;
michael@0 2196 }
michael@0 2197 },
michael@0 2198
michael@0 2199 /**
michael@0 2200 * Helper for guarding us against invalid program values for call barring.
michael@0 2201 */
michael@0 2202 _isValidCallBarringProgram: function(program) {
michael@0 2203 switch (program) {
michael@0 2204 case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_ALL_OUTGOING:
michael@0 2205 case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL:
michael@0 2206 case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_OUTGOING_INTERNATIONAL_EXCEPT_HOME:
michael@0 2207 case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_ALL_INCOMING:
michael@0 2208 case Ci.nsIDOMMozMobileConnection.CALL_BARRING_PROGRAM_INCOMING_ROAMING:
michael@0 2209 return true;
michael@0 2210 default:
michael@0 2211 return false;
michael@0 2212 }
michael@0 2213 },
michael@0 2214
michael@0 2215 /**
michael@0 2216 * Helper for guarding us against invalid options for call barring.
michael@0 2217 */
michael@0 2218 _isValidCallBarringOptions: function(options, usedForSetting) {
michael@0 2219 if (!options ||
michael@0 2220 options.serviceClass == null ||
michael@0 2221 !this._isValidCallBarringProgram(options.program)) {
michael@0 2222 return false;
michael@0 2223 }
michael@0 2224
michael@0 2225 // For setting callbarring options, |enabled| and |password| are required.
michael@0 2226 if (usedForSetting && (options.enabled == null || options.password == null)) {
michael@0 2227 return false;
michael@0 2228 }
michael@0 2229
michael@0 2230 return true;
michael@0 2231 }
michael@0 2232 };
michael@0 2233
michael@0 2234 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper,
michael@0 2235 DOMMMIError,
michael@0 2236 IccCardLockError]);

mercurial