mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1114935 - Part 2: Add Gonk Implementation of nsIIccService. r=echen
This commit is contained in:
parent
5ac9c47c75
commit
d520afaae2
@ -483,6 +483,8 @@
|
||||
#if defined(MOZ_WIDGET_GONK) && defined(MOZ_B2G_RIL)
|
||||
@RESPATH@/components/CellBroadcastService.js
|
||||
@RESPATH@/components/CellBroadcastService.manifest
|
||||
@BINPATH@/components/IccService.js
|
||||
@BINPATH@/components/IccService.manifest
|
||||
@RESPATH@/components/MmsService.js
|
||||
@RESPATH@/components/MmsService.manifest
|
||||
@RESPATH@/components/MobileMessageDatabaseService.js
|
||||
|
437
dom/icc/gonk/IccService.js
Normal file
437
dom/icc/gonk/IccService.js
Normal file
@ -0,0 +1,437 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
var RIL = {};
|
||||
Cu.import("resource://gre/modules/ril_consts.js", RIL);
|
||||
|
||||
const GONK_ICCSERVICE_CONTRACTID = "@mozilla.org/icc/gonkiccservice;1";
|
||||
const GONK_ICCSERVICE_CID = Components.ID("{df854256-9554-11e4-a16c-c39e8d106c26}");
|
||||
|
||||
const NS_XPCOM_SHUTDOWN_OBSERVER_ID = "xpcom-shutdown";
|
||||
const NS_PREFBRANCH_PREFCHANGE_TOPIC_ID = "nsPref:changed";
|
||||
|
||||
const kPrefRilDebuggingEnabled = "ril.debugging.enabled";
|
||||
const kPrefRilNumRadioInterfaces = "ril.numRadioInterfaces";
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gRadioInterfaceLayer",
|
||||
"@mozilla.org/ril;1",
|
||||
"nsIRadioInterfaceLayer");
|
||||
|
||||
let DEBUG = RIL.DEBUG_RIL;
|
||||
function debug(s) {
|
||||
dump("IccService: " + s);
|
||||
}
|
||||
|
||||
function IccInfo() {}
|
||||
IccInfo.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccInfo]),
|
||||
|
||||
// nsIIccInfo
|
||||
|
||||
iccType: null,
|
||||
iccid: null,
|
||||
mcc: null,
|
||||
mnc: null,
|
||||
spn: null,
|
||||
isDisplayNetworkNameRequired: false,
|
||||
isDisplaySpnRequired: false
|
||||
};
|
||||
|
||||
function GsmIccInfo() {}
|
||||
GsmIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIGsmIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsIGsmIccInfo
|
||||
|
||||
msisdn: null
|
||||
};
|
||||
|
||||
function CdmaIccInfo() {}
|
||||
CdmaIccInfo.prototype = {
|
||||
__proto__: IccInfo.prototype,
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsICdmaIccInfo,
|
||||
Ci.nsIIccInfo]),
|
||||
|
||||
// nsICdmaIccInfo
|
||||
|
||||
mdn: null,
|
||||
prlVersion: 0
|
||||
};
|
||||
|
||||
function IccService() {
|
||||
this._iccs = [];
|
||||
|
||||
let numClients = gRadioInterfaceLayer.numRadioInterfaces;
|
||||
for (let i = 0; i < numClients; i++) {
|
||||
this._iccs.push(new Icc(gRadioInterfaceLayer.getRadioInterface(i)));
|
||||
}
|
||||
|
||||
this._updateDebugFlag();
|
||||
|
||||
Services.prefs.addObserver(kPrefRilDebuggingEnabled, this, false);
|
||||
Services.obs.addObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
}
|
||||
IccService.prototype = {
|
||||
classID: GONK_ICCSERVICE_CID,
|
||||
|
||||
classInfo: XPCOMUtils.generateCI({classID: GONK_ICCSERVICE_CID,
|
||||
contractID: GONK_ICCSERVICE_CONTRACTID,
|
||||
classDescription: "IccService",
|
||||
interfaces: [Ci.nsIIccService,
|
||||
Ci.nsIGonkIccService],
|
||||
flags: Ci.nsIClassInfo.SINGLETON}),
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIccService,
|
||||
Ci.nsIGonkIccService,
|
||||
Ci.nsIObserver]),
|
||||
|
||||
// An array of Icc instances.
|
||||
_iccs: null,
|
||||
|
||||
_updateDebugFlag: function() {
|
||||
try {
|
||||
DEBUG = DEBUG ||
|
||||
Services.prefs.getBoolPref(kPrefRilDebuggingEnabled);
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIccService interface.
|
||||
*/
|
||||
getIccByServiceId: function(aServiceId) {
|
||||
let icc = this._iccs[aServiceId];
|
||||
if (!icc) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
return icc;
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIGonkIccService interface.
|
||||
*/
|
||||
notifyCardStateChanged: function(aServiceId, aCardState) {
|
||||
if (DEBUG) {
|
||||
debug("notifyCardStateChanged for service Id: " + aServiceId +
|
||||
", CardState: " + aCardState);
|
||||
}
|
||||
|
||||
this.getIccByServiceId(aServiceId)._updateCardState(aCardState);
|
||||
},
|
||||
|
||||
notifyIccInfoChanged: function(aServiceId, aIccInfo) {
|
||||
if (DEBUG) {
|
||||
debug("notifyIccInfoChanged for service Id: " + aServiceId +
|
||||
", IccInfo: " + JSON.stringify(aIccInfo));
|
||||
}
|
||||
|
||||
this.getIccByServiceId(aServiceId)._updateIccInfo(aIccInfo);
|
||||
},
|
||||
|
||||
notifyImsiChanged: function(aServiceId, aImsi) {
|
||||
if (DEBUG) {
|
||||
debug("notifyImsiChanged for service Id: " + aServiceId +
|
||||
", Imsi: " + aImsi);
|
||||
}
|
||||
|
||||
let icc = this.getIccByServiceId(aServiceId);
|
||||
icc._imsi = aImsi;
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIObserver interface.
|
||||
*/
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
switch (aTopic) {
|
||||
case NS_PREFBRANCH_PREFCHANGE_TOPIC_ID:
|
||||
if (aData === kPrefRilDebuggingEnabled) {
|
||||
this._updateDebugFlag();
|
||||
}
|
||||
break;
|
||||
case NS_XPCOM_SHUTDOWN_OBSERVER_ID:
|
||||
Services.prefs.removeObserver(kPrefRilDebuggingEnabled, this);
|
||||
Services.obs.removeObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function Icc(aRadioInterface) {
|
||||
this._radioInterface = aRadioInterface;
|
||||
this._listeners = [];
|
||||
}
|
||||
Icc.prototype = {
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIIcc]),
|
||||
|
||||
_radioInterface: null,
|
||||
_imsi: null,
|
||||
_listeners: null,
|
||||
|
||||
_updateCardState: function(aCardState) {
|
||||
if (this.cardState != aCardState) {
|
||||
this.cardState = aCardState;
|
||||
}
|
||||
|
||||
this._deliverListenerEvent("notifyCardStateChanged");
|
||||
},
|
||||
|
||||
// An utility function to copy objects.
|
||||
_updateInfo: function(aSrcInfo, aDestInfo) {
|
||||
for (let key in aSrcInfo) {
|
||||
aDestInfo[key] = aSrcInfo[key];
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* We need to consider below cases when update iccInfo:
|
||||
* 1. Should clear iccInfo to null if there is no card detected.
|
||||
* 2. Need to create corresponding object based on iccType.
|
||||
*/
|
||||
_updateIccInfo: function(aIccInfo) {
|
||||
// Card is not detected, clear iccInfo to null.
|
||||
if (!aIccInfo || !aIccInfo.iccid) {
|
||||
if (this.iccInfo) {
|
||||
if (DEBUG) {
|
||||
debug("Card is not detected, clear iccInfo to null.");
|
||||
}
|
||||
this.iccInfo = null;
|
||||
this._deliverListenerEvent("notifyIccInfoChanged");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// If iccInfo is null, new corresponding object based on iccType.
|
||||
if (!this.iccInfo ||
|
||||
this.iccInfo.iccType != aIccInfo.iccType) {
|
||||
if (aIccInfo.iccType === "ruim" || aIccInfo.iccType === "csim") {
|
||||
this.iccInfo = new CdmaIccInfo();
|
||||
} else if (aIccInfo.iccType === "sim" || aIccInfo.iccType === "usim") {
|
||||
this.iccInfo = new GsmIccInfo();
|
||||
} else {
|
||||
this.iccInfo = new IccInfo();
|
||||
}
|
||||
}
|
||||
|
||||
this._updateInfo(aIccInfo, this.iccInfo);
|
||||
|
||||
this._deliverListenerEvent("notifyIccInfoChanged");
|
||||
|
||||
// Update lastKnownSimMcc.
|
||||
if (aIccInfo.mcc) {
|
||||
try {
|
||||
Services.prefs.setCharPref("ril.lastKnownSimMcc",
|
||||
aIccInfo.mcc.toString());
|
||||
} catch (e) {}
|
||||
}
|
||||
},
|
||||
|
||||
_deliverListenerEvent: function(aName, aArgs) {
|
||||
let listeners = this._listeners.slice();
|
||||
for (let listener of listeners) {
|
||||
if (this._listeners.indexOf(listener) === -1) {
|
||||
continue;
|
||||
}
|
||||
let handler = listener[aName];
|
||||
if (typeof handler != "function") {
|
||||
throw new Error("No handler for " + aName);
|
||||
}
|
||||
try {
|
||||
handler.apply(listener, aArgs);
|
||||
} catch (e) {
|
||||
if (DEBUG) {
|
||||
debug("listener for " + aName + " threw an exception: " + e);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_modifyCardLock: function(aOperation, aOptions, aCallback) {
|
||||
this._radioInterface.sendWorkerMessage(aOperation,
|
||||
aOptions,
|
||||
(aResponse) => {
|
||||
if (aResponse.errorMsg) {
|
||||
let retryCount =
|
||||
(aResponse.retryCount !== undefined) ? aResponse.retryCount : -1;
|
||||
aCallback.notifyCardLockError(aResponse.errorMsg, retryCount);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback.notifySuccess();
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper to match the MVNO pattern with IMSI.
|
||||
*
|
||||
* Note: Characters 'x' and 'X' in MVNO are skipped and not compared.
|
||||
* E.g., if the aMvnoData passed is '310260x10xxxxxx', then the
|
||||
* function returns true only if imsi has the same first 6 digits, 8th
|
||||
* and 9th digit.
|
||||
*
|
||||
* @param aMvnoData
|
||||
* MVNO pattern.
|
||||
* @param aImsi
|
||||
* IMSI of this ICC.
|
||||
*
|
||||
* @return true if matched.
|
||||
*/
|
||||
_isImsiMatches: function(aMvnoData, aImsi) {
|
||||
// This should not be an error, but a mismatch.
|
||||
if (aMvnoData.length > aImsi.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < aMvnoData.length; i++) {
|
||||
let c = aMvnoData[i];
|
||||
if ((c !== 'x') && (c !== 'X') && (c !== aImsi[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* nsIIcc interface.
|
||||
*/
|
||||
iccInfo: null,
|
||||
cardState: Ci.nsIIcc.CARD_STATE_UNKNOWN,
|
||||
|
||||
registerListener: function(aListener) {
|
||||
if (this._listeners.indexOf(aListener) >= 0) {
|
||||
throw Cr.NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
this._listeners.push(aListener);
|
||||
},
|
||||
|
||||
unregisterListener: function(aListener) {
|
||||
let index = this._listeners.indexOf(aListener);
|
||||
if (index >= 0) {
|
||||
this._listeners.splice(index, 1);
|
||||
}
|
||||
},
|
||||
|
||||
getCardLockEnabled: function(aLockType, aCallback) {
|
||||
this._radioInterface.sendWorkerMessage("iccGetCardLockEnabled",
|
||||
{ lockType: aLockType },
|
||||
(aResponse) => {
|
||||
if (aResponse.errorMsg) {
|
||||
aCallback.notifyError(aResponse.errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback.notifySuccessWithBoolean(aResponse.enabled);
|
||||
});
|
||||
},
|
||||
|
||||
unlockCardLock: function(aLockType, aPassword, aNewPin, aCallback) {
|
||||
this._modifyCardLock("iccUnlockCardLock",
|
||||
{ lockType: aLockType,
|
||||
password: aPassword,
|
||||
newPin: aNewPin },
|
||||
aCallback);
|
||||
},
|
||||
|
||||
setCardLockEnabled: function(aLockType, aPassword, aEnabled, aCallback) {
|
||||
this._modifyCardLock("iccSetCardLockEnabled",
|
||||
{ lockType: aLockType,
|
||||
password: aPassword,
|
||||
enabled: aEnabled },
|
||||
aCallback);
|
||||
},
|
||||
|
||||
changeCardLockPassword: function(aLockType, aPassword, aNewPassword, aCallback) {
|
||||
this._modifyCardLock("iccChangeCardLockPassword",
|
||||
{ lockType: aLockType,
|
||||
password: aPassword,
|
||||
newPassword: aNewPassword, },
|
||||
aCallback);
|
||||
},
|
||||
|
||||
getCardLockRetryCount: function(aLockType, aCallback) {
|
||||
this._radioInterface.sendWorkerMessage("iccGetCardLockRetryCount",
|
||||
{ lockType: aLockType },
|
||||
(aResponse) => {
|
||||
if (aResponse.errorMsg) {
|
||||
aCallback.notifyError(aResponse.errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback.notifyGetCardLockRetryCount(aResponse.retryCount);
|
||||
});
|
||||
},
|
||||
|
||||
matchMvno: function(aMvnoType, aMvnoData, aCallback) {
|
||||
if (!aMvnoData) {
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_INVALID_PARAMETER);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aMvnoType) {
|
||||
case Ci.nsIIcc.CARD_MVNO_TYPE_IMSI:
|
||||
let imsi = this._imsi;
|
||||
if (!imsi) {
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
|
||||
break;
|
||||
}
|
||||
aCallback.notifySuccessWithBoolean(
|
||||
this._isImsiMatches(aMvnoData, imsi));
|
||||
break;
|
||||
case Ci.nsIIcc.CARD_MVNO_TYPE_SPN:
|
||||
let spn = this.iccInfo && this.iccInfo.spn;
|
||||
if (!spn) {
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
|
||||
break;
|
||||
}
|
||||
aCallback.notifySuccessWithBoolean(spn == aMvnoData);
|
||||
break;
|
||||
case Ci.nsIIcc.CARD_MVNO_TYPE_GID:
|
||||
this._radioInterface.sendWorkerMessage("getGID1",
|
||||
null,
|
||||
(aResponse) => {
|
||||
let gid = aResponse.gid1;
|
||||
let mvnoDataLength = aMvnoData.length;
|
||||
|
||||
if (!gid) {
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_GENERIC_FAILURE);
|
||||
} else if (mvnoDataLength > gid.length) {
|
||||
aCallback.notifySuccessWithBoolean(false);
|
||||
} else {
|
||||
let result =
|
||||
gid.substring(0, mvnoDataLength).toLowerCase() ==
|
||||
aMvnoData.toLowerCase();
|
||||
aCallback.notifySuccessWithBoolean(result);
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
aCallback.notifyError(RIL.GECKO_ERROR_MODE_NOT_SUPPORTED);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
getServiceStateEnabled: function(aService, aCallback) {
|
||||
this._radioInterface.sendWorkerMessage("getIccServiceState",
|
||||
{ service: aService },
|
||||
(aResponse) => {
|
||||
if (aResponse.errorMsg) {
|
||||
aCallback.notifyError(aResponse.errorMsg);
|
||||
return;
|
||||
}
|
||||
|
||||
aCallback.notifySuccessWithBoolean(aResponse.result);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([IccService]);
|
6
dom/icc/gonk/IccService.manifest
Normal file
6
dom/icc/gonk/IccService.manifest
Normal file
@ -0,0 +1,6 @@
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
component {df854256-9554-11e4-a16c-c39e8d106c26} IccService.js
|
||||
contract @mozilla.org/icc/gonkiccservice;1 {df854256-9554-11e4-a16c-c39e8d106c26}
|
@ -26,6 +26,10 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['MOZ_B2G_RIL']:
|
||||
EXTRA_JS_MODULES += [
|
||||
'gonk/StkProactiveCmdFactory.jsm',
|
||||
]
|
||||
EXTRA_COMPONENTS += [
|
||||
'gonk/IccService.js',
|
||||
'gonk/IccService.manifest',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
|
@ -127,6 +127,10 @@ function debug(s) {
|
||||
dump("-*- RadioInterfaceLayer: " + s + "\n");
|
||||
}
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gIccService",
|
||||
"@mozilla.org/icc/gonkiccservice;1",
|
||||
"nsIGonkIccService");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "gMobileMessageService",
|
||||
"@mozilla.org/mobilemessage/mobilemessageservice;1",
|
||||
"nsIMobileMessageService");
|
||||
@ -886,8 +890,8 @@ IccInfo.prototype = {
|
||||
mcc: null,
|
||||
mnc: null,
|
||||
spn: null,
|
||||
isDisplayNetworkNameRequired: null,
|
||||
isDisplaySpnRequired: null
|
||||
isDisplayNetworkNameRequired: false,
|
||||
isDisplaySpnRequired: false
|
||||
};
|
||||
|
||||
function GsmIccInfo() {}
|
||||
@ -1919,6 +1923,8 @@ RadioInterface.prototype = {
|
||||
case "cardstatechange":
|
||||
this.rilContext.cardState = message.cardState;
|
||||
gRadioEnabledController.receiveCardState(this.clientId);
|
||||
gIccService.notifyCardStateChanged(this.clientId,
|
||||
this.rilContext.cardState);
|
||||
gMessageManager.sendIccMessage("RIL:CardStateChanged",
|
||||
this.clientId, message);
|
||||
break;
|
||||
@ -1936,6 +1942,7 @@ RadioInterface.prototype = {
|
||||
break;
|
||||
case "iccimsi":
|
||||
this.rilContext.imsi = message.imsi;
|
||||
gIccService.notifyImsiChanged(this.clientId, this.rilContext.imsi);
|
||||
break;
|
||||
case "iccmbdn":
|
||||
this.handleIccMbdn(message);
|
||||
@ -2248,14 +2255,7 @@ RadioInterface.prototype = {
|
||||
gMessageManager.sendIccMessage("RIL:IccInfoChanged",
|
||||
this.clientId,
|
||||
message.iccid ? message : null);
|
||||
|
||||
// Update lastKnownSimMcc.
|
||||
if (message.mcc) {
|
||||
try {
|
||||
Services.prefs.setCharPref("ril.lastKnownSimMcc",
|
||||
message.mcc.toString());
|
||||
} catch (e) {}
|
||||
}
|
||||
gIccService.notifyIccInfoChanged(this.clientId, this.rilContext.iccInfo);
|
||||
|
||||
// Update lastKnownHomeNetwork.
|
||||
if (message.mcc && message.mnc) {
|
||||
|
Loading…
Reference in New Issue
Block a user