migrate OWSSyncManager from objective-c to swift

This commit is contained in:
Ehren Kret 2024-03-09 08:25:04 -06:00
parent 59b5d96196
commit c5daaa3966
9 changed files with 114 additions and 221 deletions

View File

@ -230,8 +230,6 @@
346129A51FD1F09100532771 /* OWSContactsManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 346129A21FD1F09100532771 /* OWSContactsManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 346129A31FD1F09100532771 /* OWSContactsManager.m */; };
346129AF1FD1F5D900532771 /* SystemContactsFetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346129AE1FD1F5D900532771 /* SystemContactsFetcher.swift */; };
34612A061FD7238600532771 /* OWSSyncManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 34612A041FD7238500532771 /* OWSSyncManager.h */; settings = {ATTRIBUTES = (Public, ); }; };
34612A071FD7238600532771 /* OWSSyncManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 34612A051FD7238500532771 /* OWSSyncManager.m */; };
34635330256EA52A003C5428 /* ConversationViewTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3463532E256EA525003C5428 /* ConversationViewTest.swift */; };
34635332257549F2003C5428 /* CVReactionCountsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34635331257549F1003C5428 /* CVReactionCountsView.swift */; };
3465947E2434CCC100E5C510 /* NewGroupConfirmViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3465947D2434CCC100E5C510 /* NewGroupConfirmViewController.swift */; };
@ -2863,8 +2861,6 @@
346129AE1FD1F5D900532771 /* SystemContactsFetcher.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SystemContactsFetcher.swift; sourceTree = "<group>"; };
346129B11FD1F7E800532771 /* OWSProfileManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSProfileManager.h; sourceTree = "<group>"; };
346129B21FD1F7E800532771 /* OWSProfileManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSProfileManager.m; sourceTree = "<group>"; };
34612A041FD7238500532771 /* OWSSyncManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSSyncManager.h; sourceTree = "<group>"; };
34612A051FD7238500532771 /* OWSSyncManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSSyncManager.m; sourceTree = "<group>"; };
3463532E256EA525003C5428 /* ConversationViewTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConversationViewTest.swift; sourceTree = "<group>"; };
34635331257549F1003C5428 /* CVReactionCountsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CVReactionCountsView.swift; sourceTree = "<group>"; };
34641E172088D7E900E2EDE5 /* ScreenLock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScreenLock.swift; sourceTree = "<group>"; };
@ -5895,8 +5891,6 @@
346129A21FD1F09100532771 /* OWSContactsManager.h */,
346129A31FD1F09100532771 /* OWSContactsManager.m */,
3498A0A524DC81E100CA492C /* OWSContactsManager.swift */,
34612A041FD7238500532771 /* OWSSyncManager.h */,
34612A051FD7238500532771 /* OWSSyncManager.m */,
885C354F2370DFD50004BA35 /* OWSSyncManager.swift */,
50CB431B298860C700841A34 /* SystemContactsDataProvider.swift */,
346129AE1FD1F5D900532771 /* SystemContactsFetcher.swift */,
@ -10983,7 +10977,6 @@
buildActionMask = 2147483647;
files = (
346129A51FD1F09100532771 /* OWSContactsManager.h in Headers */,
34612A061FD7238600532771 /* OWSSyncManager.h in Headers */,
34480B5B1FD0A7E300BC14EF /* SignalMessaging-Prefix.pch in Headers */,
453518961FC63DBF00210559 /* SignalMessaging.h in Headers */,
);
@ -12427,7 +12420,6 @@
346129A61FD1F09100532771 /* OWSContactsManager.m in Sources */,
3498A0A624DC81E100CA492C /* OWSContactsManager.swift in Sources */,
4C046AA7236148880035B234 /* OWSGroupSyncProcessingJobQueue.swift in Sources */,
34612A071FD7238600532771 /* OWSSyncManager.m in Sources */,
885C35502370DFD50004BA35 /* OWSSyncManager.swift in Sources */,
3474C57526111605006723D2 /* PaymentsCurrenciesImpl.swift in Sources */,
3465F4DB27287859001663AF /* PaymentsHelperImpl.swift in Sources */,

View File

@ -284,7 +284,7 @@ public class ProvisioningCoordinatorImpl: ProvisioningCoordinator {
// TODO: 90 days after all primaries include the master key in every
// provisioning message, we can make it non-optional and remove this
// branch entirely.
async let syncDidComplete: Void = NotificationCenter.default.observeOnce(.OWSSyncManagerKeysSyncDidComplete)
async let syncDidComplete: Void = NotificationCenter.default.observeOnce(.syncManagerKeysSyncDidComplete)
async let requestKeys: Void = self.db.awaitableWrite { tx in
self.syncManager.sendKeysSyncRequestMessage(tx: tx)

View File

@ -19,7 +19,7 @@ class ChatsSettingsViewController: OWSTableViewController2 {
NotificationCenter.default.addObserver(
self,
selector: #selector(updateTableContents),
name: .OWSSyncManagerConfigurationSyncDidComplete,
name: .syncManagerConfigurationSyncDidComplete,
object: nil
)
}

View File

@ -32,7 +32,7 @@ class AdvancedPrivacySettingsViewController: OWSTableViewController2 {
NotificationCenter.default.addObserver(
self,
selector: #selector(updateTableContents),
name: .OWSSyncManagerConfigurationSyncDidComplete,
name: .syncManagerConfigurationSyncDidComplete,
object: nil
)
NotificationCenter.default.addObserver(

View File

@ -17,7 +17,7 @@ class PrivacySettingsViewController: OWSTableViewController2 {
NotificationCenter.default.addObserver(
self,
selector: #selector(updateTableContents),
name: .OWSSyncManagerConfigurationSyncDidComplete,
name: .syncManagerConfigurationSyncDidComplete,
object: nil
)
}

View File

@ -13,4 +13,3 @@ FOUNDATION_EXPORT const unsigned char SignalMessagingVersionString[];
// The public headers of the framework
#import <SignalMessaging/OWSContactsManager.h>
#import <SignalMessaging/OWSSyncManager.h>

View File

@ -1,35 +0,0 @@
//
// Copyright 2017 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
extern NSString *const OWSSyncManagerConfigurationSyncDidCompleteNotification;
extern NSString *const OWSSyncManagerKeysSyncDidCompleteNotification;
@class AnyPromise;
@class OWSContactsManager;
@class OWSIdentityManager;
@class OWSProfileManager;
@class SDSKeyValueStore;
@protocol SyncManagerProtocol;
@protocol SyncManagerProtocolObjc;
@interface OWSSyncManager : NSObject <SyncManagerProtocolObjc>
+ (SDSKeyValueStore *)keyValueStore;
+ (instancetype)new NS_UNAVAILABLE;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initDefault NS_DESIGNATED_INITIALIZER;
@property (nonatomic) BOOL isRequestInFlight;
@end
NS_ASSUME_NONNULL_END

View File

@ -1,161 +0,0 @@
//
// Copyright 2017 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
//
#import "OWSSyncManager.h"
#import "OWSContactsManager.h"
#import "OWSProfileManager.h"
#import <Contacts/Contacts.h>
#import <SignalCoreKit/Cryptography.h>
#import <SignalMessaging/SignalMessaging-Swift.h>
#import <SignalServiceKit/AppReadiness.h>
#import <SignalServiceKit/DataSource.h>
#import <SignalServiceKit/MIMETypeUtil.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/OWSReceiptManager.h>
#import <SignalServiceKit/OWSSyncConfigurationMessage.h>
#import <SignalServiceKit/OWSSyncFetchLatestMessage.h>
#import <SignalServiceKit/OWSSyncKeysMessage.h>
#import <SignalServiceKit/OWSSyncRequestMessage.h>
#import <SignalServiceKit/SignalServiceKit-Swift.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const OWSSyncManagerConfigurationSyncDidCompleteNotification = @"OWSSyncManagerConfigurationSyncDidCompleteNotification";
NSString *const OWSSyncManagerKeysSyncDidCompleteNotification = @"OWSSyncManagerKeysSyncDidCompleteNotification";
@interface OWSSyncManager ()
@end
#pragma mark -
@implementation OWSSyncManager
+ (SDSKeyValueStore *)keyValueStore
{
return [[SDSKeyValueStore alloc] initWithCollection:@"kTSStorageManagerOWSSyncManagerCollection"];
}
#pragma mark -
- (instancetype)initDefault {
self = [super init];
if (!self) {
return self;
}
OWSSingletonAssert();
AppReadinessRunNowOrWhenMainAppDidBecomeReadyAsync(^{
[self addObservers];
if ([TSAccountManagerObjcBridge isRegisteredWithMaybeTransaction]) {
OWSAssertDebug(self.contactsManagerImpl.isSetup);
if ([TSAccountManagerObjcBridge isPrimaryDeviceWithMaybeTransaction]) {
// syncAllContactsIfNecessary will skip if nothing has changed,
// so this won't yield redundant traffic.
[self syncAllContactsIfNecessary];
} else {
[self sendAllSyncRequestMessagesIfNecessary].catch(
^(NSError *error) { OWSLogError(@"Error: %@.", error); });
}
}
});
return self;
}
- (void)addObservers {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(signalAccountsDidChange:)
name:OWSContactsManagerSignalAccountsDidChangeNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(profileKeyDidChange:)
name:UserProfileNotifications.localProfileKeyDidChange
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(registrationStateDidChange)
name:[RegistrationStateChangeNotifications registrationStateDidChange]
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(willEnterForeground:)
name:OWSApplicationWillEnterForegroundNotification
object:nil];
}
#pragma mark - Notifications
- (void)signalAccountsDidChange:(id)notification {
OWSAssertIsOnMainThread();
[self syncAllContactsIfNecessary];
}
- (void)profileKeyDidChange:(id)notification {
OWSAssertIsOnMainThread();
[self syncAllContactsIfNecessary];
}
- (void)registrationStateDidChange
{
OWSAssertIsOnMainThread();
[self syncAllContactsIfNecessary];
}
- (void)willEnterForeground:(id)notificaiton
{
OWSAssertIsOnMainThread();
// If the user foregrounds the app, check for pending NSE requests.
(void)[self syncAllContactsIfFullSyncRequested];
}
#pragma mark - Methods
- (void)processIncomingConfigurationSyncMessage:(SSKProtoSyncMessageConfiguration *)syncMessage transaction:(SDSAnyWriteTransaction *)transaction
{
if (syncMessage.hasReadReceipts) {
[SSKEnvironment.shared.receiptManager setAreReadReceiptsEnabled:syncMessage.readReceipts
transaction:transaction];
}
if (syncMessage.hasUnidentifiedDeliveryIndicators) {
BOOL updatedValue = syncMessage.unidentifiedDeliveryIndicators;
[self.preferences setShouldShowUnidentifiedDeliveryIndicators:updatedValue transaction:transaction];
}
if (syncMessage.hasTypingIndicators) {
[self.typingIndicatorsImpl setTypingIndicatorsEnabledWithValue:syncMessage.typingIndicators
transaction:transaction];
}
if (syncMessage.hasLinkPreviews) {
[SSKPreferences setAreLinkPreviewsEnabled:syncMessage.linkPreviews
sendSyncMessage:NO
transaction:transaction];
}
[transaction addAsyncCompletionOffMain:^{
[[NSNotificationCenter defaultCenter] postNotificationNameAsync:OWSSyncManagerConfigurationSyncDidCompleteNotification
object:nil];
}];
}
- (void)processIncomingContactsSyncMessage:(SSKProtoSyncMessageContacts *)syncMessage transaction:(SDSAnyWriteTransaction *)transaction
{
TSAttachmentPointer *attachmentPointer = [TSAttachmentPointer attachmentPointerFromProto:syncMessage.blob
albumMessage:nil];
[attachmentPointer anyInsertWithTransaction:transaction];
[self.smJobQueues.incomingContactSyncJobQueue addWithAttachmentId:attachmentPointer.uniqueId
isComplete:syncMessage.isComplete
transaction:transaction];
}
@end
NS_ASSUME_NONNULL_END

View File

@ -8,6 +8,104 @@ import Foundation
import LibSignalClient
import SignalServiceKit
extension Notification.Name {
public static let syncManagerConfigurationSyncDidComplete = Notification.Name("OWSSyncManagerConfigurationSyncDidCompleteNotification")
public static let syncManagerKeysSyncDidComplete = Notification.Name("OWSSyncManagerKeysSyncDidCompleteNotification")
}
@objc
public class OWSSyncManager: NSObject, SyncManagerProtocolObjc {
private static var keyValueStore: SDSKeyValueStore {
SDSKeyValueStore(collection: "kTSStorageManagerOWSSyncManagerCollection")
}
private var isRequestInFlight: Bool = false
init(default: Void) {
super.init()
SwiftSingletons.register(self)
AppReadiness.runNowOrWhenMainAppDidBecomeReadyAsync {
self.addObservers()
if TSAccountManagerObjcBridge.isRegisteredWithMaybeTransaction {
owsAssertDebug(self.contactsManagerImpl.isSetup)
if TSAccountManagerObjcBridge.isPrimaryDeviceWithMaybeTransaction {
// syncAllContactsIfNecessary will skip if nothing has changed,
// so this won't yield redundant traffic.
self.syncAllContactsIfNecessary()
} else {
self.sendAllSyncRequestMessagesIfNecessary().catch { (_ error: Error) in
Logger.error("Error: \(error).")
}
}
}
}
}
private func addObservers() {
NotificationCenter.default.addObserver(self, selector: #selector(signalAccountsDidChange(_:)), name: .OWSContactsManagerSignalAccountsDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(profileKeyDidChange(_:)), name: UserProfileNotifications.localProfileKeyDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(registrationStateDidChange(_:)), name: RegistrationStateChangeNotifications.registrationStateDidChange, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: .OWSApplicationWillEnterForeground, object: nil)
}
// MARK: - Notifications
@objc
private func signalAccountsDidChange(_ notification: AnyObject) {
AssertIsOnMainThread()
syncAllContactsIfNecessary()
}
@objc
private func profileKeyDidChange(_ notification: AnyObject) {
AssertIsOnMainThread()
syncAllContactsIfNecessary()
}
@objc
private func registrationStateDidChange(_ notification: AnyObject) {
AssertIsOnMainThread()
syncAllContactsIfNecessary()
}
@objc
private func willEnterForeground(_ notification: AnyObject) {
AssertIsOnMainThread()
_ = syncAllContactsIfFullSyncRequested()
}
// MARK: - SyncManagerProtocolObjc methods
public func processIncomingConfigurationSyncMessage(_ syncMessage: SSKProtoSyncMessageConfiguration, transaction: SDSAnyWriteTransaction) {
if syncMessage.hasReadReceipts {
SSKEnvironment.shared.receiptManager.setAreReadReceiptsEnabled(syncMessage.readReceipts, transaction: transaction)
}
if syncMessage.hasUnidentifiedDeliveryIndicators {
let updatedValue = syncMessage.unidentifiedDeliveryIndicators
self.preferences.setShouldShowUnidentifiedDeliveryIndicators(updatedValue, transaction: transaction)
}
if syncMessage.hasTypingIndicators {
self.typingIndicatorsImpl.setTypingIndicatorsEnabled(value: syncMessage.typingIndicators, transaction: transaction)
}
if syncMessage.hasLinkPreviews {
SSKPreferences.setAreLinkPreviewsEnabled(syncMessage.linkPreviews, transaction: transaction)
}
transaction.addAsyncCompletionOffMain {
NotificationCenter.default.postNotificationNameAsync(.syncManagerConfigurationSyncDidComplete, object: nil)
}
}
public func processIncomingContactsSyncMessage(_ syncMessage: SSKProtoSyncMessageContacts, transaction: SDSAnyWriteTransaction) {
guard let attachmentPointer = TSAttachmentPointer(fromProto: syncMessage.blob, albumMessage: nil) else {
owsFailDebug("failed to create attachment pointer from incoming contacts sync message")
return
}
attachmentPointer.anyInsert(transaction: transaction)
self.smJobQueues.incomingContactSyncJobQueue.add(attachmentId: attachmentPointer.uniqueId, isComplete: syncMessage.isComplete, transaction: transaction)
}
}
extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
// MARK: - Constants
@ -39,7 +137,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
return databaseStorage.write(.promise) { (transaction) -> Promise<Void> in
let currentAppVersion = AppVersionImpl.shared.currentAppVersion
let syncRequestedAppVersion = {
Self.keyValueStore().getString(
Self.keyValueStore.getString(
Constants.syncRequestedAppVersionKey,
transaction: transaction
)
@ -56,7 +154,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
self.sendSyncRequestMessage(.contacts, transaction: transaction)
self.sendSyncRequestMessage(.keys, transaction: transaction)
Self.keyValueStore().setString(
Self.keyValueStore.setString(
currentAppVersion,
key: Constants.syncRequestedAppVersionKey,
transaction: transaction
@ -64,9 +162,9 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
return Promise.when(fulfilled: [
NotificationCenter.default.observe(once: .incomingContactSyncDidComplete).asVoid(),
NotificationCenter.default.observe(once: .OWSSyncManagerConfigurationSyncDidComplete).asVoid(),
NotificationCenter.default.observe(once: .syncManagerConfigurationSyncDidComplete).asVoid(),
NotificationCenter.default.observe(once: BlockingManager.blockedSyncDidComplete).asVoid(),
NotificationCenter.default.observe(once: .OWSSyncManagerKeysSyncDidComplete).asVoid()
NotificationCenter.default.observe(once: .syncManagerKeysSyncDidComplete).asVoid()
])
}.then(on: DependenciesBridge.shared.schedulers.sync) { $0 }
}
@ -131,7 +229,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
}
transaction.addAsyncCompletionOffMain {
NotificationCenter.default.postNotificationNameAsync(.OWSSyncManagerKeysSyncDidComplete, object: nil)
NotificationCenter.default.postNotificationNameAsync(.syncManagerKeysSyncDidComplete, object: nil)
}
}
@ -351,7 +449,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
// main app can send that request the next time in runs.
if mode == .allSignalAccounts {
databaseStorage.write { tx in
Self.keyValueStore().setString(UUID().uuidString, key: Constants.fullSyncRequestIdKey, transaction: tx)
Self.keyValueStore.setString(UUID().uuidString, key: Constants.fullSyncRequestIdKey, transaction: tx)
}
}
// If a full sync sync is requested in NSE, ignore it. Opportunistic syncs
@ -404,7 +502,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
message: result.message
)
await self.databaseStorage.awaitableWrite { tx in
Self.keyValueStore().setData(messageHash, key: Constants.lastContactSyncKey, transaction: tx)
Self.keyValueStore.setData(messageHash, key: Constants.lastContactSyncKey, transaction: tx)
self.clearFullSyncRequestId(ifMatches: result.fullSyncRequestId, tx: tx)
}
}
@ -425,7 +523,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
// Check if there's a pending request from the NSE. Any full sync in the
// main app can clear this flag, even if it's not started in response to
// calling syncAllContactsIfFullSyncRequested.
let fullSyncRequestId = Self.keyValueStore().getString(Constants.fullSyncRequestIdKey, transaction: tx)
let fullSyncRequestId = Self.keyValueStore.getString(Constants.fullSyncRequestIdKey, transaction: tx)
// However, only syncAllContactsIfFullSyncRequested-initiated requests
// should be skipped if there's no request.
@ -446,7 +544,7 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
message: message,
syncFileUrl: syncFileUrl,
fullSyncRequestId: fullSyncRequestId,
previousMessageHash: Self.keyValueStore().getData(Constants.lastContactSyncKey, transaction: tx)
previousMessageHash: Self.keyValueStore.getData(Constants.lastContactSyncKey, transaction: tx)
)
}
@ -454,13 +552,13 @@ extension OWSSyncManager: SyncManagerProtocol, SyncManagerProtocolSwift {
guard let requestId else {
return
}
let storedRequestId = Self.keyValueStore().getString(Constants.fullSyncRequestIdKey, transaction: tx)
let storedRequestId = Self.keyValueStore.getString(Constants.fullSyncRequestIdKey, transaction: tx)
// If the requestId we just finished matches the one in the database, we've
// fulfilled the contract with the NSE. If the NSE triggers *another* sync
// while this is outstanding, the match will fail, and we'll kick off
// another sync at the next opportunity.
if storedRequestId == requestId {
Self.keyValueStore().removeValue(forKey: Constants.fullSyncRequestIdKey, transaction: tx)
Self.keyValueStore.removeValue(forKey: Constants.fullSyncRequestIdKey, transaction: tx)
}
}
@ -513,7 +611,7 @@ public extension OWSSyncManager {
let notificationsPromise: Promise<([(threadUniqueId: String, sortOrder: UInt32)], Void, Void)> = Promise.when(fulfilled:
NotificationCenter.default.observe(once: .incomingContactSyncDidComplete).map { $0.insertedThreads }.timeout(seconds: timeoutSeconds, substituteValue: []),
NotificationCenter.default.observe(once: .OWSSyncManagerConfigurationSyncDidComplete).asVoid().timeout(seconds: timeoutSeconds),
NotificationCenter.default.observe(once: .syncManagerConfigurationSyncDidComplete).asVoid().timeout(seconds: timeoutSeconds),
NotificationCenter.default.observe(once: BlockingManager.blockedSyncDidComplete).asVoid().timeout(seconds: timeoutSeconds)
)