Ensure thread safety in phone parsing logic.

pull/1/head
Matthew Chen 7 years ago
parent 4bf08280dc
commit 043218fb91

@ -40,7 +40,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
OWSAssert(text != nil); OWSAssert(text != nil);
OWSAssert(regionCode != nil); OWSAssert(regionCode != nil);
PhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedUtil]; PhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedThreadLocal];
NSError *parseError = nil; NSError *parseError = nil;
NBPhoneNumber *number = [phoneUtil parse:text defaultRegion:regionCode error:&parseError]; NBPhoneNumber *number = [phoneUtil parse:text defaultRegion:regionCode error:&parseError];
@ -71,7 +71,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
NSString *_Nullable countryCode = nil; NSString *_Nullable countryCode = nil;
#if TARGET_OS_IPHONE #if TARGET_OS_IPHONE
countryCode = [[PhoneNumberUtil sharedUtil].nbPhoneNumberUtil countryCodeByCarrier]; countryCode = [[PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil countryCodeByCarrier];
if ([countryCode isEqualToString:@"ZZ"]) { if ([countryCode isEqualToString:@"ZZ"]) {
countryCode = [locale objectForKey:NSLocaleCountryCode]; countryCode = [locale objectForKey:NSLocaleCountryCode];
@ -164,7 +164,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
} }
+ (NSString *)regionCodeFromCountryCodeString:(NSString *)countryCodeString { + (NSString *)regionCodeFromCountryCodeString:(NSString *)countryCodeString {
NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedUtil].nbPhoneNumberUtil; NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil;
NSString *regionCode = NSString *regionCode =
[phoneUtil getRegionCodeForCountryCode:@([[countryCodeString substringFromIndex:1] integerValue])]; [phoneUtil getRegionCodeForCountryCode:@([[countryCodeString substringFromIndex:1] integerValue])];
return regionCode; return regionCode;
@ -381,11 +381,11 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
} }
- (BOOL)isValid { - (BOOL)isValid {
return [[PhoneNumberUtil sharedUtil].nbPhoneNumberUtil isValidNumber:self.phoneNumber]; return [[PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil isValidNumber:self.phoneNumber];
} }
- (NSString *)localizedDescriptionForUser { - (NSString *)localizedDescriptionForUser {
NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedUtil].nbPhoneNumberUtil; NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedThreadLocal].nbPhoneNumberUtil;
NSError *formatError = nil; NSError *formatError = nil;
NSString *pretty = NSString *pretty =

@ -1,14 +1,18 @@
// //
// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
#import <libPhoneNumber_iOS/NBPhoneNumberUtil.h>
#import "PhoneNumber.h" #import "PhoneNumber.h"
#import <libPhoneNumber_iOS/NBPhoneNumberUtil.h>
@interface PhoneNumberUtil : NSObject @interface PhoneNumberUtil : NSObject
@property (nonatomic, retain) NBPhoneNumberUtil *nbPhoneNumberUtil; @property (nonatomic, retain) NBPhoneNumberUtil *nbPhoneNumberUtil;
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)sharedThreadLocal;
+ (BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString; + (BOOL)name:(NSString *)nameString matchesQuery:(NSString *)queryString;
+ (NSString *)callingCodeFromCountryCode:(NSString *)countryCode; + (NSString *)callingCodeFromCountryCode:(NSString *)countryCode;
@ -28,8 +32,6 @@
+ (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode; + (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode;
+ (instancetype)sharedUtil;
- (NBPhoneNumber *)parse:(NSString *)numberToParse defaultRegion:(NSString *)defaultRegion error:(NSError **)error; - (NBPhoneNumber *)parse:(NSString *)numberToParse defaultRegion:(NSString *)defaultRegion error:(NSError **)error;
- (NSString *)format:(NBPhoneNumber *)phoneNumber - (NSString *)format:(NBPhoneNumber *)phoneNumber
numberFormat:(NBEPhoneNumberFormat)numberFormat numberFormat:(NBEPhoneNumberFormat)numberFormat

@ -1,5 +1,5 @@
// //
// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // Copyright (c) 2018 Open Whisper Systems. All rights reserved.
// //
#import "PhoneNumberUtil.h" #import "PhoneNumberUtil.h"
@ -18,13 +18,28 @@
@implementation PhoneNumberUtil @implementation PhoneNumberUtil
+ (instancetype)sharedUtil { + (NSObject *)sharedLock
{
static dispatch_once_t onceToken; static dispatch_once_t onceToken;
static id sharedInstance = nil; static NSObject *lock = nil;
dispatch_once(&onceToken, ^{ dispatch_once(&onceToken, ^{
sharedInstance = [self.class new]; lock = [NSObject new];
}); });
return sharedInstance; return lock;
}
+ (PhoneNumberUtil *)sharedThreadLocal
{
@synchronized(self.sharedLock)
{
NSString *key = PhoneNumberUtil.logTag;
PhoneNumberUtil *_Nullable threadLocal = NSThread.currentThread.threadDictionary[key];
if (!threadLocal) {
threadLocal = [PhoneNumberUtil new];
NSThread.currentThread.threadDictionary[key] = threadLocal;
}
return threadLocal;
}
} }
- (instancetype)init { - (instancetype)init {
@ -138,9 +153,10 @@
return @"+1"; return @"+1";
} }
NSString *callingCode = [NSString stringWithFormat:@"%@%@", NSString *callingCode =
[NSString stringWithFormat:@"%@%@",
COUNTRY_CODE_PREFIX, COUNTRY_CODE_PREFIX,
[[[self sharedUtil] nbPhoneNumberUtil] getCountryCodeForRegion:countryCode]]; [[[self sharedThreadLocal] nbPhoneNumberUtil] getCountryCodeForRegion:countryCode]];
return callingCode; return callingCode;
} }
@ -578,25 +594,23 @@
+ (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode + (NSString *)examplePhoneNumberForCountryCode:(NSString *)countryCode
{ {
PhoneNumberUtil *sharedUtil = [self sharedThreadLocal];
// Signal users are very likely using mobile devices, so prefer that kind of example. // Signal users are very likely using mobile devices, so prefer that kind of example.
NSError *error; NSError *error;
NBPhoneNumber *nbPhoneNumber = NBPhoneNumber *nbPhoneNumber =
[[[self sharedUtil] nbPhoneNumberUtil] getExampleNumberForType:countryCode [sharedUtil.nbPhoneNumberUtil getExampleNumberForType:countryCode type:NBEPhoneNumberTypeMOBILE error:&error];
type:NBEPhoneNumberTypeMOBILE
error:&error];
OWSAssert(!error); OWSAssert(!error);
if (!nbPhoneNumber) { if (!nbPhoneNumber) {
// For countries that with similar mobile and land lines, use "line or mobile" // For countries that with similar mobile and land lines, use "line or mobile"
// examples. // examples.
nbPhoneNumber = nbPhoneNumber = [sharedUtil.nbPhoneNumberUtil getExampleNumberForType:countryCode
[[[self sharedUtil] nbPhoneNumberUtil] getExampleNumberForType:countryCode
type:NBEPhoneNumberTypeFIXED_LINE_OR_MOBILE type:NBEPhoneNumberTypeFIXED_LINE_OR_MOBILE
error:&error]; error:&error];
OWSAssert(!error); OWSAssert(!error);
} }
NSString *result = (nbPhoneNumber ? [[[self sharedUtil] nbPhoneNumberUtil] format:nbPhoneNumber NSString *result = (nbPhoneNumber
numberFormat:NBEPhoneNumberFormatE164 ? [sharedUtil.nbPhoneNumberUtil format:nbPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:&error]
error:&error]
: nil); : nil);
OWSAssert(!error); OWSAssert(!error);
return result; return result;

Loading…
Cancel
Save