diff --git a/src/Account/TSAccountManager.h b/src/Account/TSAccountManager.h index 63673a450..a9ca71119 100644 --- a/src/Account/TSAccountManager.h +++ b/src/Account/TSAccountManager.h @@ -1,9 +1,5 @@ // -// TSAccountManagement.h -// TextSecureKit -// -// Created by Frederic Jacobs on 27/10/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // #import @@ -21,6 +17,8 @@ static NSString *const TSRegistrationErrorUserInfoHTTPStatus = @"TSHTTPStatus"; #pragma mark - Initializers +- (instancetype)init NS_UNAVAILABLE; + - (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager storageManager:(TSStorageManager *)storageManager; diff --git a/src/Account/TSAccountManager.m b/src/Account/TSAccountManager.m index 0fbc7d8b7..63125df58 100644 --- a/src/Account/TSAccountManager.m +++ b/src/Account/TSAccountManager.m @@ -35,6 +35,8 @@ NS_ASSUME_NONNULL_BEGIN _networkManager = networkManager; _storageManager = storageManager; + OWSSingletonAssert(); + return self; } diff --git a/src/Account/TSPrivacyPreferences.h b/src/Account/TSPrivacyPreferences.h index c334db853..47c9af719 100644 --- a/src/Account/TSPrivacyPreferences.h +++ b/src/Account/TSPrivacyPreferences.h @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 11/7/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "TSYapDatabaseObject.h" @@ -7,6 +8,8 @@ NS_ASSUME_NONNULL_BEGIN @interface TSPrivacyPreferences : TSYapDatabaseObject +- (instancetype)init NS_UNAVAILABLE; + + (instancetype)sharedInstance; @property BOOL shouldBlockOnIdentityChange; diff --git a/src/Account/TSPrivacyPreferences.m b/src/Account/TSPrivacyPreferences.m index 635e8097a..fe3aa7054 100644 --- a/src/Account/TSPrivacyPreferences.m +++ b/src/Account/TSPrivacyPreferences.m @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 11/7/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// #import "TSPrivacyPreferences.h" @@ -37,6 +38,8 @@ NSString *const TSPrivacyPreferencesSingletonKey = @"TSPrivacyPreferences"; _shouldBlockOnIdentityChange = shouldBlockOnIdentityChange; + OWSSingletonAssert(); + return self; } diff --git a/src/Contacts/ContactsUpdater.m b/src/Contacts/ContactsUpdater.m index c2c22ce7f..daae4123b 100644 --- a/src/Contacts/ContactsUpdater.m +++ b/src/Contacts/ContactsUpdater.m @@ -25,6 +25,19 @@ NS_ASSUME_NONNULL_BEGIN return sharedInstance; } + +- (instancetype)init +{ + self = [super init]; + if (!self) { + return self; + } + + OWSSingletonAssert(); + + return self; +} + - (nullable SignalRecipient *)synchronousLookup:(NSString *)identifier error:(NSError **)error { dispatch_semaphore_t sema = dispatch_semaphore_create(0); diff --git a/src/Contacts/PhoneNumberUtil.m b/src/Contacts/PhoneNumberUtil.m index 63783da23..a54921d64 100644 --- a/src/Contacts/PhoneNumberUtil.m +++ b/src/Contacts/PhoneNumberUtil.m @@ -23,6 +23,8 @@ if (self) { _nbPhoneNumberUtil = [[NBPhoneNumberUtil alloc] init]; + + OWSSingletonAssert(); } return self; diff --git a/src/Messages/OWSMessageSender.h b/src/Messages/OWSMessageSender.h index 76b0a4ba4..7d8c865bf 100644 --- a/src/Messages/OWSMessageSender.h +++ b/src/Messages/OWSMessageSender.h @@ -1,5 +1,6 @@ -// Created by Michael Kirk on 10/7/16. -// Copyright © 2016 Open Whisper Systems. All rights reserved. +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// NS_ASSUME_NONNULL_BEGIN @@ -23,6 +24,8 @@ NS_SWIFT_NAME(MessageSender) ContactsUpdater *_contactsUpdater; } +- (instancetype)init NS_UNAVAILABLE; + - (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager storageManager:(TSStorageManager *)storageManager contactsManager:(id)contactsManager diff --git a/src/Messages/OWSMessageSender.m b/src/Messages/OWSMessageSender.m index c1c168c73..136f59c9b 100644 --- a/src/Messages/OWSMessageSender.m +++ b/src/Messages/OWSMessageSender.m @@ -288,6 +288,8 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; _dbConnection = storageManager.newDatabaseConnection; _disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager]; + OWSSingletonAssert(); + return self; } diff --git a/src/Messages/TSBlockingManager.m b/src/Messages/TSBlockingManager.m index 032c3dc96..c10357402 100644 --- a/src/Messages/TSBlockingManager.m +++ b/src/Messages/TSBlockingManager.m @@ -66,6 +66,8 @@ NSString *const kTSStorageManager_SyncedBlockedPhoneNumbersKey = @"kTSStorageMan _storageManager = storageManager; _messageSender = messageSender; + OWSSingletonAssert(); + return self; } diff --git a/src/Messages/TSMessagesManager.m b/src/Messages/TSMessagesManager.m index 2f660901e..4ea23fc6d 100644 --- a/src/Messages/TSMessagesManager.m +++ b/src/Messages/TSMessagesManager.m @@ -105,7 +105,9 @@ NS_ASSUME_NONNULL_BEGIN _disappearingMessagesJob = [[OWSDisappearingMessagesJob alloc] initWithStorageManager:storageManager]; _incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithDatabase:storageManager.database]; _blockingManager = [TSBlockingManager sharedManager]; - + + OWSSingletonAssert(); + return self; } diff --git a/src/Network/API/TSNetworkManager.h b/src/Network/API/TSNetworkManager.h index 08da37b94..62f06e3d3 100644 --- a/src/Network/API/TSNetworkManager.h +++ b/src/Network/API/TSNetworkManager.h @@ -28,6 +28,8 @@ NS_ASSUME_NONNULL_BEGIN @interface TSNetworkManager : NSObject +- (instancetype)init NS_UNAVAILABLE; + + (id)sharedManager; - (void)makeRequest:(TSRequest *)request diff --git a/src/Network/API/TSNetworkManager.m b/src/Network/API/TSNetworkManager.m index b79bb609a..e5e5bbc85 100644 --- a/src/Network/API/TSNetworkManager.m +++ b/src/Network/API/TSNetworkManager.m @@ -43,6 +43,8 @@ typedef void (^failureBlock)(NSURLSessionDataTask *task, NSError *error); _signalService = signalService; + OWSSingletonAssert(); + return self; } diff --git a/src/Network/WebSockets/TSSocketManager.h b/src/Network/WebSockets/TSSocketManager.h index 9a6e81457..079eea6a2 100644 --- a/src/Network/WebSockets/TSSocketManager.h +++ b/src/Network/WebSockets/TSSocketManager.h @@ -1,9 +1,5 @@ // -// TSSocketManager.h -// TextSecureiOS -// -// Created by Frederic Jacobs on 17/05/14. -// Copyright (c) 2014 Open Whisper Systems. All rights reserved. +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. // #import @@ -23,6 +19,8 @@ extern NSString *const SocketConnectingNotification; @interface TSSocketManager : NSObject +- (instancetype)init NS_UNAVAILABLE; + + (void)becomeActiveFromForeground; + (void)becomeActiveFromBackgroundExpectMessage:(BOOL)expected; diff --git a/src/Network/WebSockets/TSSocketManager.m b/src/Network/WebSockets/TSSocketManager.m index 68404d339..83a2ad4a0 100644 --- a/src/Network/WebSockets/TSSocketManager.m +++ b/src/Network/WebSockets/TSSocketManager.m @@ -61,6 +61,8 @@ NSString *const SocketConnectingNotification = @"SocketConnectingNotification"; [self addObserver:self forKeyPath:@"status" options:0 context:kSocketStatusObservationContext]; + OWSSingletonAssert(); + return self; } diff --git a/src/Storage/TSStorageManager.h b/src/Storage/TSStorageManager.h index 08f41e367..a0c9be407 100644 --- a/src/Storage/TSStorageManager.h +++ b/src/Storage/TSStorageManager.h @@ -16,6 +16,8 @@ extern NSString *const TSUIDatabaseConnectionDidUpdateNotification; @interface TSStorageManager : NSObject +- (instancetype)init NS_UNAVAILABLE; + + (instancetype)sharedManager; /** diff --git a/src/Storage/TSStorageManager.m b/src/Storage/TSStorageManager.m index eaca489b8..ace86f0a2 100644 --- a/src/Storage/TSStorageManager.m +++ b/src/Storage/TSStorageManager.m @@ -129,6 +129,8 @@ static NSString *keychainDBPassAccount = @"TSDatabasePass"; [NSException raise:TSStorageManagerExceptionNameNoDatabase format:@"Failed to initialize database."]; } + + OWSSingletonAssert(); } return self; diff --git a/src/Util/Asserts.h b/src/Util/Asserts.h index d0cfbc728..6ec08413e 100755 --- a/src/Util/Asserts.h +++ b/src/Util/Asserts.h @@ -35,3 +35,37 @@ NSCAssert(0, @"Assertion failed: %s", CONVERT_EXPR_TO_STRING(X)); \ #endif #endif + +#pragma mark - Singleton Asserts + +// The "singleton asserts" can be used to ensure +// that we only create a singleton once. +// +// The simplest way to use them is the OWSSingletonAssert() macro. +// It is intended to be used inside the singleton's initializer. +// +// If, however, a singleton has multiple possible initializers, +// you need to: +// +// 1. Use OWSSingletonAssertFlag() outside the class definition. +// 2. Use OWSSingletonAssertInit() in each initializer. +#ifdef DEBUG + +#define OWSSingletonAssertFlag() static BOOL _isSingletonCreated = NO; + +#define OWSSingletonAssertInit() \ + @synchronized([self class]) \ + { \ + OWSAssert(!_isSingletonCreated); \ + _isSingletonCreated = YES; \ + } + +#define OWSSingletonAssert() OWSSingletonAssertFlag() OWSSingletonAssertInit() + +#else + +#define OWSSingletonAssertFlag() +#define OWSSingletonAssertInit() +#define OWSSingletonAssert() + +#endif