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]);