From 87836f506b5bb517ac7c353b8c4df7f9b9396724 Mon Sep 17 00:00:00 2001
From: Matthew Chen <matthew@signal.org>
Date: Thu, 20 Sep 2018 12:52:43 -0400
Subject: [PATCH] Move more singletons to SSKEnvironment.

---
 Signal/src/AppDelegate.m                      |  2 +
 .../ViewControllers/OWSTableViewController.h  |  3 +-
 SignalMessaging/environment/AppSetup.m        | 16 +++-
 .../src/Contacts/Threads/TSContactThread.h    |  5 +
 .../src/Contacts/Threads/TSContactThread.m    |  1 -
 .../src/Messages/OWSBlockingManager.h         |  2 +
 .../src/Messages/OWSBlockingManager.m         | 31 ++----
 .../src/Messages/OWSIdentityManager.h         |  1 +
 .../src/Messages/OWSIdentityManager.m         | 26 ++---
 .../src/Messages/OWSMessageManager.h          |  6 ++
 .../src/Messages/OWSMessageManager.m          | 95 ++++++++++---------
 .../src/Messages/OWSMessageSender.h           |  6 +-
 .../src/Messages/OWSMessageSender.m           | 31 +++---
 SignalServiceKit/src/SSKEnvironment.h         | 11 ++-
 SignalServiceKit/src/SSKEnvironment.m         | 12 +++
 .../src/Tests/MockSSKEnvironment.h            |  3 +
 .../src/Tests/MockSSKEnvironment.m            | 12 ++-
 17 files changed, 152 insertions(+), 111 deletions(-)

diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m
index 8fecc0b75..02b07b7b4 100644
--- a/Signal/src/AppDelegate.m
+++ b/Signal/src/AppDelegate.m
@@ -1080,6 +1080,8 @@ static NSTimeInterval launchStartedAt;
 
     [OWSBackup.sharedManager setup];
 
+    [SSKEnvironment.shared.messageManager startObserving];
+
 #ifdef DEBUG
     // Resume lazy restore.
     [OWSBackupLazyRestoreJob runAsync];
diff --git a/SignalMessaging/ViewControllers/OWSTableViewController.h b/SignalMessaging/ViewControllers/OWSTableViewController.h
index c90133e84..fb6fdac8f 100644
--- a/SignalMessaging/ViewControllers/OWSTableViewController.h
+++ b/SignalMessaging/ViewControllers/OWSTableViewController.h
@@ -55,7 +55,8 @@ typedef UITableViewCell *_Nonnull (^OWSTableCustomCellBlock)(void);
 + (UITableViewCell *)newCell;
 + (void)configureCell:(UITableViewCell *)cell;
 
-+ (OWSTableItem *)itemWithTitle:(NSString *)title actionBlock:(nullable OWSTableActionBlock)actionBlock;
++ (OWSTableItem *)itemWithTitle:(NSString *)title
+                    actionBlock:(nullable OWSTableActionBlock)actionBlock NS_SWIFT_NAME(init(title:actionBlock:));
 
 + (OWSTableItem *)itemWithCustomCell:(UITableViewCell *)customCell
                      customRowHeight:(CGFloat)customRowHeight
diff --git a/SignalMessaging/environment/AppSetup.m b/SignalMessaging/environment/AppSetup.m
index 96ed299ea..0a7f24601 100644
--- a/SignalMessaging/environment/AppSetup.m
+++ b/SignalMessaging/environment/AppSetup.m
@@ -10,6 +10,9 @@
 #import <SignalMessaging/OWSProfileManager.h>
 #import <SignalMessaging/SignalMessaging-Swift.h>
 #import <SignalServiceKit/OWSBackgroundTask.h>
+#import <SignalServiceKit/OWSBlockingManager.h>
+#import <SignalServiceKit/OWSIdentityManager.h>
+#import <SignalServiceKit/OWSMessageManager.h>
 #import <SignalServiceKit/OWSStorage.h>
 #import <SignalServiceKit/SSKEnvironment.h>
 
@@ -42,14 +45,16 @@ NS_ASSUME_NONNULL_BEGIN
         TSNetworkManager *networkManager = [[TSNetworkManager alloc] initDefault];
         OWSContactsManager *contactsManager = [[OWSContactsManager alloc] initWithPrimaryStorage:primaryStorage];
         ContactsUpdater *contactsUpdater = [ContactsUpdater new];
-        OWSMessageSender *messageSender = [[OWSMessageSender alloc] initWithNetworkManager:networkManager
-                                                                            primaryStorage:primaryStorage
-                                                                           contactsManager:contactsManager];
+        OWSMessageSender *messageSender = [[OWSMessageSender alloc] initWithPrimaryStorage:primaryStorage];
 
         OWSProfileManager *profileManager = [[OWSProfileManager alloc] initWithPrimaryStorage:primaryStorage
                                                                                 messageSender:messageSender
                                                                                networkManager:networkManager];
 
+        OWSMessageManager *messageManager = [[OWSMessageManager alloc] initWithPrimaryStorage:primaryStorage];
+        OWSBlockingManager *blockingManager = [[OWSBlockingManager alloc] initWithPrimaryStorage:primaryStorage];
+        OWSIdentityManager *identityManager = [[OWSIdentityManager alloc] initWithPrimaryStorage:primaryStorage];
+
         [Environment setShared:[[Environment alloc] initWithPreferences:preferences]];
 
         [SSKEnvironment setShared:[[SSKEnvironment alloc] initWithContactsManager:contactsManager
@@ -57,7 +62,10 @@ NS_ASSUME_NONNULL_BEGIN
                                                                    profileManager:profileManager
                                                                    primaryStorage:primaryStorage
                                                                   contactsUpdater:contactsUpdater
-                                                                   networkManager:networkManager]];
+                                                                   networkManager:networkManager
+                                                                   messageManager:messageManager
+                                                                  blockingManager:blockingManager
+                                                                  identityManager:identityManager]];
 
         appSpecificSingletonBlock();
 
diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h
index c0ac5c256..23c8dbace 100644
--- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.h
+++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.h
@@ -22,6 +22,11 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (NSString *)contactIdFromThreadId:(NSString *)threadId;
 
+// This is only exposed for tests.
+#ifdef DEBUG
++ (NSString *)threadIdFromContactId:(NSString *)contactId;
+#endif
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m
index 886ac6743..a6dc7cb03 100644
--- a/SignalServiceKit/src/Contacts/Threads/TSContactThread.m
+++ b/SignalServiceKit/src/Contacts/Threads/TSContactThread.m
@@ -83,7 +83,6 @@ NS_ASSUME_NONNULL_BEGIN
     return [SSKEnvironment.shared.contactsManager displayNameForPhoneIdentifier:self.contactIdentifier];
 }
 
-
 + (NSString *)threadIdFromContactId:(NSString *)contactId {
     return [TSContactThreadPrefix stringByAppendingString:contactId];
 }
diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.h b/SignalServiceKit/src/Messages/OWSBlockingManager.h
index 92fd681de..3280dd645 100644
--- a/SignalServiceKit/src/Messages/OWSBlockingManager.h
+++ b/SignalServiceKit/src/Messages/OWSBlockingManager.h
@@ -4,6 +4,7 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@class OWSPrimaryStorage;
 @class TSGroupModel;
 @class TSThread;
 
@@ -13,6 +14,7 @@ extern NSString *const kNSNotificationName_BlockListDidChange;
 @interface OWSBlockingManager : NSObject
 
 - (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage NS_DESIGNATED_INITIALIZER;
 
 + (instancetype)sharedManager;
 
diff --git a/SignalServiceKit/src/Messages/OWSBlockingManager.m b/SignalServiceKit/src/Messages/OWSBlockingManager.m
index 0454bf756..46c810e48 100644
--- a/SignalServiceKit/src/Messages/OWSBlockingManager.m
+++ b/SignalServiceKit/src/Messages/OWSBlockingManager.m
@@ -31,7 +31,6 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
 @interface OWSBlockingManager ()
 
 @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
-@property (nonatomic, readonly) OWSMessageSender *messageSender;
 
 // We don't store the phone numbers as instances of PhoneNumber to avoid
 // consistency issues between clients, but these should all be valid e164
@@ -47,24 +46,12 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
 
 + (instancetype)sharedManager
 {
-    static OWSBlockingManager *sharedMyManager = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        sharedMyManager = [[self alloc] initDefault];
-    });
-    return sharedMyManager;
-}
+    OWSAssertDebug(SSKEnvironment.shared.blockingManager);
 
-- (instancetype)initDefault
-{
-    OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
-    OWSMessageSender *messageSender = SSKEnvironment.shared.messageSender;
-
-    return [self initWithPrimaryStorage:primaryStorage messageSender:messageSender];
+    return SSKEnvironment.shared.blockingManager;
 }
 
 - (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
-                         messageSender:(OWSMessageSender *)messageSender
 {
     self = [super init];
 
@@ -73,17 +60,11 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
     }
 
     OWSAssertDebug(primaryStorage);
-    OWSAssertDebug(messageSender);
 
     _dbConnection = primaryStorage.newDatabaseConnection;
-    _messageSender = messageSender;
 
     OWSSingletonAssert();
 
-    // Register this manager with the message sender.
-    // This is a circular dependency.
-    [messageSender setBlockingManager:self];
-
     return self;
 }
 
@@ -100,8 +81,14 @@ NSString *const kOWSBlockingManager_SyncedBlockedGroupIdsKey = @"kOWSBlockingMan
                                                object:nil];
 }
 
-#pragma mark -
+- (OWSMessageSender *)messageSender
+{
+    OWSAssertDebug(SSKEnvironment.shared.messageSender);
 
+    return SSKEnvironment.shared.messageSender;
+}
+
+#pragma mark -
 
 - (BOOL)isThreadBlocked:(TSThread *)thread
 {
diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.h b/SignalServiceKit/src/Messages/OWSIdentityManager.h
index 6391af58d..26964853c 100644
--- a/SignalServiceKit/src/Messages/OWSIdentityManager.h
+++ b/SignalServiceKit/src/Messages/OWSIdentityManager.h
@@ -25,6 +25,7 @@ extern const NSUInteger kIdentityKeyLength;
 @interface OWSIdentityManager : NSObject <IdentityKeyStore>
 
 - (instancetype)init NS_UNAVAILABLE;
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage NS_DESIGNATED_INITIALIZER;
 
 + (instancetype)sharedManager;
 
diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.m b/SignalServiceKit/src/Messages/OWSIdentityManager.m
index 69e761ba2..922115dc8 100644
--- a/SignalServiceKit/src/Messages/OWSIdentityManager.m
+++ b/SignalServiceKit/src/Messages/OWSIdentityManager.m
@@ -58,7 +58,6 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
 
 @property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
 @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
-@property (nonatomic, readonly) OWSMessageSender *messageSender;
 
 @end
 
@@ -68,24 +67,12 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
 
 + (instancetype)sharedManager
 {
-    static OWSIdentityManager *sharedMyManager = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        sharedMyManager = [[self alloc] initDefault];
-    });
-    return sharedMyManager;
-}
-
-- (instancetype)initDefault
-{
-    OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
-    OWSMessageSender *messageSender = SSKEnvironment.shared.messageSender;
+    OWSAssertDebug(SSKEnvironment.shared.identityManager);
 
-    return [self initWithPrimaryStorage:primaryStorage messageSender:messageSender];
+    return SSKEnvironment.shared.identityManager;
 }
 
 - (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
-                         messageSender:(OWSMessageSender *)messageSender
 {
     self = [super init];
 
@@ -94,12 +81,10 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
     }
 
     OWSAssertDebug(primaryStorage);
-    OWSAssertDebug(messageSender);
 
     _primaryStorage = primaryStorage;
     _dbConnection = primaryStorage.newDatabaseConnection;
     self.dbConnection.objectCacheEnabled = NO;
-    _messageSender = messageSender;
 
     OWSSingletonAssert();
 
@@ -113,6 +98,13 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa
     [[NSNotificationCenter defaultCenter] removeObserver:self];
 }
 
+- (OWSMessageSender *)messageSender
+{
+    OWSAssertDebug(SSKEnvironment.shared.messageSender);
+
+    return SSKEnvironment.shared.messageSender;
+}
+
 - (void)observeNotifications
 {
     [[NSNotificationCenter defaultCenter] addObserver:self
diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.h b/SignalServiceKit/src/Messages/OWSMessageManager.h
index 5f297d773..0e7cd51e4 100644
--- a/SignalServiceKit/src/Messages/OWSMessageManager.h
+++ b/SignalServiceKit/src/Messages/OWSMessageManager.h
@@ -6,6 +6,7 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+@class OWSPrimaryStorage;
 @class SSKProtoEnvelope;
 @class TSThread;
 @class YapDatabaseReadWriteTransaction;
@@ -15,11 +16,16 @@ NS_ASSUME_NONNULL_BEGIN
 - (instancetype)init NS_UNAVAILABLE;
 + (instancetype)sharedManager;
 
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage NS_DESIGNATED_INITIALIZER;
+
 // processEnvelope: can be called from any thread.
 - (void)processEnvelope:(SSKProtoEnvelope *)envelope
           plaintextData:(NSData *_Nullable)plaintextData
             transaction:(YapDatabaseReadWriteTransaction *)transaction;
 
+// This should be invoked by the main app when the app is ready.
+- (void)startObserving;
+
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m
index f0354ab68..2ff730a52 100644
--- a/SignalServiceKit/src/Messages/OWSMessageManager.m
+++ b/SignalServiceKit/src/Messages/OWSMessageManager.m
@@ -54,15 +54,9 @@ NS_ASSUME_NONNULL_BEGIN
 
 @interface OWSMessageManager ()
 
-@property (nonatomic, readonly) id<OWSCallMessageHandler> callMessageHandler;
-@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
 @property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
-@property (nonatomic, readonly) OWSMessageSender *messageSender;
-@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
-@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
-@property (nonatomic, readonly) OWSIdentityManager *identityManager;
-@property (nonatomic, readonly) TSNetworkManager *networkManager;
 @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
+@property (nonatomic, readonly) OWSIncomingMessageFinder *incomingMessageFinder;
 
 @end
 
@@ -72,38 +66,12 @@ NS_ASSUME_NONNULL_BEGIN
 
 + (instancetype)sharedManager
 {
-    static OWSMessageManager *sharedMyManager = nil;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-        sharedMyManager = [[self alloc] initDefault];
-    });
-    return sharedMyManager;
-}
+    OWSAssertDebug(SSKEnvironment.shared.messageManager);
 
-- (instancetype)initDefault
-{
-    TSNetworkManager *networkManager = [TSNetworkManager sharedManager];
-    OWSPrimaryStorage *primaryStorage = [OWSPrimaryStorage sharedManager];
-    id<ContactsManagerProtocol> contactsManager = SSKEnvironment.shared.contactsManager;
-    id<OWSCallMessageHandler> callMessageHandler = SSKEnvironment.shared.callMessageHandler;
-    OWSIdentityManager *identityManager = [OWSIdentityManager sharedManager];
-    OWSMessageSender *messageSender = SSKEnvironment.shared.messageSender;
-
-
-    return [self initWithNetworkManager:networkManager
-                         primaryStorage:primaryStorage
-                     callMessageHandler:callMessageHandler
-                        contactsManager:contactsManager
-                        identityManager:identityManager
-                          messageSender:messageSender];
+    return SSKEnvironment.shared.messageManager;
 }
 
-- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
-                        primaryStorage:(OWSPrimaryStorage *)primaryStorage
-                    callMessageHandler:(id<OWSCallMessageHandler>)callMessageHandler
-                       contactsManager:(id<ContactsManagerProtocol>)contactsManager
-                       identityManager:(OWSIdentityManager *)identityManager
-                         messageSender:(OWSMessageSender *)messageSender
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
 {
     self = [super init];
 
@@ -112,24 +80,57 @@ NS_ASSUME_NONNULL_BEGIN
     }
 
     _primaryStorage = primaryStorage;
-    _networkManager = networkManager;
-    _callMessageHandler = callMessageHandler;
-    _contactsManager = contactsManager;
-    _identityManager = identityManager;
-    _messageSender = messageSender;
-
     _dbConnection = primaryStorage.newDatabaseConnection;
     _incomingMessageFinder = [[OWSIncomingMessageFinder alloc] initWithPrimaryStorage:primaryStorage];
-    _blockingManager = [OWSBlockingManager sharedManager];
 
     OWSSingletonAssert();
     OWSAssertDebug(CurrentAppContext().isMainApp);
 
-    [self startObserving];
-
     return self;
 }
 
+- (id<OWSCallMessageHandler>)callMessageHandler
+{
+    OWSAssertDebug(SSKEnvironment.shared.callMessageHandler);
+
+    return SSKEnvironment.shared.callMessageHandler;
+}
+
+- (id<ContactsManagerProtocol>)contactsManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.contactsManager);
+
+    return SSKEnvironment.shared.contactsManager;
+}
+
+- (OWSMessageSender *)messageSender
+{
+    OWSAssertDebug(SSKEnvironment.shared.messageSender);
+
+    return SSKEnvironment.shared.messageSender;
+}
+
+- (OWSBlockingManager *)blockingManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.blockingManager);
+
+    return SSKEnvironment.shared.blockingManager;
+}
+
+- (OWSIdentityManager *)identityManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.identityManager);
+
+    return SSKEnvironment.shared.identityManager;
+}
+
+- (TSNetworkManager *)networkManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.networkManager);
+
+    return SSKEnvironment.shared.networkManager;
+}
+
 - (void)startObserving
 {
     [[NSNotificationCenter defaultCenter] addObserver:self
@@ -162,7 +163,7 @@ NS_ASSUME_NONNULL_BEGIN
 {
     OWSAssertDebug(envelope);
 
-    return [_blockingManager isRecipientIdBlocked:envelope.source];
+    return [self.blockingManager isRecipientIdBlocked:envelope.source];
 }
 
 - (BOOL)isDataMessageBlocked:(SSKProtoDataMessage *)dataMessage envelope:(SSKProtoEnvelope *)envelope
@@ -825,7 +826,7 @@ NS_ASSUME_NONNULL_BEGIN
                 }];
         } else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeBlocked) {
             OWSLogInfo(@"Received request for block list");
-            [_blockingManager syncBlockList];
+            [self.blockingManager syncBlockList];
         } else if (syncMessage.request.type == SSKProtoSyncMessageRequestTypeConfiguration) {
             BOOL areReadReceiptsEnabled =
                 [[OWSReadReceiptManager sharedManager] areReadReceiptsEnabledWithTransaction:transaction];
diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.h b/SignalServiceKit/src/Messages/OWSMessageSender.h
index bdb91fad0..761bfa8fa 100644
--- a/SignalServiceKit/src/Messages/OWSMessageSender.h
+++ b/SignalServiceKit/src/Messages/OWSMessageSender.h
@@ -37,11 +37,7 @@ NS_SWIFT_NAME(MessageSender)
 
 - (instancetype)init NS_UNAVAILABLE;
 
-- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
-                        primaryStorage:(OWSPrimaryStorage *)primaryStorage
-                       contactsManager:(id<ContactsManagerProtocol>)contactsManager;
-
-- (void)setBlockingManager:(OWSBlockingManager *)blockingManager;
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage NS_DESIGNATED_INITIALIZER;
 
 /**
  * Send and resend text messages or resend messages with existing attachments.
diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m
index faf14ee2e..fc92b82e5 100644
--- a/SignalServiceKit/src/Messages/OWSMessageSender.m
+++ b/SignalServiceKit/src/Messages/OWSMessageSender.m
@@ -27,6 +27,7 @@
 #import "OWSRequestFactory.h"
 #import "OWSUploadOperation.h"
 #import "PreKeyBundle+jsonDict.h"
+#import "SSKEnvironment.h"
 #import "SignalRecipient.h"
 #import "TSAccountManager.h"
 #import "TSAttachmentStream.h"
@@ -200,29 +201,22 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
 
 @interface OWSMessageSender ()
 
-@property (nonatomic, readonly) TSNetworkManager *networkManager;
 @property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
-@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
 @property (nonatomic, readonly) YapDatabaseConnection *dbConnection;
-@property (nonatomic, readonly) id<ContactsManagerProtocol> contactsManager;
 @property (atomic, readonly) NSMutableDictionary<NSString *, NSOperationQueue *> *sendingQueueMap;
 
 @end
 
 @implementation OWSMessageSender
 
-- (instancetype)initWithNetworkManager:(TSNetworkManager *)networkManager
-                        primaryStorage:(OWSPrimaryStorage *)primaryStorage
-                       contactsManager:(id<ContactsManagerProtocol>)contactsManager
+- (instancetype)initWithPrimaryStorage:(OWSPrimaryStorage *)primaryStorage
 {
     self = [super init];
     if (!self) {
         return self;
     }
 
-    _networkManager = networkManager;
     _primaryStorage = primaryStorage;
-    _contactsManager = contactsManager;
     _sendingQueueMap = [NSMutableDictionary new];
     _dbConnection = primaryStorage.newDatabaseConnection;
 
@@ -231,12 +225,25 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException";
     return self;
 }
 
-- (void)setBlockingManager:(OWSBlockingManager *)blockingManager
+- (id<ContactsManagerProtocol>)contactsManager
 {
-    OWSAssertDebug(blockingManager);
-    OWSAssertDebug(!_blockingManager);
+    OWSAssertDebug(SSKEnvironment.shared.contactsManager);
 
-    _blockingManager = blockingManager;
+    return SSKEnvironment.shared.contactsManager;
+}
+
+- (OWSBlockingManager *)blockingManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.blockingManager);
+
+    return SSKEnvironment.shared.blockingManager;
+}
+
+- (TSNetworkManager *)networkManager
+{
+    OWSAssertDebug(SSKEnvironment.shared.networkManager);
+
+    return SSKEnvironment.shared.networkManager;
 }
 
 - (NSOperationQueue *)sendingQueueForMessage:(TSOutgoingMessage *)message
diff --git a/SignalServiceKit/src/SSKEnvironment.h b/SignalServiceKit/src/SSKEnvironment.h
index 5b9a04cd8..254ac307a 100644
--- a/SignalServiceKit/src/SSKEnvironment.h
+++ b/SignalServiceKit/src/SSKEnvironment.h
@@ -5,6 +5,9 @@
 NS_ASSUME_NONNULL_BEGIN
 
 @class ContactsUpdater;
+@class OWSBlockingManager;
+@class OWSIdentityManager;
+@class OWSMessageManager;
 @class OWSMessageSender;
 @class OWSPrimaryStorage;
 @class TSNetworkManager;
@@ -22,7 +25,10 @@ NS_ASSUME_NONNULL_BEGIN
                          profileManager:(id<ProfileManagerProtocol>)profileManager
                          primaryStorage:(OWSPrimaryStorage *)primaryStorage
                         contactsUpdater:(ContactsUpdater *)contactsUpdater
-                         networkManager:(TSNetworkManager *)networkManager NS_DESIGNATED_INITIALIZER;
+                         networkManager:(TSNetworkManager *)networkManager
+                         messageManager:(OWSMessageManager *)messageManager
+                        blockingManager:(OWSBlockingManager *)blockingManager
+                        identityManager:(OWSIdentityManager *)identityManager NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
 
@@ -41,6 +47,9 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic, readonly) OWSPrimaryStorage *primaryStorage;
 @property (nonatomic, readonly) ContactsUpdater *contactsUpdater;
 @property (nonatomic, readonly) TSNetworkManager *networkManager;
+@property (nonatomic, readonly) OWSMessageManager *messageManager;
+@property (nonatomic, readonly) OWSBlockingManager *blockingManager;
+@property (nonatomic, readonly) OWSIdentityManager *identityManager;
 
 // This property is configured after Environment is created.
 @property (atomic, nullable) id<OWSCallMessageHandler> callMessageHandler;
diff --git a/SignalServiceKit/src/SSKEnvironment.m b/SignalServiceKit/src/SSKEnvironment.m
index 61ba00cb0..8ccfd211e 100644
--- a/SignalServiceKit/src/SSKEnvironment.m
+++ b/SignalServiceKit/src/SSKEnvironment.m
@@ -18,6 +18,9 @@ static SSKEnvironment *sharedSSKEnvironment;
 @property (nonatomic) OWSPrimaryStorage *primaryStorage;
 @property (nonatomic) ContactsUpdater *contactsUpdater;
 @property (nonatomic) TSNetworkManager *networkManager;
+@property (nonatomic) OWSMessageManager *messageManager;
+@property (nonatomic) OWSBlockingManager *blockingManager;
+@property (nonatomic) OWSIdentityManager *identityManager;
 
 @end
 
@@ -35,6 +38,9 @@ static SSKEnvironment *sharedSSKEnvironment;
                          primaryStorage:(OWSPrimaryStorage *)primaryStorage
                         contactsUpdater:(ContactsUpdater *)contactsUpdater
                          networkManager:(TSNetworkManager *)networkManager
+                         messageManager:(OWSMessageManager *)messageManager
+                        blockingManager:(OWSBlockingManager *)blockingManager
+                        identityManager:(OWSIdentityManager *)identityManager
 {
     self = [super init];
     if (!self) {
@@ -47,6 +53,9 @@ static SSKEnvironment *sharedSSKEnvironment;
     OWSAssertDebug(primaryStorage);
     OWSAssertDebug(contactsUpdater);
     OWSAssertDebug(networkManager);
+    OWSAssertDebug(messageManager);
+    OWSAssertDebug(blockingManager);
+    OWSAssertDebug(identityManager);
 
     _contactsManager = contactsManager;
     _messageSender = messageSender;
@@ -54,6 +63,9 @@ static SSKEnvironment *sharedSSKEnvironment;
     _primaryStorage = primaryStorage;
     _contactsUpdater = contactsUpdater;
     _networkManager = networkManager;
+    _messageManager = messageManager;
+    _blockingManager = blockingManager;
+    _identityManager = identityManager;
 
     return self;
 }
diff --git a/SignalServiceKit/src/Tests/MockSSKEnvironment.h b/SignalServiceKit/src/Tests/MockSSKEnvironment.h
index 0d56d0a32..fe2443860 100644
--- a/SignalServiceKit/src/Tests/MockSSKEnvironment.h
+++ b/SignalServiceKit/src/Tests/MockSSKEnvironment.h
@@ -18,6 +18,9 @@ NS_ASSUME_NONNULL_BEGIN
 @property (nonatomic) OWSPrimaryStorage *primaryStorage;
 @property (nonatomic) ContactsUpdater *contactsUpdater;
 @property (nonatomic) TSNetworkManager *networkManager;
+@property (nonatomic) OWSMessageManager *messageManager;
+@property (nonatomic) OWSBlockingManager *blockingManager;
+@property (nonatomic) OWSIdentityManager *identityManager;
 
 @end
 
diff --git a/SignalServiceKit/src/Tests/MockSSKEnvironment.m b/SignalServiceKit/src/Tests/MockSSKEnvironment.m
index 5f7fac71b..35ceca78d 100644
--- a/SignalServiceKit/src/Tests/MockSSKEnvironment.m
+++ b/SignalServiceKit/src/Tests/MockSSKEnvironment.m
@@ -3,6 +3,7 @@
 //
 
 #import "MockSSKEnvironment.h"
+#import "OWSBlockingManager.h"
 #import "OWSFakeCallMessageHandler.h"
 #import "OWSFakeContactsManager.h"
 #import "OWSFakeContactsUpdater.h"
@@ -10,6 +11,8 @@
 #import "OWSFakeNetworkManager.h"
 #import "OWSFakeNotificationsManager.h"
 #import "OWSFakeProfileManager.h"
+#import "OWSIdentityManager.h"
+#import "OWSMessageManager.h"
 #import "OWSPrimaryStorage.h"
 
 NS_ASSUME_NONNULL_BEGIN
@@ -39,12 +42,19 @@ NS_ASSUME_NONNULL_BEGIN
     TSNetworkManager *networkManager = [OWSFakeNetworkManager new];
     OWSMessageSender *messageSender = [OWSFakeMessageSender new];
 
+    OWSMessageManager *messageManager = [[OWSMessageManager alloc] initWithPrimaryStorage:primaryStorage];
+    OWSBlockingManager *blockingManager = [[OWSBlockingManager alloc] initWithPrimaryStorage:primaryStorage];
+    OWSIdentityManager *identityManager = [[OWSIdentityManager alloc] initWithPrimaryStorage:primaryStorage];
+
     self = [super initWithContactsManager:contactsManager
                             messageSender:messageSender
                            profileManager:[OWSFakeProfileManager new]
                            primaryStorage:primaryStorage
                           contactsUpdater:[OWSFakeContactsUpdater new]
-                           networkManager:networkManager];
+                           networkManager:networkManager
+                           messageManager:messageManager
+                          blockingManager:blockingManager
+                          identityManager:identityManager];
     if (!self) {
         return nil;
     }