diff --git a/b2g/installer/package-manifest.in b/b2g/installer/package-manifest.in index a463c201dc7d..08a44acdff0c 100644 --- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -348,6 +348,8 @@ @BINPATH@/components/BrowserElementParent.js @BINPATH@/components/ContactManager.js @BINPATH@/components/ContactManager.manifest +@BINPATH@/components/PhoneNumberService.js +@BINPATH@/components/PhoneNumberService.manifest @BINPATH@/components/PermissionSettings.js @BINPATH@/components/PermissionSettings.manifest @BINPATH@/components/PermissionPromptService.js diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in index be663761d41f..28b51cf46ad9 100644 --- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -520,6 +520,8 @@ @BINPATH@/components/PermissionSettings.manifest @BINPATH@/components/ContactManager.js @BINPATH@/components/ContactManager.manifest +@BINPATH@/components/PhoneNumberService.js +@BINPATH@/components/PhoneNumberService.manifest @BINPATH@/components/AlarmsManager.js @BINPATH@/components/AlarmsManager.manifest @BINPATH@/components/Push.js diff --git a/dom/apps/src/PermissionsTable.jsm b/dom/apps/src/PermissionsTable.jsm index ffe2bb6d6de0..52d627ed6f11 100644 --- a/dom/apps/src/PermissionsTable.jsm +++ b/dom/apps/src/PermissionsTable.jsm @@ -145,6 +145,11 @@ this.PermissionsTable = { geolocation: { privileged: DENY_ACTION, certified: ALLOW_ACTION }, + phonenumberservice: { + app: DENY_ACTION, + privileged: DENY_ACTION, + certified: ALLOW_ACTION + }, fmradio: { app: DENY_ACTION, privileged: ALLOW_ACTION, diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index 0fd5a18ff5ea..28a3a6f56d3e 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -1602,6 +1602,14 @@ Navigator::HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal) return win && PowerManager::CheckPermission(win); } +/* static */ +bool +Navigator::HasPhoneNumberSupport(JSContext* /* unused */, JSObject* aGlobal) +{ + nsCOMPtr win = GetWindowFromGlobal(aGlobal); + return CheckPermission(win, "phonenumberservice"); +} + /* static */ bool Navigator::HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal) diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 1bac15c4796b..b603ef71f378 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -256,6 +256,7 @@ public: // WebIDL helper methods static bool HasBatterySupport(JSContext* /* unused*/, JSObject* /*unused */); static bool HasPowerSupport(JSContext* /* unused */, JSObject* aGlobal); + static bool HasPhoneNumberSupport(JSContext* /* unused */, JSObject* aGlobal); static bool HasIdleSupport(JSContext* /* unused */, JSObject* aGlobal); static bool HasWakeLockSupport(JSContext* /* unused*/, JSObject* /*unused */); static bool HasDesktopNotificationSupport(JSContext* /* unused*/, diff --git a/dom/phonenumberutils/PhoneNumber.jsm b/dom/phonenumberutils/PhoneNumber.jsm index b10db4a5c615..70879189e72c 100644 --- a/dom/phonenumberutils/PhoneNumber.jsm +++ b/dom/phonenumberutils/PhoneNumber.jsm @@ -9,19 +9,18 @@ this.EXPORTED_SYMBOLS = ["PhoneNumber"]; Components.utils.import("resource://gre/modules/PhoneNumberMetaData.jsm"); +Components.utils.import("resource://gre/modules/PhoneNumberNormalizer.jsm"); this.PhoneNumber = (function (dataBase) { // Use strict in our context only - users might not want it 'use strict'; const MAX_PHONE_NUMBER_LENGTH = 50; - const UNICODE_DIGITS = /[\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9]/g; const NON_ALPHA_CHARS = /[^a-zA-Z]/g; const NON_DIALABLE_CHARS = /[^,#+\*\d]/g; const NON_DIALABLE_CHARS_ONCE = new RegExp(NON_DIALABLE_CHARS.source); const BACKSLASH = /\\/g; const SPLIT_FIRST_GROUP = /^(\d+)(.*)$/; - const VALID_ALPHA_PATTERN = /[a-zA-Z]/g; const LEADING_PLUS_CHARS_PATTERN = /^[+\uFF0B]+/g; // Format of the string encoded meta data. If the name contains "^" or "$" @@ -225,40 +224,6 @@ this.PhoneNumber = (function (dataBase) { } }; - // Map letters to numbers according to the ITU E.161 standard - var E161 = { - 'a': 2, 'b': 2, 'c': 2, - 'd': 3, 'e': 3, 'f': 3, - 'g': 4, 'h': 4, 'i': 4, - 'j': 5, 'k': 5, 'l': 5, - 'm': 6, 'n': 6, 'o': 6, - 'p': 7, 'q': 7, 'r': 7, 's': 7, - 't': 8, 'u': 8, 'v': 8, - 'w': 9, 'x': 9, 'y': 9, 'z': 9 - }; - - // Normalize a number by converting unicode numbers and symbols to their - // ASCII equivalents and removing all non-dialable characters. - function NormalizeNumber(number, numbersOnly) { - if (typeof number !== 'string') { - return ''; - } - - number = number.replace(UNICODE_DIGITS, - function (ch) { - return String.fromCharCode(48 + (ch.charCodeAt(0) & 0xf)); - }); - if (!numbersOnly) { - number = number.replace(VALID_ALPHA_PATTERN, - function (ch) { - return String(E161[ch.toLowerCase()] || 0); - }); - } - number = number.replace(LEADING_PLUS_CHARS_PATTERN, "+"); - number = number.replace(NON_DIALABLE_CHARS, ""); - return number; - } - // Check whether the number is valid for the given region. function IsValidNumber(number, md) { return md.possiblePattern.test(number); @@ -329,7 +294,7 @@ this.PhoneNumber = (function (dataBase) { var ret; // Remove formating characters and whitespace. - number = NormalizeNumber(number); + number = PhoneNumberNormalizer.Normalize(number); // If there is no defaultRegion, we can't parse international access codes. if (!defaultRegion && number[0] !== '+') @@ -404,6 +369,5 @@ this.PhoneNumber = (function (dataBase) { return { IsPlain: IsPlainPhoneNumber, Parse: ParseNumber, - Normalize: NormalizeNumber }; })(PHONE_NUMBER_META_DATA); diff --git a/dom/phonenumberutils/PhoneNumberNormalizer.jsm b/dom/phonenumberutils/PhoneNumberNormalizer.jsm new file mode 100644 index 000000000000..863ebdc24748 --- /dev/null +++ b/dom/phonenumberutils/PhoneNumberNormalizer.jsm @@ -0,0 +1,55 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +// Don't modify this code. Please use: +// https://github.com/andreasgal/PhoneNumber.js + +"use strict"; + +this.EXPORTED_SYMBOLS = ["PhoneNumberNormalizer"]; + +this.PhoneNumberNormalizer = (function() { + const UNICODE_DIGITS = /[\uFF10-\uFF19\u0660-\u0669\u06F0-\u06F9]/g; + const VALID_ALPHA_PATTERN = /[a-zA-Z]/g; + const LEADING_PLUS_CHARS_PATTERN = /^[+\uFF0B]+/g; + const NON_DIALABLE_CHARS = /[^,#+\*\d]/g; + + // Map letters to numbers according to the ITU E.161 standard + var E161 = { + 'a': 2, 'b': 2, 'c': 2, + 'd': 3, 'e': 3, 'f': 3, + 'g': 4, 'h': 4, 'i': 4, + 'j': 5, 'k': 5, 'l': 5, + 'm': 6, 'n': 6, 'o': 6, + 'p': 7, 'q': 7, 'r': 7, 's': 7, + 't': 8, 'u': 8, 'v': 8, + 'w': 9, 'x': 9, 'y': 9, 'z': 9 + }; + + // Normalize a number by converting unicode numbers and symbols to their + // ASCII equivalents and removing all non-dialable characters. + function NormalizeNumber(number, numbersOnly) { + if (typeof number !== 'string') { + return ''; + } + + number = number.replace(UNICODE_DIGITS, + function (ch) { + return String.fromCharCode(48 + (ch.charCodeAt(0) & 0xf)); + }); + if (!numbersOnly) { + number = number.replace(VALID_ALPHA_PATTERN, + function (ch) { + return String(E161[ch.toLowerCase()] || 0); + }); + } + number = number.replace(LEADING_PLUS_CHARS_PATTERN, "+"); + number = number.replace(NON_DIALABLE_CHARS, ""); + return number; + }; + + + return { + Normalize: NormalizeNumber + }; +})(); \ No newline at end of file diff --git a/dom/phonenumberutils/PhoneNumberService.js b/dom/phonenumberutils/PhoneNumberService.js new file mode 100644 index 000000000000..f71c1026cbd0 --- /dev/null +++ b/dom/phonenumberutils/PhoneNumberService.js @@ -0,0 +1,97 @@ +/* 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 DEBUG = false; +function debug(s) { dump("-*- PhoneNumberService.js: " + s + "\n"); } + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cu = Components.utils; + +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); +Cu.import("resource://gre/modules/PhoneNumberUtils.jsm"); +Cu.import("resource://gre/modules/PhoneNumberNormalizer.jsm"); + +XPCOMUtils.defineLazyServiceGetter(this, "cpmm", + "@mozilla.org/childprocessmessagemanager;1", + "nsIMessageSender"); + +// PhoneNumberService + +function PhoneNumberService() +{ + if (DEBUG) debug("Constructor"); +} + +PhoneNumberService.prototype = { + __proto__: DOMRequestIpcHelper.prototype, + + receiveMessage: function(aMessage) { + if (DEBUG) debug("receiveMessage: " + aMessage.name); + let msg = aMessage.json; + + let req = this.getRequest(msg.requestID); + if (!req) { + return; + } + + switch (aMessage.name) { + case "PhoneNumberService:FuzzyMatch:Return:KO": + Services.DOMRequest.fireError(req.request, msg.errorMsg); + break; + case "PhoneNumberService:FuzzyMatch:Return:OK": + Services.DOMRequest.fireSuccess(req.request, msg.result); + break; + default: + if (DEBUG) debug("Wrong message: " + aMessage.name); + } + this.removeRequest(msg.requestID); + }, + + fuzzyMatch: function(aNumber1, aNumber2) { + if (DEBUG) debug("fuzzyMatch: " + aNumber1 + ", " + aNumber2); + let request = this.createRequest(); + + if ((aNumber1 && !aNumber2) || (aNumber2 && !aNumber1)) { + // if only one of the numbers is empty/null/undefined and the other + // number is not, we can fire false result in next tick + Services.DOMRequest.fireSuccessAsync(request, false); + } else if ((aNumber1 === aNumber2) || + (PhoneNumberNormalizer.Normalize(aNumber1) === PhoneNumberNormalizer.Normalize(aNumber2))) { + // if we have a simple match fire successful request in next tick + Services.DOMRequest.fireSuccessAsync(request, true); + } else { + // invoke fuzzy matching in the parent + let options = { number1: aNumber1, number2: aNumber2 }; + cpmm.sendAsyncMessage("PhoneNumberService:FuzzyMatch", + {requestID: this.getRequestId({request: request}), + options: options}); + } + + return request; + }, + + normalize: function(aNumber) { + if (DEBUG) debug("normalize: " + aNumber); + return PhoneNumberNormalizer.Normalize(aNumber); + }, + + init: function(aWindow) { + if (DEBUG) debug("init call"); + this.initDOMRequestHelper(aWindow, [ + "PhoneNumberService:FuzzyMatch:Return:OK", + "PhoneNumberService:FuzzyMatch:Return:KO" + ]); + }, + + classID : Components.ID("{e2768710-eb17-11e2-91e2-0800200c9a66}"), + contractID : "@mozilla.org/phoneNumberService;1", + QueryInterface : XPCOMUtils.generateQI([Ci.nsIDOMGlobalPropertyInitializer]), +} + +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PhoneNumberService]); diff --git a/dom/phonenumberutils/PhoneNumberService.manifest b/dom/phonenumberutils/PhoneNumberService.manifest new file mode 100644 index 000000000000..6e84e50257f7 --- /dev/null +++ b/dom/phonenumberutils/PhoneNumberService.manifest @@ -0,0 +1,2 @@ +component {e2768710-eb17-11e2-91e2-0800200c9a66} PhoneNumberService.js +contract @mozilla.org/phoneNumberService;1 {e2768710-eb17-11e2-91e2-0800200c9a66} \ No newline at end of file diff --git a/dom/phonenumberutils/PhoneNumberUtils.jsm b/dom/phonenumberutils/PhoneNumberUtils.jsm index 484b6921999d..020f7c10c4db 100644 --- a/dom/phonenumberutils/PhoneNumberUtils.jsm +++ b/dom/phonenumberutils/PhoneNumberUtils.jsm @@ -9,10 +9,12 @@ 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'); -Cu.import("resource://gre/modules/PhoneNumber.jsm"); +Cu.import("resource://gre/modules/PhoneNumberNormalizer.jsm"); Cu.import("resource://gre/modules/mcc_iso3166_table.jsm"); #ifdef MOZ_B2G_RIL @@ -22,6 +24,9 @@ XPCOMUtils.defineLazyServiceGetter(this, "mobileConnection", #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 @@ -96,8 +101,62 @@ this.PhoneNumberUtils = { }, normalize: function Normalize(aNumber, aNumbersOnly) { - var normalized = PhoneNumber.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 === parsed2.internationalNumber + || 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.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) { + Cu.import("resource://gre/modules/PhoneNumber.jsm"); + XPCOMUtils.defineLazyServiceGetter(this, "ppmm", + "@mozilla.org/parentprocessmessagemanager;1", + "nsIMessageListenerManager"); + PhoneNumberUtils.init(); +} + diff --git a/dom/phonenumberutils/moz.build b/dom/phonenumberutils/moz.build index 66f2b5c72b65..4203f35a5bbe 100644 --- a/dom/phonenumberutils/moz.build +++ b/dom/phonenumberutils/moz.build @@ -6,13 +6,18 @@ TEST_DIRS += ['tests'] +EXTRA_COMPONENTS += [ + 'PhoneNumberService.js', + 'PhoneNumberService.manifest', +] + EXTRA_JS_MODULES += [ 'PhoneNumber.jsm', 'PhoneNumberMetaData.jsm', + 'PhoneNumberNormalizer.jsm', 'mcc_iso3166_table.jsm', ] EXTRA_PP_JS_MODULES += [ 'PhoneNumberUtils.jsm', ] - diff --git a/dom/phonenumberutils/tests/Makefile.in b/dom/phonenumberutils/tests/Makefile.in index 2d9ffe1dfc5d..4f12284fca3b 100644 --- a/dom/phonenumberutils/tests/Makefile.in +++ b/dom/phonenumberutils/tests/Makefile.in @@ -11,9 +11,14 @@ relativesrcdir = @relativesrcdir@ include $(DEPTH)/config/autoconf.mk +MOCHITEST_FILES = \ + test_phonenumberutils_basics.html \ + $(NULL) + MOCHITEST_CHROME_FILES = \ test_phonenumber.xul \ test_phonenumberutils.xul \ + test_phonenumberservice.xul \ $(NULL) include $(topsrcdir)/config/rules.mk diff --git a/dom/phonenumberutils/tests/test_phonenumber.xul b/dom/phonenumberutils/tests/test_phonenumber.xul index f7f49d705ae8..cad6b7a083eb 100644 --- a/dom/phonenumberutils/tests/test_phonenumber.xul +++ b/dom/phonenumberutils/tests/test_phonenumber.xul @@ -21,6 +21,7 @@ "use strict"; Components.utils.import("resource://gre/modules/PhoneNumber.jsm"); +Components.utils.import("resource://gre/modules/PhoneNumberNormalizer.jsm"); function IsPlain(dial, expected) { var result = PhoneNumber.IsPlain(dial); @@ -32,7 +33,7 @@ function IsPlain(dial, expected) { } function Normalize(dial, expected) { - var result = PhoneNumber.Normalize(dial); + var result = PhoneNumberNormalizer.Normalize(dial); if (result !== expected) { ok(false, "normalized " + dial + " to " + result + ", expected " + expected + " instead."); } else { @@ -41,7 +42,7 @@ function Normalize(dial, expected) { } function Normalize(dial, expected) { - var result = PhoneNumber.Normalize(dial); + var result = PhoneNumberNormalizer.Normalize(dial); if (result != expected) { ok(false, "Normalize error!\n"); print("expected: " + expected); diff --git a/dom/phonenumberutils/tests/test_phonenumberservice.xul b/dom/phonenumberutils/tests/test_phonenumberservice.xul new file mode 100644 index 000000000000..20fd2b43d93e --- /dev/null +++ b/dom/phonenumberutils/tests/test_phonenumberservice.xul @@ -0,0 +1,158 @@ + + + + + + + + + + diff --git a/dom/phonenumberutils/tests/test_phonenumberutils.xul b/dom/phonenumberutils/tests/test_phonenumberutils.xul index 838a9e8233ed..f2a1059a3e69 100644 --- a/dom/phonenumberutils/tests/test_phonenumberutils.xul +++ b/dom/phonenumberutils/tests/test_phonenumberutils.xul @@ -20,8 +20,12 @@ "use strict"; +Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource://gre/modules/PhoneNumberUtils.jsm"); +Services.prefs.setIntPref("dom.phonenumber.substringmatching.BR", 8); +Services.prefs.setCharPref("ril.lastKnownSimMcc", "310"); + function CantParseWithMcc(dial, mcc) { var result = PhoneNumberUtils.parseWithMCC(dial, mcc); if (result) { @@ -43,6 +47,11 @@ function ParseWithMcc(dial, mcc) { } } +function FuzzyMatch(number1, number2, expect) { + var result = PhoneNumberUtils.fuzzyMatch(number1, number2); + is(result, expect, "FuzzyMatch OK!"); +} + // Unknown mcc CantParseWithMcc("1234", 123); ParseWithMcc("4165555555", 302); @@ -50,5 +59,10 @@ ParseWithMcc("4165555555", 302); is(PhoneNumberUtils.normalize("123abc", true), "123", "NumbersOnly"); is(PhoneNumberUtils.normalize("123abc", false), "123222", "NumbersOnly"); +FuzzyMatch("123abc", "123222", true); +FuzzyMatch("123456789", "123456789", true); +FuzzyMatch("111", null, false); +FuzzyMatch("+552155555555", "2155555555", true); +FuzzyMatch("aaa123456789", "zzzzz123456789", true); diff --git a/dom/phonenumberutils/tests/test_phonenumberutils_basics.html b/dom/phonenumberutils/tests/test_phonenumberutils_basics.html new file mode 100644 index 000000000000..5c5772fa3885 --- /dev/null +++ b/dom/phonenumberutils/tests/test_phonenumberutils_basics.html @@ -0,0 +1,32 @@ + + + + + Test for Bug 883923 PhoneNumberUtils FuzzyMatch + + + + + + +Mozilla Bug 883923 +

+ +
+
+
+ + diff --git a/dom/webidl/PhoneNumberService.webidl b/dom/webidl/PhoneNumberService.webidl new file mode 100644 index 000000000000..6e3db45d5696 --- /dev/null +++ b/dom/webidl/PhoneNumberService.webidl @@ -0,0 +1,15 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. + */ + +[JSImplementation="@mozilla.org/phoneNumberService;1", NavigatorProperty="mozPhoneNumberService"] +interface PhoneNumberService { + + [Func="Navigator::HasPhoneNumberSupport"] + DOMRequest fuzzyMatch([TreatNullAs=EmptyString, TreatUndefinedAs=EmptyString] DOMString number1, [TreatNullAs=EmptyString, TreatUndefinedAs=EmptyString] DOMString number2); + + [Func="Navigator::HasPhoneNumberSupport"] + DOMString normalize(DOMString number); +}; diff --git a/dom/webidl/WebIDL.mk b/dom/webidl/WebIDL.mk index 0484d79dbe59..ac85c2f1db35 100644 --- a/dom/webidl/WebIDL.mk +++ b/dom/webidl/WebIDL.mk @@ -224,6 +224,7 @@ webidl_files = \ PerformanceNavigation.webidl \ PerformanceTiming.webidl \ PeriodicWave.webidl \ + PhoneNumberService.webidl \ Plugin.webidl \ PluginArray.webidl \ Position.webidl \ diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index b1ae77d27997..4f64f3d7f57c 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -283,6 +283,8 @@ @BINPATH@/components/ConsoleAPI.js @BINPATH@/components/ContactManager.js @BINPATH@/components/ContactManager.manifest +@BINPATH@/components/PhoneNumberService.js +@BINPATH@/components/PhoneNumberService.manifest @BINPATH@/components/SettingsManager.js @BINPATH@/components/SettingsManager.manifest @BINPATH@/components/SettingsService.js