DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */

"use strict";

this.EXPORTED_SYMBOLS = ["PhoneNumberUtils"];

const DEBUG = false;
function debug(s) { if(DEBUG) dump("-*- PhoneNumberutils: " + s + "\n"); }

const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;

Cu.import("resource://gre/modules/Services.jsm");
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this, "PhoneNumberNormalizer",
                                  "resource://gre/modules/PhoneNumberNormalizer.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "MCC_ISO3166_TABLE",
                                  "resource://gre/modules/mcc_iso3166_table.jsm");

#ifdef MOZ_B2G_RIL
XPCOMUtils.defineLazyServiceGetter(this, "mobileConnection",
                                   "@mozilla.org/ril/content-helper;1",
                                   "nsIMobileConnectionProvider");
XPCOMUtils.defineLazyServiceGetter(this, "icc",
                                   "@mozilla.org/ril/content-helper;1",
                                   "nsIIccProvider");
#endif

this.PhoneNumberUtils = {
  init: function() {
    ppmm.addMessageListener(["PhoneNumberService:FuzzyMatch"], this);
  },
  //  1. See whether we have a network mcc
  //  2. If we don't have that, look for the simcard mcc
  //  3. If we don't have that or its 0 (not activated), pick up the last used mcc
  //  4. If we don't have, default to some mcc

  // mcc for Brasil
  _mcc: '724',

  getCountryName: function getCountryName() {
    let mcc;
    let countryName;

#ifdef MOZ_B2G_RIL
    // TODO: Bug 926740 - PhoneNumberUtils for multisim
    // In Multi-sim, there is more than one client in 
    // iccProvider/mobileConnectionProvider. Each client represents a
    // icc/mobileConnection service. To maintain the backward compatibility with
    // single sim, we always use client 0 for now. Adding support for multiple
    // sim will be addressed in bug 926740, if needed.
    let clientId = 0;

    // Get network mcc
    let voice = mobileConnection.getVoiceConnectionInfo(clientId);
    if (voice && voice.network && voice.network.mcc) {
      mcc = voice.network.mcc;
    }

    // Get SIM mcc
    let iccInfo = icc.getIccInfo(clientId);
    if (!mcc && iccInfo && iccInfo.mcc) {
      mcc = iccInfo.mcc;
    }

    // Attempt to grab last known sim mcc from prefs
    if (!mcc) {
      try {
        mcc = Services.prefs.getCharPref("ril.lastKnownSimMcc");
      } catch (e) {}
    }

    // Set to default mcc
    if (!mcc) {
      mcc = this._mcc;
    }
#else

    // Attempt to grab last known sim mcc from prefs
    if (!mcc) {
      try {
        mcc = Services.prefs.getCharPref("ril.lastKnownSimMcc");
      } catch (e) {}
    }

    if (!mcc) {
      mcc = this._mcc;
    }
#endif

    countryName = MCC_ISO3166_TABLE[mcc];
    if (DEBUG) debug("MCC: " + mcc + "countryName: " + countryName);
    return countryName;
  },

  parse: function(aNumber) {
    if (DEBUG) debug("call parse: " + aNumber);
    let result = PhoneNumber.Parse(aNumber, this.getCountryName());

    if (result) {
      let countryName = result.countryName || this.getCountryName();
      let number = null;
      if (countryName) {
        if (Services.prefs.getPrefType("dom.phonenumber.substringmatching." + countryName) == Ci.nsIPrefBranch.PREF_INT) {
          let val = Services.prefs.getIntPref("dom.phonenumber.substringmatching." + countryName);
          if (val) {
            number = result.internationalNumber || result.nationalNumber;
            if (number && number.length > val) {
              number = number.slice(-val);
            }
          }
        }
      }
      Object.defineProperty(result, "nationalMatchingFormat", { value: number, enumerable: true });
      if (DEBUG) {
        debug("InternationalFormat: " + result.internationalFormat);
        debug("InternationalNumber: " + result.internationalNumber);
        debug("NationalNumber: " + result.nationalNumber);
        debug("NationalFormat: " + result.nationalFormat);
        debug("CountryName: " + result.countryName);
        debug("NationalMatchingFormat: " + result.nationalMatchingFormat);
      }
    } else if (DEBUG) {
      debug("NO PARSING RESULT!");
    }
    return result;
  },

  parseWithMCC: function(aNumber, aMCC) {
    let countryName = MCC_ISO3166_TABLE[aMCC];
    if (DEBUG) debug("found country name: " + countryName);
    return PhoneNumber.Parse(aNumber, countryName);
  },

  parseWithCountryName: function(aNumber, countryName) {
    return PhoneNumber.Parse(aNumber, countryName);
  },

  isPlainPhoneNumber: function isPlainPhoneNumber(aNumber) {
    var isPlain = PhoneNumber.IsPlain(aNumber);
    if (DEBUG) debug("isPlain(" + aNumber + ") " + isPlain);
    return isPlain;
  },

  normalize: function Normalize(aNumber, aNumbersOnly) {
    let normalized = PhoneNumberNormalizer.Normalize(aNumber, aNumbersOnly);
    if (DEBUG) debug("normalize(" + aNumber + "): " + normalized + ", " + aNumbersOnly);
    return normalized;
  },

  fuzzyMatch: function fuzzyMatch(aNumber1, aNumber2) {
    let normalized1 = this.normalize(aNumber1);
    let normalized2 = this.normalize(aNumber2);
    if (DEBUG) debug("Normalized Number1: " + normalized1 + ", Number2: " + normalized2);
    if (normalized1 === normalized2) {
      return true;
    }
    let parsed1 = this.parse(aNumber1);
    let parsed2 = this.parse(aNumber2);
    if (parsed1 && parsed2) {
      if ((parsed1.internationalNumber && parsed1.internationalNumber === parsed2.internationalNumber)
          || (parsed1.nationalNumber && parsed1.nationalNumber === parsed2.nationalNumber)) {
        return true;
      }
    }
    let countryName = this.getCountryName();
    let ssPref = "dom.phonenumber.substringmatching." + countryName;
    if (Services.prefs.getPrefType(ssPref) == Ci.nsIPrefBranch.PREF_INT) {
      let val = Services.prefs.getIntPref(ssPref);
      if (normalized1.length > val && normalized2.length > val
         && normalized1.slice(-val) === normalized2.slice(-val)) {
        return true;
      }
    }
    return false;
  },

  receiveMessage: function(aMessage) {
    if (DEBUG) debug("receiveMessage " + aMessage.name);
    let mm = aMessage.target;
    let msg = aMessage.data;

    switch (aMessage.name) {
      case "PhoneNumberService:FuzzyMatch":
        mm.sendAsyncMessage("PhoneNumberService:FuzzyMatch:Return:OK", {
          requestID: msg.requestID,
          result: this.fuzzyMatch(msg.options.number1, msg.options.number2)
        });
        break;
      default:
        if (DEBUG) debug("WRONG MESSAGE NAME: " + aMessage.name);
    }
  }
};

let inParent = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime)
                 .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
if (inParent) {
  XPCOMUtils.defineLazyModuleGetter(this, "PhoneNumber",
                                    "resource://gre/modules/PhoneNumber.jsm");
  XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
                                     "@mozilla.org/parentprocessmessagemanager;1",
                                     "nsIMessageListenerManager");
  PhoneNumberUtils.init();
}