Fetch safety number upon entering thread

* uniform method to get recipients in group/contact thread
  * use it to clean up markAsSeenJob

// FREEBIE
This commit is contained in:
Michael Kirk 2017-05-24 13:42:29 -07:00
parent 22b608c8e8
commit 1a03be8ae7
6 changed files with 123 additions and 16 deletions

View File

@ -136,7 +136,7 @@ CHECKOUT OPTIONS:
:commit: 7054e4b13ee5bcd6d524adb6dc9a726e8c466308
:git: https://github.com/WhisperSystems/JSQMessagesViewController.git
SignalServiceKit:
:commit: b89d16ea905c08f368c7320fb32bbd31e127ecca
:commit: 0201fa34ce760351149dd33674353d9e7edea32f
:git: https://github.com/WhisperSystems/SignalServiceKit.git
SocketRocket:
:commit: 877ac7438be3ad0b45ef5ca3969574e4b97112bf

View File

@ -142,6 +142,7 @@
45855F371D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45855F361D9498A40084F340 /* OWSContactAvatarBuilder.m */; };
45855F381D9498A40084F340 /* OWSContactAvatarBuilder.m in Sources */ = {isa = PBXBuildFile; fileRef = 45855F361D9498A40084F340 /* OWSContactAvatarBuilder.m */; };
4585C4601ED4FD0400896AEA /* OWS104CreateRecipientIdentities.m in Sources */ = {isa = PBXBuildFile; fileRef = 4585C45F1ED4FD0400896AEA /* OWS104CreateRecipientIdentities.m */; };
4585C4661ED5DF7A00896AEA /* ProfileFetcherJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4585C4651ED5DF7A00896AEA /* ProfileFetcherJob.swift */; };
458967111DC117CC00E9DD21 /* AccountManagerTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458967101DC117CC00E9DD21 /* AccountManagerTest.swift */; };
458DE9D61DEE3FD00071BB03 /* PeerConnectionClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = 458DE9D51DEE3FD00071BB03 /* PeerConnectionClient.swift */; };
458DE9D91DEE7B360071BB03 /* OWSWebRTCDataProtos.pb.m in Sources */ = {isa = PBXBuildFile; fileRef = 458DE9D81DEE7B360071BB03 /* OWSWebRTCDataProtos.pb.m */; };
@ -557,6 +558,7 @@
45855F361D9498A40084F340 /* OWSContactAvatarBuilder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactAvatarBuilder.m; sourceTree = "<group>"; };
4585C45E1ED4FD0400896AEA /* OWS104CreateRecipientIdentities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OWS104CreateRecipientIdentities.h; path = Migrations/OWS104CreateRecipientIdentities.h; sourceTree = "<group>"; };
4585C45F1ED4FD0400896AEA /* OWS104CreateRecipientIdentities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWS104CreateRecipientIdentities.m; path = Migrations/OWS104CreateRecipientIdentities.m; sourceTree = "<group>"; };
4585C4651ED5DF7A00896AEA /* ProfileFetcherJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileFetcherJob.swift; sourceTree = "<group>"; };
4589670F1DC117CC00E9DD21 /* SignalTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SignalTests-Bridging-Header.h"; sourceTree = "<group>"; };
458967101DC117CC00E9DD21 /* AccountManagerTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AccountManagerTest.swift; path = Models/AccountManagerTest.swift; sourceTree = "<group>"; };
458DE9D51DEE3FD00071BB03 /* PeerConnectionClient.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PeerConnectionClient.swift; sourceTree = "<group>"; };
@ -1147,6 +1149,7 @@
45D231761DC7E8F10034FA89 /* SessionResetJob.swift */,
452ECA4C1E087E7200E2F016 /* MessageFetcherJob.swift */,
459B1C661ED480BB00506A04 /* MarkIdentityAsSeenJob.swift */,
4585C4651ED5DF7A00896AEA /* ProfileFetcherJob.swift */,
);
name = Jobs;
sourceTree = "<group>";
@ -2040,6 +2043,7 @@
buildActionMask = 2147483647;
files = (
34B3F8761E8DF1700035BE1A /* CodeVerificationViewController.m in Sources */,
4585C4661ED5DF7A00896AEA /* ProfileFetcherJob.swift in Sources */,
76EB063E18170B33006006FC /* Operation.m in Sources */,
34B3F8741E8DF1700035BE1A /* AttachmentSharing.m in Sources */,
34D8C02B1ED3685800188D7C /* DebugUIContacts.m in Sources */,

View File

@ -19,21 +19,8 @@ class MarkIdentityAsSeenJob: NSObject {
}
public func run() {
switch self.thread {
case let contactThread as TSContactThread:
markAsSeenIfNecessary(recipientId: contactThread.contactIdentifier())
case let groupThread as TSGroupThread:
groupThread.groupModel.groupMemberIds?.forEach { memberId in
guard let recipientId = memberId as? String else {
Logger.error("\(TAG) unexecpted type in group members.")
assertionFailure("\(TAG) unexecpted type in group members.")
return
}
markAsSeenIfNecessary(recipientId: recipientId)
}
default:
assertionFailure("Unexpected thread type: \(self.thread)")
for recipientId in self.thread.recipientIdentifiers {
markAsSeenIfNecessary(recipientId: recipientId)
}
}

View File

@ -0,0 +1,113 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
import Foundation
@objc
class ProfileFetcherJob: NSObject {
let TAG = "[ProfileFetcherJob]"
let networkManager: TSNetworkManager
let storageManager: TSStorageManager
let thread: TSThread
public class func run(thread: TSThread, networkManager: TSNetworkManager) {
ProfileFetcherJob(thread: thread, networkManager: networkManager).run()
}
init(thread: TSThread, networkManager: TSNetworkManager) {
self.networkManager = networkManager
self.storageManager = TSStorageManager.shared()
self.thread = thread
}
public func run() {
for recipientId in self.thread.recipientIdentifiers {
let request = OWSGetProfileRequest(recipientId: recipientId)
self.networkManager.makeRequest(
request,
success: { (_: URLSessionDataTask?, responseObject: Any?) -> Void in
guard let profileResponse = SignalServiceProfile(recipientId: recipientId, rawResponse: responseObject) else {
Logger.error("\(self.TAG) response object had unexpected content")
assertionFailure("\(self.TAG) response object had unexpected content")
return
}
self.processResponse(signalServiceProfile: profileResponse)
},
failure: { (_: URLSessionDataTask?, error: Error?) in
guard let error = error else {
Logger.error("\(self.TAG) error in \(#function) was surpringly nil. sheesh rough day.")
assertionFailure("\(self.TAG) error in \(#function) was surpringly nil. sheesh rough day.")
return
}
Logger.error("\(self.TAG) failed to fetch profile for recipient: \(recipientId) with error: \(error)")
})
}
}
private func processResponse(signalServiceProfile: SignalServiceProfile) {
Logger.debug("\(TAG) in \(#function) for \(signalServiceProfile)")
verifyIdentityUpToDateAsync(recipientId: signalServiceProfile.recipientId, latestIdentityKey: signalServiceProfile.identityKey)
// Eventually we'll want to do more things with new SignalServiceProfile fields here.
}
private func verifyIdentityUpToDateAsync(recipientId: String, latestIdentityKey: Data) {
OWSDispatch.sessionStoreQueue().async {
if self.storageManager.identityKey(forRecipientId: recipientId) == nil {
// first time use, do nothing, since there's no change.
return
}
if self.storageManager.saveRemoteIdentity(latestIdentityKey, recipientId: recipientId) {
Logger.info("\(self.TAG) updated identity key in fetched profile for recipient: \(recipientId)")
self.storageManager.deleteAllSessions(forContact: recipientId)
} else {
// no change in identity.
}
}
}
}
struct SignalServiceProfile {
let TAG = "[ProfileResponse]"
public let recipientId: String
public let identityKey: Data
init?(recipientId: String, rawResponse: Any?) {
self.recipientId = recipientId
guard let responseDict = rawResponse as? [String: Any?] else {
Logger.error("\(TAG) unexpected type: \(String(describing: rawResponse))")
return nil
}
guard let identityKeyString = responseDict["identityKey"] as? String else {
Logger.error("\(TAG) missing identity key: \(String(describing: rawResponse))")
return nil
}
guard let identityKeyWithType = Data(base64Encoded: identityKeyString) else {
Logger.error("\(TAG) unable to parse identity key: \(identityKeyString)")
return nil
}
let kIdentityKeyLength = 33
guard identityKeyWithType.count == kIdentityKeyLength else {
Logger.error("\(TAG) malformed key \(identityKeyString) with decoded length: \(identityKeyWithType.count)")
return nil
}
// `removeKeyType` is an objc category method only on NSData, so temporarily cast.
self.identityKey = (identityKeyWithType as NSData).removeKeyType() as Data
}
}

View File

@ -31,6 +31,7 @@
#import "UIUtil.h"
#import "UIView+OWS.h"
#import "ViewControllerUtils.h"
#import <AxolotlKit/NSData+keyVersionByte.h>
#import <JSQMessagesViewController/JSQMediaItem.h>
#import <JSQMessagesViewController/JSQMessagesMediaViewBubbleImageMasker.h>
#import <JSQMessagesViewController/UIColor+JSQMessages.h>
@ -54,6 +55,7 @@
#import <SignalServiceKit/OWSEndSessionMessage.h>
#import <SignalServiceKit/OWSError.h>
#import <SignalServiceKit/OWSGetMessagesRequest.h>
#import <SignalServiceKit/OWSGetProfileRequest.h>
#import <SignalServiceKit/OWSMessageSender.h>
#import <SignalServiceKit/OWSOutgoingCallMessage.h>
#import <SignalServiceKit/OWSRecipientIdentity.h>

View File

@ -1212,6 +1212,7 @@ typedef enum : NSUInteger {
}
[self updateNavigationBarSubtitleLabel];
[MarkIdentityAsSeenJob runWithThread:self.thread];
[ProfileFetcherJob runWithThread:self.thread networkManager:self.networkManager];
}
- (void)viewWillDisappear:(BOOL)animated {