michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ michael@0: michael@0: "use strict"; michael@0: michael@0: this.EXPORTED_SYMBOLS = ["PhoneNumberUtils"]; michael@0: michael@0: const DEBUG = false; michael@0: function debug(s) { if(DEBUG) dump("-*- PhoneNumberutils: " + s + "\n"); } michael@0: michael@0: const Cu = Components.utils; michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import('resource://gre/modules/XPCOMUtils.jsm'); michael@0: Cu.import("resource://gre/modules/PhoneNumberNormalizer.jsm"); michael@0: Cu.import("resource://gre/modules/mcc_iso3166_table.jsm"); michael@0: michael@0: #ifdef MOZ_B2G_RIL michael@0: XPCOMUtils.defineLazyServiceGetter(this, "mobileConnection", michael@0: "@mozilla.org/ril/content-helper;1", michael@0: "nsIMobileConnectionProvider"); michael@0: XPCOMUtils.defineLazyServiceGetter(this, "icc", michael@0: "@mozilla.org/ril/content-helper;1", michael@0: "nsIIccProvider"); michael@0: #endif michael@0: michael@0: this.PhoneNumberUtils = { michael@0: init: function() { michael@0: ppmm.addMessageListener(["PhoneNumberService:FuzzyMatch"], this); michael@0: }, michael@0: // 1. See whether we have a network mcc michael@0: // 2. If we don't have that, look for the simcard mcc michael@0: // 3. If we don't have that or its 0 (not activated), pick up the last used mcc michael@0: // 4. If we don't have, default to some mcc michael@0: michael@0: // mcc for Brasil michael@0: _mcc: '724', michael@0: michael@0: getCountryName: function getCountryName() { michael@0: let mcc; michael@0: let countryName; michael@0: michael@0: #ifdef MOZ_B2G_RIL michael@0: // TODO: Bug 926740 - PhoneNumberUtils for multisim michael@0: // In Multi-sim, there is more than one client in michael@0: // iccProvider/mobileConnectionProvider. Each client represents a michael@0: // icc/mobileConnection service. To maintain the backward compatibility with michael@0: // single sim, we always use client 0 for now. Adding support for multiple michael@0: // sim will be addressed in bug 926740, if needed. michael@0: let clientId = 0; michael@0: michael@0: // Get network mcc michael@0: let voice = mobileConnection.getVoiceConnectionInfo(clientId); michael@0: if (voice && voice.network && voice.network.mcc) { michael@0: mcc = voice.network.mcc; michael@0: } michael@0: michael@0: // Get SIM mcc michael@0: let iccInfo = icc.getIccInfo(clientId); michael@0: if (!mcc && iccInfo && iccInfo.mcc) { michael@0: mcc = iccInfo.mcc; michael@0: } michael@0: michael@0: // Attempt to grab last known sim mcc from prefs michael@0: if (!mcc) { michael@0: try { michael@0: mcc = Services.prefs.getCharPref("ril.lastKnownSimMcc"); michael@0: } catch (e) {} michael@0: } michael@0: michael@0: // Set to default mcc michael@0: if (!mcc) { michael@0: mcc = this._mcc; michael@0: } michael@0: #else michael@0: michael@0: // Attempt to grab last known sim mcc from prefs michael@0: if (!mcc) { michael@0: try { michael@0: mcc = Services.prefs.getCharPref("ril.lastKnownSimMcc"); michael@0: } catch (e) {} michael@0: } michael@0: michael@0: if (!mcc) { michael@0: mcc = this._mcc; michael@0: } michael@0: #endif michael@0: michael@0: countryName = MCC_ISO3166_TABLE[mcc]; michael@0: if (DEBUG) debug("MCC: " + mcc + "countryName: " + countryName); michael@0: return countryName; michael@0: }, michael@0: michael@0: parse: function(aNumber) { michael@0: if (DEBUG) debug("call parse: " + aNumber); michael@0: let result = PhoneNumber.Parse(aNumber, this.getCountryName()); michael@0: michael@0: if (result) { michael@0: let countryName = result.countryName || this.getCountryName(); michael@0: let number = null; michael@0: if (countryName) { michael@0: if (Services.prefs.getPrefType("dom.phonenumber.substringmatching." + countryName) == Ci.nsIPrefBranch.PREF_INT) { michael@0: let val = Services.prefs.getIntPref("dom.phonenumber.substringmatching." + countryName); michael@0: if (val) { michael@0: number = result.internationalNumber || result.nationalNumber; michael@0: if (number && number.length > val) { michael@0: number = number.slice(-val); michael@0: } michael@0: } michael@0: } michael@0: } michael@0: Object.defineProperty(result, "nationalMatchingFormat", { value: number, enumerable: true }); michael@0: if (DEBUG) { michael@0: debug("InternationalFormat: " + result.internationalFormat); michael@0: debug("InternationalNumber: " + result.internationalNumber); michael@0: debug("NationalNumber: " + result.nationalNumber); michael@0: debug("NationalFormat: " + result.nationalFormat); michael@0: debug("CountryName: " + result.countryName); michael@0: debug("NationalMatchingFormat: " + result.nationalMatchingFormat); michael@0: } michael@0: } else if (DEBUG) { michael@0: debug("NO PARSING RESULT!"); michael@0: } michael@0: return result; michael@0: }, michael@0: michael@0: parseWithMCC: function(aNumber, aMCC) { michael@0: let countryName = MCC_ISO3166_TABLE[aMCC]; michael@0: if (DEBUG) debug("found country name: " + countryName); michael@0: return PhoneNumber.Parse(aNumber, countryName); michael@0: }, michael@0: michael@0: parseWithCountryName: function(aNumber, countryName) { michael@0: return PhoneNumber.Parse(aNumber, countryName); michael@0: }, michael@0: michael@0: isPlainPhoneNumber: function isPlainPhoneNumber(aNumber) { michael@0: var isPlain = PhoneNumber.IsPlain(aNumber); michael@0: if (DEBUG) debug("isPlain(" + aNumber + ") " + isPlain); michael@0: return isPlain; michael@0: }, michael@0: michael@0: normalize: function Normalize(aNumber, aNumbersOnly) { michael@0: let normalized = PhoneNumberNormalizer.Normalize(aNumber, aNumbersOnly); michael@0: if (DEBUG) debug("normalize(" + aNumber + "): " + normalized + ", " + aNumbersOnly); michael@0: return normalized; michael@0: }, michael@0: michael@0: fuzzyMatch: function fuzzyMatch(aNumber1, aNumber2) { michael@0: let normalized1 = this.normalize(aNumber1); michael@0: let normalized2 = this.normalize(aNumber2); michael@0: if (DEBUG) debug("Normalized Number1: " + normalized1 + ", Number2: " + normalized2); michael@0: if (normalized1 === normalized2) { michael@0: return true; michael@0: } michael@0: let parsed1 = this.parse(aNumber1); michael@0: let parsed2 = this.parse(aNumber2); michael@0: if (parsed1 && parsed2) { michael@0: if ((parsed1.internationalNumber && parsed1.internationalNumber === parsed2.internationalNumber) michael@0: || (parsed1.nationalNumber && parsed1.nationalNumber === parsed2.nationalNumber)) { michael@0: return true; michael@0: } michael@0: } michael@0: let countryName = this.getCountryName(); michael@0: let ssPref = "dom.phonenumber.substringmatching." + countryName; michael@0: if (Services.prefs.getPrefType(ssPref) == Ci.nsIPrefBranch.PREF_INT) { michael@0: let val = Services.prefs.getIntPref(ssPref); michael@0: if (normalized1.length > val && normalized2.length > val michael@0: && normalized1.slice(-val) === normalized2.slice(-val)) { michael@0: return true; michael@0: } michael@0: } michael@0: return false; michael@0: }, michael@0: michael@0: receiveMessage: function(aMessage) { michael@0: if (DEBUG) debug("receiveMessage " + aMessage.name); michael@0: let mm = aMessage.target; michael@0: let msg = aMessage.data; michael@0: michael@0: switch (aMessage.name) { michael@0: case "PhoneNumberService:FuzzyMatch": michael@0: mm.sendAsyncMessage("PhoneNumberService:FuzzyMatch:Return:OK", { michael@0: requestID: msg.requestID, michael@0: result: this.fuzzyMatch(msg.options.number1, msg.options.number2) michael@0: }); michael@0: break; michael@0: default: michael@0: if (DEBUG) debug("WRONG MESSAGE NAME: " + aMessage.name); michael@0: } michael@0: } michael@0: }; michael@0: michael@0: let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime) michael@0: .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; michael@0: if (inParent) { michael@0: Cu.import("resource://gre/modules/PhoneNumber.jsm"); michael@0: XPCOMUtils.defineLazyServiceGetter(this, "ppmm", michael@0: "@mozilla.org/parentprocessmessagemanager;1", michael@0: "nsIMessageListenerManager"); michael@0: PhoneNumberUtils.init(); michael@0: } michael@0: