2012-07-20 13:10:44 +04:00
|
|
|
/* Copyright 2012 Mozilla Foundation and Mozilla contributors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
|
|
|
|
|
|
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
|
|
Cu.import("resource://gre/modules/Services.jsm");
|
2012-04-12 08:01:49 +04:00
|
|
|
Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
var RIL = {};
|
|
|
|
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
|
|
|
|
2012-06-20 02:52:06 +04:00
|
|
|
// set to true to in ril_consts.js to see debug messages
|
|
|
|
const DEBUG = RIL.DEBUG_CONTENT_HELPER;
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
const RILCONTENTHELPER_CID =
|
|
|
|
Components.ID("{472816e1-1fd6-4405-996c-806f9ea68174}");
|
|
|
|
const MOBILECONNECTIONINFO_CID =
|
|
|
|
Components.ID("{a35cfd39-2d93-4489-ac7d-396475dacb27}");
|
2012-06-13 01:05:50 +04:00
|
|
|
const MOBILENETWORKINFO_CID =
|
2012-06-02 01:10:39 +04:00
|
|
|
Components.ID("{a6c8416c-09b4-46d1-bf29-6520d677d085}");
|
2012-07-19 07:27:08 +04:00
|
|
|
const VOICEMAILSTATUS_CID=
|
|
|
|
Components.ID("{5467f2eb-e214-43ea-9b89-67711241ec8e}");
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
const RIL_IPC_MSG_NAMES = [
|
|
|
|
"RIL:CardStateChanged",
|
|
|
|
"RIL:VoiceInfoChanged",
|
|
|
|
"RIL:DataInfoChanged",
|
2012-04-24 19:44:42 +04:00
|
|
|
"RIL:EnumerateCalls",
|
2012-06-02 01:10:39 +04:00
|
|
|
"RIL:GetAvailableNetworks",
|
2012-06-20 02:52:06 +04:00
|
|
|
"RIL:NetworkSelectionModeChanged",
|
|
|
|
"RIL:SelectNetwork",
|
|
|
|
"RIL:SelectNetworkAuto",
|
2012-04-24 19:44:42 +04:00
|
|
|
"RIL:CallStateChanged",
|
2012-07-19 07:27:08 +04:00
|
|
|
"RIL:VoicemailNotification",
|
2012-07-21 04:19:38 +04:00
|
|
|
"RIL:VoicemailNumberChanged",
|
2012-05-15 08:13:06 +04:00
|
|
|
"RIL:CallError",
|
2012-04-12 08:01:49 +04:00
|
|
|
"RIL:GetCardLock:Return:OK",
|
|
|
|
"RIL:GetCardLock:Return:KO",
|
|
|
|
"RIL:SetCardLock:Return:OK",
|
|
|
|
"RIL:SetCardLock:Return:KO",
|
|
|
|
"RIL:UnlockCardLock:Return:OK",
|
|
|
|
"RIL:UnlockCardLock:Return:KO",
|
2012-06-10 01:07:18 +04:00
|
|
|
"RIL:UssdReceived",
|
|
|
|
"RIL:SendUssd:Return:OK",
|
|
|
|
"RIL:SendUssd:Return:KO",
|
|
|
|
"RIL:CancelUssd:Return:OK",
|
|
|
|
"RIL:CancelUssd:Return:KO"
|
2012-04-20 01:33:25 +04:00
|
|
|
];
|
|
|
|
|
|
|
|
const kVoiceChangedTopic = "mobile-connection-voice-changed";
|
|
|
|
const kDataChangedTopic = "mobile-connection-data-changed";
|
|
|
|
const kCardStateChangedTopic = "mobile-connection-cardstate-changed";
|
2012-06-10 01:07:18 +04:00
|
|
|
const kUssdReceivedTopic = "mobile-connection-ussd-received";
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
|
|
|
|
"@mozilla.org/childprocessmessagemanager;1",
|
|
|
|
"nsIFrameMessageManager");
|
|
|
|
|
|
|
|
function MobileConnectionInfo() {}
|
|
|
|
MobileConnectionInfo.prototype = {
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileConnectionInfo]),
|
|
|
|
classID: MOBILECONNECTIONINFO_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({
|
|
|
|
classID: MOBILECONNECTIONINFO_CID,
|
|
|
|
classDescription: "MobileConnectionInfo",
|
|
|
|
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
|
|
interfaces: [Ci.nsIDOMMozMobileConnectionInfo]
|
|
|
|
}),
|
|
|
|
|
|
|
|
// nsIDOMMozMobileConnectionInfo
|
|
|
|
|
|
|
|
connected: false,
|
|
|
|
emergencyCallsOnly: false,
|
|
|
|
roaming: false,
|
2012-06-13 01:05:50 +04:00
|
|
|
network: null,
|
2012-04-20 01:33:25 +04:00
|
|
|
type: null,
|
|
|
|
signalStrength: null,
|
|
|
|
relSignalStrength: null
|
|
|
|
};
|
|
|
|
|
2012-06-13 01:05:50 +04:00
|
|
|
function MobileNetworkInfo() {}
|
|
|
|
MobileNetworkInfo.prototype = {
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozMobileNetworkInfo]),
|
|
|
|
classID: MOBILENETWORKINFO_CID,
|
2012-06-02 01:10:39 +04:00
|
|
|
classInfo: XPCOMUtils.generateCI({
|
2012-06-13 01:05:50 +04:00
|
|
|
classID: MOBILENETWORKINFO_CID,
|
|
|
|
classDescription: "MobileNetworkInfo",
|
2012-06-02 01:10:39 +04:00
|
|
|
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
2012-06-13 01:05:50 +04:00
|
|
|
interfaces: [Ci.nsIDOMMozMobileNetworkInfo]
|
2012-06-02 01:10:39 +04:00
|
|
|
}),
|
|
|
|
|
2012-06-13 01:05:50 +04:00
|
|
|
// nsIDOMMozMobileNetworkInfo
|
2012-06-02 01:10:39 +04:00
|
|
|
|
|
|
|
shortName: null,
|
|
|
|
longName: null,
|
|
|
|
mcc: 0,
|
|
|
|
mnc: 0,
|
|
|
|
state: null
|
|
|
|
};
|
2012-04-20 01:33:25 +04:00
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
function VoicemailStatus() {}
|
|
|
|
VoicemailStatus.prototype = {
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMMozVoicemailStatus]),
|
|
|
|
classID: VOICEMAILSTATUS_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({
|
|
|
|
classID: VOICEMAILSTATUS_CID,
|
|
|
|
classDescription: "VoicemailStatus",
|
|
|
|
flags: Ci.nsIClassInfo.DOM_OBJECT,
|
|
|
|
interfaces: [Ci.nsIDOMMozVoicemailStatus]
|
|
|
|
}),
|
|
|
|
|
|
|
|
// nsIDOMMozVoicemailStatus
|
|
|
|
|
|
|
|
hasMessages: false,
|
|
|
|
messageCount: Ci.nsIDOMMozVoicemailStatus.MESSAGE_COUNT_UNKNOWN,
|
|
|
|
returnNumber: null,
|
|
|
|
returnMessage: null
|
|
|
|
};
|
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
function RILContentHelper() {
|
|
|
|
this.voiceConnectionInfo = new MobileConnectionInfo();
|
|
|
|
this.dataConnectionInfo = new MobileConnectionInfo();
|
|
|
|
|
2012-04-12 08:01:49 +04:00
|
|
|
this.initRequests();
|
|
|
|
this.initMessageListener(RIL_IPC_MSG_NAMES);
|
2012-04-20 01:33:25 +04:00
|
|
|
Services.obs.addObserver(this, "xpcom-shutdown", false);
|
|
|
|
|
|
|
|
// Request initial state.
|
|
|
|
let radioState = cpmm.QueryInterface(Ci.nsISyncMessageSender)
|
|
|
|
.sendSyncMessage("RIL:GetRadioState")[0];
|
2012-06-13 01:05:50 +04:00
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
if (!radioState) {
|
|
|
|
debug("Received null radioState from chrome process.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.cardState = radioState.cardState;
|
2012-06-13 01:05:50 +04:00
|
|
|
this.updateConnectionInfo(radioState.voice, this.voiceConnectionInfo);
|
|
|
|
this.updateConnectionInfo(radioState.data, this.dataConnectionInfo);
|
2012-04-20 01:33:25 +04:00
|
|
|
}
|
2012-06-13 01:05:50 +04:00
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
RILContentHelper.prototype = {
|
2012-04-12 08:01:49 +04:00
|
|
|
__proto__: DOMRequestIpcHelper.prototype,
|
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIMobileConnectionProvider,
|
|
|
|
Ci.nsIRILContentHelper,
|
|
|
|
Ci.nsIObserver]),
|
|
|
|
classID: RILCONTENTHELPER_CID,
|
|
|
|
classInfo: XPCOMUtils.generateCI({classID: RILCONTENTHELPER_CID,
|
|
|
|
classDescription: "RILContentHelper",
|
|
|
|
interfaces: [Ci.nsIMobileConnectionProvider,
|
|
|
|
Ci.nsIRILContentHelper]}),
|
|
|
|
|
2012-06-13 01:05:50 +04:00
|
|
|
updateConnectionInfo: function updateConnectionInfo(srcInfo, destInfo) {
|
|
|
|
for (let key in srcInfo) {
|
|
|
|
if (key != "network") {
|
|
|
|
destInfo[key] = srcInfo[key];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let srcNetwork = srcInfo.network;
|
|
|
|
if (!srcNetwork) {
|
|
|
|
destInfo.network= null;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let network = destInfo.network;
|
|
|
|
if (!network) {
|
|
|
|
network = destInfo.network = new MobileNetworkInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
network.longName = srcNetwork.longName;
|
|
|
|
network.shortName = srcNetwork.shortName;
|
|
|
|
network.mnc = srcNetwork.mnc;
|
|
|
|
network.mcc = srcNetwork.mcc;
|
|
|
|
},
|
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
// nsIRILContentHelper
|
|
|
|
|
|
|
|
cardState: RIL.GECKO_CARDSTATE_UNAVAILABLE,
|
|
|
|
voiceConnectionInfo: null,
|
|
|
|
dataConnectionInfo: null,
|
2012-06-20 02:52:06 +04:00
|
|
|
networkSelectionMode: RIL.GECKO_NETWORK_SELECTION_UNKNOWN,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The network that is currently trying to be selected (or "automatic").
|
|
|
|
* This helps ensure that only one network is selected at a time.
|
|
|
|
*/
|
|
|
|
_selectingNetwork: null,
|
2012-04-20 01:33:25 +04:00
|
|
|
|
|
|
|
getNetworks: function getNetworks(window) {
|
2012-06-02 01:10:39 +04:00
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
|
|
|
|
cpmm.sendAsyncMessage("RIL:GetAvailableNetworks", requestId);
|
|
|
|
return request;
|
2012-04-20 01:33:25 +04:00
|
|
|
},
|
|
|
|
|
2012-06-20 02:52:06 +04:00
|
|
|
selectNetwork: function selectNetwork(window, network) {
|
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._selectingNetwork) {
|
|
|
|
throw new Error("Already selecting a network: " + this._selectingNetwork);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!network) {
|
|
|
|
throw new Error("Invalid network provided: " + network);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mnc = network.mnc;
|
|
|
|
if (!mnc) {
|
|
|
|
throw new Error("Invalid network MNC: " + mnc);
|
|
|
|
}
|
|
|
|
|
|
|
|
let mcc = network.mcc;
|
|
|
|
if (!mcc) {
|
|
|
|
throw new Error("Invalid network MCC: " + mcc);
|
|
|
|
}
|
|
|
|
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
|
|
|
|
if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_MANUAL
|
|
|
|
&& this.voiceConnectionInfo.network === network) {
|
|
|
|
|
|
|
|
// Already manually selected this network, so schedule
|
|
|
|
// onsuccess to be fired on the next tick
|
|
|
|
this.dispatchFireRequestSuccess(requestId, null);
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._selectingNetwork = network;
|
|
|
|
|
|
|
|
cpmm.sendAsyncMessage("RIL:SelectNetwork", {
|
|
|
|
requestId: requestId,
|
|
|
|
mnc: mnc,
|
|
|
|
mcc: mcc
|
|
|
|
});
|
|
|
|
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
|
|
|
selectNetworkAutomatically: function selectNetworkAutomatically(window) {
|
|
|
|
|
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._selectingNetwork) {
|
|
|
|
throw new Error("Already selecting a network: " + this._selectingNetwork);
|
|
|
|
}
|
|
|
|
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
|
|
|
|
if (this.networkSelectionMode == RIL.GECKO_NETWORK_SELECTION_AUTOMATIC) {
|
|
|
|
// Already using automatic selection mode, so schedule
|
|
|
|
// onsuccess to be be fired on the next tick
|
|
|
|
this.dispatchFireRequestSuccess(requestId, null);
|
|
|
|
return request;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._selectingNetwork = "automatic";
|
|
|
|
cpmm.sendAsyncMessage("RIL:SelectNetworkAuto", requestId);
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
2012-04-12 08:01:49 +04:00
|
|
|
getCardLock: function getCardLock(window, lockType) {
|
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
cpmm.sendAsyncMessage("RIL:GetCardLock", {lockType: lockType, requestId: requestId});
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
|
|
|
unlockCardLock: function unlockCardLock(window, info) {
|
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
info.requestId = this.getRequestId(request);
|
|
|
|
cpmm.sendAsyncMessage("RIL:UnlockCardLock", info);
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
|
|
|
setCardLock: function setCardLock(window, info) {
|
|
|
|
if (window == null) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
info.requestId = this.getRequestId(request);
|
|
|
|
cpmm.sendAsyncMessage("RIL:SetCardLock", info);
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
2012-06-10 01:07:18 +04:00
|
|
|
sendUSSD: function sendUSSD(window, ussd) {
|
|
|
|
debug("Sending USSD " + ussd);
|
|
|
|
if (!window) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_EXPECTED);
|
|
|
|
}
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
cpmm.sendAsyncMessage("RIL:SendUSSD", {ussd: ussd, requestId: requestId});
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
|
|
|
cancelUSSD: function cancelUSSD(window) {
|
|
|
|
debug("Cancel USSD");
|
|
|
|
if (!window) {
|
|
|
|
throw Components.Exception("Can't get window object",
|
|
|
|
Cr.NS_ERROR_UNEXPECTED);
|
|
|
|
}
|
|
|
|
let request = Services.DOMRequest.createRequest(window);
|
|
|
|
let requestId = this.getRequestId(request);
|
|
|
|
cpmm.sendAsyncMessage("RIL:CancelUSSD", {requestId: requestId});
|
|
|
|
return request;
|
|
|
|
},
|
|
|
|
|
2012-04-24 19:44:42 +04:00
|
|
|
_telephonyCallbacks: null,
|
2012-07-19 07:27:08 +04:00
|
|
|
_voicemailCallbacks: null,
|
|
|
|
_enumerateTelephonyCallbacks: null,
|
2012-04-24 19:44:42 +04:00
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
voicemailStatus: null,
|
2012-07-21 04:19:38 +04:00
|
|
|
voicemailNumber: null,
|
|
|
|
voicemailDisplayName: null,
|
2012-07-19 07:27:08 +04:00
|
|
|
|
|
|
|
registerCallback: function registerCallback(callbackType, callback) {
|
|
|
|
let callbacks = this[callbackType];
|
|
|
|
if (!callbacks) {
|
|
|
|
callbacks = this[callbackType] = [];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (callbacks.indexOf(callback) != -1) {
|
|
|
|
throw new Error("Already registered this callback!");
|
2012-04-24 19:44:42 +04:00
|
|
|
}
|
2012-07-19 07:27:08 +04:00
|
|
|
|
|
|
|
callbacks.push(callback);
|
|
|
|
if (DEBUG) debug("Registered " + callbackType + " callback: " + callback);
|
2012-04-24 19:44:42 +04:00
|
|
|
},
|
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
unregisterCallback: function unregisterCallback(callbackType, callback) {
|
|
|
|
let callbacks = this[callbackType];
|
|
|
|
if (!callbacks) {
|
2012-04-24 19:44:42 +04:00
|
|
|
return;
|
|
|
|
}
|
2012-07-19 07:27:08 +04:00
|
|
|
|
|
|
|
let index = callbacks.indexOf(callback);
|
2012-04-24 19:44:42 +04:00
|
|
|
if (index != -1) {
|
2012-07-19 07:27:08 +04:00
|
|
|
callbacks.splice(index, 1);
|
|
|
|
if (DEBUG) debug("Unregistered telephony callback: " + callback);
|
2012-04-24 19:44:42 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
registerTelephonyCallback: function registerTelephonyCallback(callback) {
|
|
|
|
this.registerCallback("_telephonyCallbacks", callback);
|
|
|
|
},
|
|
|
|
|
|
|
|
unregisterTelephonyCallback: function unregisteTelephonyCallback(callback) {
|
|
|
|
this.unregisterCallback("_telephonyCallbacks", callback);
|
|
|
|
},
|
|
|
|
|
|
|
|
registerVoicemailCallback: function registerVoicemailCallback(callback) {
|
|
|
|
this.registerCallback("_voicemailCallbacks", callback);
|
|
|
|
},
|
|
|
|
|
|
|
|
unregisterVoicemailCallback: function unregisteVoicemailCallback(callback) {
|
|
|
|
this.unregisterCallback("_voicemailCallbacks", callback);
|
|
|
|
},
|
|
|
|
|
2012-04-24 19:44:42 +04:00
|
|
|
enumerateCalls: function enumerateCalls(callback) {
|
|
|
|
debug("Requesting enumeration of calls for callback: " + callback);
|
|
|
|
cpmm.sendAsyncMessage("RIL:EnumerateCalls");
|
|
|
|
if (!this._enumerationTelephonyCallbacks) {
|
|
|
|
this._enumerationTelephonyCallbacks = [];
|
|
|
|
}
|
|
|
|
this._enumerationTelephonyCallbacks.push(callback);
|
|
|
|
},
|
|
|
|
|
|
|
|
startTone: function startTone(dtmfChar) {
|
|
|
|
debug("Sending Tone for " + dtmfChar);
|
|
|
|
cpmm.sendAsyncMessage("RIL:StartTone", dtmfChar);
|
|
|
|
},
|
|
|
|
|
|
|
|
stopTone: function stopTone() {
|
|
|
|
debug("Stopping Tone");
|
|
|
|
cpmm.sendAsyncMessage("RIL:StopTone");
|
|
|
|
},
|
|
|
|
|
|
|
|
dial: function dial(number) {
|
|
|
|
debug("Dialing " + number);
|
|
|
|
cpmm.sendAsyncMessage("RIL:Dial", number);
|
|
|
|
},
|
|
|
|
|
2012-07-20 16:08:24 +04:00
|
|
|
dialEmergency: function dialEmergency(number) {
|
|
|
|
debug("Dialing emergency " + number);
|
|
|
|
cpmm.sendAsyncMessage("RIL:DialEmergency", number);
|
|
|
|
},
|
|
|
|
|
2012-04-24 19:44:42 +04:00
|
|
|
hangUp: function hangUp(callIndex) {
|
|
|
|
debug("Hanging up call no. " + callIndex);
|
|
|
|
cpmm.sendAsyncMessage("RIL:HangUp", callIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
answerCall: function answerCall(callIndex) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:AnswerCall", callIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
rejectCall: function rejectCall(callIndex) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:RejectCall", callIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
holdCall: function holdCall(callIndex) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:HoldCall", callIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
resumeCall: function resumeCall(callIndex) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:ResumeCall", callIndex);
|
|
|
|
},
|
|
|
|
|
|
|
|
get microphoneMuted() {
|
|
|
|
return cpmm.sendSyncMessage("RIL:GetMicrophoneMuted")[0];
|
|
|
|
},
|
|
|
|
|
|
|
|
set microphoneMuted(value) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:SetMicrophoneMuted", value);
|
|
|
|
},
|
|
|
|
|
|
|
|
get speakerEnabled() {
|
|
|
|
return cpmm.sendSyncMessage("RIL:GetSpeakerEnabled")[0];
|
|
|
|
},
|
|
|
|
|
|
|
|
set speakerEnabled(value) {
|
|
|
|
cpmm.sendAsyncMessage("RIL:SetSpeakerEnabled", value);
|
|
|
|
},
|
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
// nsIObserver
|
|
|
|
|
|
|
|
observe: function observe(subject, topic, data) {
|
|
|
|
if (topic == "xpcom-shutdown") {
|
2012-04-12 08:01:49 +04:00
|
|
|
this.removeMessageListener();
|
2012-04-20 01:33:25 +04:00
|
|
|
Services.obs.removeObserver(this, "xpcom-shutdown");
|
|
|
|
cpmm = null;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
// nsIFrameMessageListener
|
|
|
|
|
2012-06-13 01:05:50 +04:00
|
|
|
fireRequestSuccess: function fireRequestSuccess(requestId, result) {
|
|
|
|
let request = this.takeRequest(requestId);
|
|
|
|
if (!request) {
|
|
|
|
if (DEBUG) {
|
2012-06-20 02:52:06 +04:00
|
|
|
debug("not firing success for id: " + requestId +
|
|
|
|
", result: " + JSON.stringify(result));
|
2012-06-13 01:05:50 +04:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DEBUG) {
|
2012-06-20 02:52:06 +04:00
|
|
|
debug("fire request success, id: " + requestId +
|
|
|
|
", result: " + JSON.stringify(result));
|
2012-06-13 01:05:50 +04:00
|
|
|
}
|
|
|
|
Services.DOMRequest.fireSuccess(request, result);
|
|
|
|
},
|
|
|
|
|
2012-06-20 02:52:06 +04:00
|
|
|
dispatchFireRequestSuccess: function dispatchFireRequestSuccess(requestId, result) {
|
|
|
|
let currentThread = Services.tm.currentThread;
|
|
|
|
|
|
|
|
currentThread.dispatch(this.fireRequestSuccess.bind(this, requestId, result),
|
|
|
|
Ci.nsIThread.DISPATCH_NORMAL);
|
|
|
|
},
|
|
|
|
|
2012-06-13 01:05:50 +04:00
|
|
|
fireRequestError: function fireRequestError(requestId, error) {
|
|
|
|
let request = this.takeRequest(requestId);
|
|
|
|
if (!request) {
|
|
|
|
if (DEBUG) {
|
2012-06-20 02:52:06 +04:00
|
|
|
debug("not firing error for id: " + requestId +
|
|
|
|
", error: " + JSON.stringify(error));
|
2012-06-13 01:05:50 +04:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (DEBUG) {
|
2012-06-20 02:52:06 +04:00
|
|
|
debug("fire request error, id: " + requestId +
|
|
|
|
", result: " + JSON.stringify(error));
|
2012-06-13 01:05:50 +04:00
|
|
|
}
|
|
|
|
Services.DOMRequest.fireError(request, error);
|
|
|
|
},
|
|
|
|
|
2012-04-20 01:33:25 +04:00
|
|
|
receiveMessage: function receiveMessage(msg) {
|
2012-04-12 08:01:49 +04:00
|
|
|
let request;
|
2012-04-20 01:33:25 +04:00
|
|
|
debug("Received message '" + msg.name + "': " + JSON.stringify(msg.json));
|
|
|
|
switch (msg.name) {
|
|
|
|
case "RIL:CardStateChanged":
|
|
|
|
if (this.cardState != msg.json.cardState) {
|
|
|
|
this.cardState = msg.json.cardState;
|
|
|
|
Services.obs.notifyObservers(null, kCardStateChangedTopic, null);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "RIL:VoiceInfoChanged":
|
2012-06-13 01:05:50 +04:00
|
|
|
this.updateConnectionInfo(msg.json, this.voiceConnectionInfo);
|
2012-04-20 01:33:25 +04:00
|
|
|
Services.obs.notifyObservers(null, kVoiceChangedTopic, null);
|
|
|
|
break;
|
|
|
|
case "RIL:DataInfoChanged":
|
2012-06-13 01:05:50 +04:00
|
|
|
this.updateConnectionInfo(msg.json, this.dataConnectionInfo);
|
2012-04-20 01:33:25 +04:00
|
|
|
Services.obs.notifyObservers(null, kDataChangedTopic, null);
|
|
|
|
break;
|
2012-04-24 19:44:42 +04:00
|
|
|
case "RIL:EnumerateCalls":
|
|
|
|
this.handleEnumerateCalls(msg.json);
|
|
|
|
break;
|
2012-06-02 01:10:39 +04:00
|
|
|
case "RIL:GetAvailableNetworks":
|
|
|
|
this.handleGetAvailableNetworks(msg.json);
|
|
|
|
break;
|
2012-06-20 02:52:06 +04:00
|
|
|
case "RIL:NetworkSelectionModeChanged":
|
|
|
|
this.networkSelectionMode = msg.json.mode;
|
|
|
|
break;
|
|
|
|
case "RIL:SelectNetwork":
|
|
|
|
this.handleSelectNetwork(msg.json,
|
|
|
|
RIL.GECKO_NETWORK_SELECTION_MANUAL);
|
|
|
|
break;
|
|
|
|
case "RIL:SelectNetworkAuto":
|
|
|
|
this.handleSelectNetwork(msg.json,
|
|
|
|
RIL.GECKO_NETWORK_SELECTION_AUTOMATIC);
|
|
|
|
break;
|
2012-04-24 19:44:42 +04:00
|
|
|
case "RIL:CallStateChanged":
|
2012-07-19 07:27:08 +04:00
|
|
|
this._deliverCallback("_telephonyCallbacks",
|
|
|
|
"callStateChanged",
|
|
|
|
[msg.json.callIndex, msg.json.state,
|
|
|
|
msg.json.number, msg.json.isActive]);
|
2012-05-15 08:13:06 +04:00
|
|
|
break;
|
|
|
|
case "RIL:CallError":
|
2012-07-19 07:27:08 +04:00
|
|
|
this._deliverCallback("_telephonyCallbacks",
|
|
|
|
"notifyError",
|
|
|
|
[msg.json.callIndex,
|
|
|
|
msg.json.error]);
|
|
|
|
break;
|
|
|
|
case "RIL:VoicemailNotification":
|
|
|
|
this.handleVoicemailNotification(msg.json);
|
2012-06-02 01:10:39 +04:00
|
|
|
break;
|
2012-07-21 04:19:38 +04:00
|
|
|
case "RIL:VoicemailNumberChanged":
|
|
|
|
this.voicemailNumber = msg.json.number;
|
|
|
|
this.voicemailDisplayName = msg.json.alphaId;
|
|
|
|
break;
|
2012-04-12 08:01:49 +04:00
|
|
|
case "RIL:GetCardLock:Return:OK":
|
|
|
|
case "RIL:SetCardLock:Return:OK":
|
|
|
|
case "RIL:UnlockCardLock:Return:OK":
|
2012-06-13 01:05:50 +04:00
|
|
|
this.fireRequestSuccess(msg.json.requestId, msg.json);
|
2012-04-12 08:01:49 +04:00
|
|
|
break;
|
|
|
|
case "RIL:GetCardLock:Return:KO":
|
|
|
|
case "RIL:SetCardLock:Return:KO":
|
|
|
|
case "RIL:UnlockCardLock:Return:KO":
|
2012-06-13 01:05:50 +04:00
|
|
|
this.fireRequestError(msg.json.requestId, msg.json.errorMsg);
|
2012-04-12 08:01:49 +04:00
|
|
|
break;
|
2012-06-10 01:07:18 +04:00
|
|
|
case "RIL:UssdReceived":
|
|
|
|
Services.obs.notifyObservers(null, kUssdReceivedTopic,
|
|
|
|
msg.json.message);
|
|
|
|
break;
|
|
|
|
case "RIL:SendUssd:Return:OK":
|
|
|
|
case "RIL:CancelUssd:Return:OK":
|
|
|
|
request = this.takeRequest(msg.json.requestId);
|
|
|
|
if (request) {
|
|
|
|
Services.DOMRequest.fireSuccess(request, msg.json);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case "RIL:SendUssd:Return:KO":
|
|
|
|
case "RIL:CancelUssd:Return:KO":
|
|
|
|
request = this.takeRequest(msg.json.requestId);
|
|
|
|
if (request) {
|
|
|
|
Services.DOMRequest.fireError(request, msg.json.errorMsg);
|
|
|
|
}
|
|
|
|
break;
|
2012-04-24 19:44:42 +04:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-05-15 08:13:06 +04:00
|
|
|
handleEnumerateCalls: function handleEnumerateCalls(calls) {
|
|
|
|
debug("handleEnumerateCalls: " + JSON.stringify(calls));
|
2012-04-24 19:44:42 +04:00
|
|
|
let callback = this._enumerationTelephonyCallbacks.shift();
|
|
|
|
for (let i in calls) {
|
|
|
|
let call = calls[i];
|
|
|
|
let keepGoing;
|
|
|
|
try {
|
|
|
|
keepGoing =
|
|
|
|
callback.enumerateCallState(call.callIndex, call.state, call.number,
|
2012-05-15 08:13:06 +04:00
|
|
|
call.isActive);
|
2012-04-24 19:44:42 +04:00
|
|
|
} catch (e) {
|
|
|
|
debug("callback handler for 'enumerateCallState' threw an " +
|
|
|
|
" exception: " + e);
|
|
|
|
keepGoing = true;
|
|
|
|
}
|
|
|
|
if (!keepGoing) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-06-02 01:10:39 +04:00
|
|
|
handleGetAvailableNetworks: function handleGetAvailableNetworks(message) {
|
|
|
|
debug("handleGetAvailableNetworks: " + JSON.stringify(message));
|
|
|
|
|
|
|
|
let requestId = message.requestId;
|
|
|
|
let request = this.takeRequest(requestId);
|
|
|
|
if (!request) {
|
|
|
|
debug("no DOMRequest found with request ID: " + requestId);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (message.error) {
|
|
|
|
debug("Received error from getAvailableNetworks: " + message.error);
|
|
|
|
Services.DOMRequest.fireError(request, message.error);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let networks = message.networks;
|
|
|
|
for (let i = 0; i < networks.length; i++) {
|
|
|
|
let network = networks[i];
|
2012-06-13 01:05:50 +04:00
|
|
|
let info = new MobileNetworkInfo();
|
2012-06-02 01:10:39 +04:00
|
|
|
|
|
|
|
for (let key in network) {
|
|
|
|
info[key] = network[key];
|
|
|
|
}
|
|
|
|
|
|
|
|
networks[i] = info;
|
|
|
|
}
|
|
|
|
|
|
|
|
Services.DOMRequest.fireSuccess(request, networks);
|
|
|
|
},
|
|
|
|
|
2012-06-20 02:52:06 +04:00
|
|
|
handleSelectNetwork: function handleSelectNetwork(message, mode) {
|
|
|
|
this._selectingNetwork = null;
|
|
|
|
this.networkSelectionMode = mode;
|
|
|
|
|
|
|
|
if (message.error) {
|
|
|
|
this.fireRequestError(message.requestId, message.error);
|
|
|
|
} else {
|
|
|
|
this.fireRequestSuccess(message.requestId, null);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
handleVoicemailNotification: function handleVoicemailNotification(message) {
|
|
|
|
let changed = false;
|
|
|
|
if (!this.voicemailStatus) {
|
|
|
|
this.voicemailStatus = new VoicemailStatus();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.voicemailStatus.hasMessages != message.active) {
|
|
|
|
changed = true;
|
|
|
|
this.voicemailStatus.hasMessages = message.active;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.voicemailStatus.messageCount != message.msgCount) {
|
|
|
|
changed = true;
|
|
|
|
this.voicemailStatus.messageCount = message.msgCount;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.voicemailStatus.returnNumber != message.returnNumber) {
|
|
|
|
changed = true;
|
|
|
|
this.voicemailStatus.returnNumber = message.returnNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.voicemailStatus.returnMessage != message.returnMessage) {
|
|
|
|
changed = true;
|
|
|
|
this.voicemailStatus.returnMessage = message.returnMessage;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (changed) {
|
|
|
|
this._deliverCallback("_voicemailCallbacks",
|
|
|
|
"voicemailNotification",
|
|
|
|
[this.voicemailStatus]);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_deliverCallback: function _deliverCallback(callbackType, name, args) {
|
|
|
|
let thisCallbacks = this[callbackType];
|
|
|
|
if (!thisCallbacks) {
|
2012-04-24 19:44:42 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-19 07:27:08 +04:00
|
|
|
let callbacks = thisCallbacks.slice();
|
2012-04-24 19:44:42 +04:00
|
|
|
for each (let callback in callbacks) {
|
2012-07-19 07:27:08 +04:00
|
|
|
if (thisCallbacks.indexOf(callback) == -1) {
|
2012-04-24 19:44:42 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let handler = callback[name];
|
|
|
|
if (typeof handler != "function") {
|
|
|
|
throw new Error("No handler for " + name);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
handler.apply(callback, args);
|
|
|
|
} catch (e) {
|
|
|
|
debug("callback handler for " + name + " threw an exception: " + e);
|
|
|
|
}
|
2012-04-20 01:33:25 +04:00
|
|
|
}
|
2012-07-19 07:27:08 +04:00
|
|
|
}
|
2012-04-20 01:33:25 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
const NSGetFactory = XPCOMUtils.generateNSGetFactory([RILContentHelper]);
|
|
|
|
|
|
|
|
let debug;
|
|
|
|
if (DEBUG) {
|
|
|
|
debug = function (s) {
|
|
|
|
dump("-*- RILContentHelper: " + s + "\n");
|
|
|
|
};
|
|
|
|
} else {
|
|
|
|
debug = function (s) {};
|
|
|
|
}
|