diff --git a/MatrixSDK.xcodeproj/project.pbxproj b/MatrixSDK.xcodeproj/project.pbxproj index 8202d3ae66..a3cd1a5950 100644 --- a/MatrixSDK.xcodeproj/project.pbxproj +++ b/MatrixSDK.xcodeproj/project.pbxproj @@ -713,6 +713,10 @@ 3B60DCAB92D470B91262BF0C /* libPods-MatrixSDKTests-macOS.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 15D7F292D95EB58AEE801C4E /* libPods-MatrixSDKTests-macOS.a */; }; 66398BA527A4085B00466E89 /* MXRefreshResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 66398BA427A4085B00466E89 /* MXRefreshResponse.m */; }; 66398BA627A4085B00466E89 /* MXRefreshResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 66398BA427A4085B00466E89 /* MXRefreshResponse.m */; }; + 66836AB727CFA17200515780 /* MXEventStreamService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66836AB527CFA17200515780 /* MXEventStreamService.swift */; }; + 66836AB827CFA17200515780 /* MXEventStreamService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66836AB527CFA17200515780 /* MXEventStreamService.swift */; }; + 66836AB927CFA17200515780 /* MXLiveEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66836AB627CFA17200515780 /* MXLiveEventListener.swift */; }; + 66836ABA27CFA17200515780 /* MXLiveEventListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 66836AB627CFA17200515780 /* MXLiveEventListener.swift */; }; 66AC9D23278CE627002E9B8F /* MXRefreshTokenData.h in Headers */ = {isa = PBXBuildFile; fileRef = 66AC9D21278CE626002E9B8F /* MXRefreshTokenData.h */; }; 66AC9D24278CE627002E9B8F /* MXRefreshTokenData.h in Headers */ = {isa = PBXBuildFile; fileRef = 66AC9D21278CE626002E9B8F /* MXRefreshTokenData.h */; }; 66AC9D25278CE627002E9B8F /* MXRefreshTokenData.m in Sources */ = {isa = PBXBuildFile; fileRef = 66AC9D22278CE626002E9B8F /* MXRefreshTokenData.m */; }; @@ -2328,6 +2332,8 @@ 6257D945D115DA658F44E8D4 /* Pods-SDK-MatrixSDK-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDK-MatrixSDK-macOS.release.xcconfig"; path = "Target Support Files/Pods-SDK-MatrixSDK-macOS/Pods-SDK-MatrixSDK-macOS.release.xcconfig"; sourceTree = ""; }; 66398BA427A4085B00466E89 /* MXRefreshResponse.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXRefreshResponse.m; sourceTree = ""; }; 66398BA727A408C000466E89 /* MXRefreshResponse.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXRefreshResponse.h; sourceTree = ""; }; + 66836AB527CFA17200515780 /* MXEventStreamService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXEventStreamService.swift; sourceTree = ""; }; + 66836AB627CFA17200515780 /* MXLiveEventListener.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MXLiveEventListener.swift; sourceTree = ""; }; 66AC9D21278CE626002E9B8F /* MXRefreshTokenData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXRefreshTokenData.h; sourceTree = ""; }; 66AC9D22278CE626002E9B8F /* MXRefreshTokenData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXRefreshTokenData.m; sourceTree = ""; }; 6869D206EA7C7FB05EAB75B0 /* Pods-MatrixSDKTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MatrixSDKTests-iOS.release.xcconfig"; path = "Target Support Files/Pods-MatrixSDKTests-iOS/Pods-MatrixSDKTests-iOS.release.xcconfig"; sourceTree = ""; }; @@ -3747,6 +3753,7 @@ 32C6F92F19DD814400EA4E9C /* MatrixSDK */ = { isa = PBXGroup; children = ( + 66836AB427CFA17200515780 /* EventStream */, 3A858DD82750EE0A006322C1 /* HomeServer */, ECCA02B9273485A100B6F34F /* Threads */, 3259CFD9260266F700C365DB /* Categories */, @@ -4065,6 +4072,16 @@ path = Dehydration; sourceTree = ""; }; + 66836AB427CFA17200515780 /* EventStream */ = { + isa = PBXGroup; + children = ( + 66836AB527CFA17200515780 /* MXEventStreamService.swift */, + 66836AB627CFA17200515780 /* MXLiveEventListener.swift */, + ); + name = EventStream; + path = MatrixSDK/EventStream; + sourceTree = SOURCE_ROOT; + }; 916911E77039455CC9D0900C /* Pods */ = { isa = PBXGroup; children = ( @@ -5832,6 +5849,7 @@ 32DC15D51A8CF874006F9AD3 /* MXPushRuleEventMatchConditionChecker.m in Sources */, EC1165B427107E330089FA56 /* MXStoreRoomListDataManager.swift in Sources */, 32B94E06228EE90300716A26 /* MXRealmReactionRelation.m in Sources */, + 66836AB927CFA17200515780 /* MXLiveEventListener.swift in Sources */, 320BBF411D6C81550079890E /* MXEventsByTypesEnumeratorOnArray.m in Sources */, 181FD5D62660C791008EC084 /* MXLogObjcWrapper.m in Sources */, EC60ED87265CFD0700B39A4E /* MXRoomsSyncResponse.m in Sources */, @@ -5866,6 +5884,7 @@ 329FB1761A0A3A1600A5E88E /* MXRoomMember.m in Sources */, 3251D41F25AF01D7001E6E77 /* MXUIKitApplicationStateService.swift in Sources */, B1136965230AC9D900E2B2FA /* MXIdentityService.m in Sources */, + 66836AB727CFA17200515780 /* MXEventStreamService.swift in Sources */, B11BD44922CB56790064D8B0 /* MXReplyEventParser.m in Sources */, EC0B941127184E8A00B4D440 /* MXRoomSummaryMO.swift in Sources */, EC0B941327184E8A00B4D440 /* MXRoomMembersCountMO.swift in Sources */, @@ -6352,6 +6371,7 @@ B14EF1E42397E90400758AF0 /* MXWellknownIntegrations.m in Sources */, EC60EDF5265CFFAC00B39A4E /* MXGroupsSyncResponse.m in Sources */, EC1165B527107E330089FA56 /* MXStoreRoomListDataManager.swift in Sources */, + 66836ABA27CFA17200515780 /* MXLiveEventListener.swift in Sources */, B14EF1E52397E90400758AF0 /* MXLoginPolicy.m in Sources */, B14EF1E62397E90400758AF0 /* (null) in Sources */, EC60EDB5265CFE6200B39A4E /* MXRoomSyncEphemeral.m in Sources */, @@ -6386,6 +6406,7 @@ B14EF1F82397E90400758AF0 /* MXReplyEventParts.m in Sources */, 3259D02426037A7200C365DB /* NSArray.swift in Sources */, 3A108A8125810C96005EEBE9 /* MXKeyData.m in Sources */, + 66836AB827CFA17200515780 /* MXEventStreamService.swift in Sources */, 3A59A4A025A7A16F00DDA1FC /* MXOlmOutboundGroupSession.m in Sources */, EC0B941227184E8A00B4D440 /* MXRoomSummaryMO.swift in Sources */, EC0B941427184E8A00B4D440 /* MXRoomMembersCountMO.swift in Sources */, diff --git a/MatrixSDK/Contrib/Swift/MXRestClient.swift b/MatrixSDK/Contrib/Swift/MXRestClient.swift index 4bc4d12c8b..462703570e 100644 --- a/MatrixSDK/Contrib/Swift/MXRestClient.swift +++ b/MatrixSDK/Contrib/Swift/MXRestClient.swift @@ -1842,7 +1842,7 @@ public extension MXRestClient { - returns: a `MXHTTPOperation` instance. */ - @nonobjc @discardableResult func sendDirectToDevice(eventType: String, contentMap: MXUsersDevicesMap, txnId: String, completion: @escaping (_ response: MXResponse) -> Void) -> MXHTTPOperation { + @nonobjc @discardableResult func sendDirectToDevice(eventType: String, contentMap: MXUsersDevicesMap, txnId: String?, completion: @escaping (_ response: MXResponse) -> Void) -> MXHTTPOperation { return __send(toDevice: eventType, contentMap: contentMap, txnId: txnId, success: currySuccess(completion), failure: curryFailure(completion)) } diff --git a/MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m b/MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m index 7128466679..3435d43d67 100644 --- a/MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m +++ b/MatrixSDK/Crypto/Algorithms/Megolm/MXMegolmDecryption.m @@ -24,6 +24,7 @@ #import "MXCryptoAlgorithms.h" #import "MXCrypto_Private.h" #import "MXTools.h" +#import "MatrixSDKSwiftHeader.h" @interface MXMegolmDecryption () { @@ -146,7 +147,8 @@ - (MXEventDecryptionResult *)decryptEvent:(MXEvent*)event inTimeline:(NSString*) result.error = olmError; } - + + [crypto.mxSession.eventStreamService dispatchLiveEventDecryptionAttemptedWithEvent:event result:result]; return result; } diff --git a/MatrixSDK/Crypto/MXCrypto.h b/MatrixSDK/Crypto/MXCrypto.h index 01f980236e..6fe541811b 100644 --- a/MatrixSDK/Crypto/MXCrypto.h +++ b/MatrixSDK/Crypto/MXCrypto.h @@ -264,12 +264,12 @@ extern NSString *const MXDeviceListDidUpdateUsersDevicesNotification; - (void)handleDeviceUnusedFallbackKeys:(NSArray *)deviceUnusedFallbackKeys; /** - Handle a room key event. + Handle toDevice event - @param event the room key event. + @param event the `toDevice` event. @param onComplete the block called when the operation completes. */ -- (void)handleRoomKeyEvent:(MXEvent*)event onComplete:(void (^)(void))onComplete; +- (void)handleToDeviceEvent:(MXEvent*)event onComplete:(void (^)(void))onComplete; /** Handle the completion of a /sync. diff --git a/MatrixSDK/Crypto/MXCrypto.m b/MatrixSDK/Crypto/MXCrypto.m index 3a85751db2..3966f92b2c 100644 --- a/MatrixSDK/Crypto/MXCrypto.m +++ b/MatrixSDK/Crypto/MXCrypto.m @@ -51,6 +51,7 @@ #import "MXDeviceListResponse.h" +#import "MatrixSDKSwiftHeader.h" /** The store to use for crypto. */ @@ -817,6 +818,24 @@ - (void)handleDeviceListsChanges:(MXDeviceListResponse*)deviceLists #endif } +- (void)handleToDeviceEvent:(MXEvent *)event onComplete:(void (^)(void))onComplete +{ + switch (event.eventType) + { + case MXEventTypeRoomKey: + { + [self handleRoomKeyEvent:event onComplete:onComplete]; + break; + } + + default: + onComplete(); + break; + } + [self.mxSession.eventStreamService dispatchOnLiveToDeviceWithEvent:event]; +} + + - (void)handleRoomKeyEvent:(MXEvent*)event onComplete:(void (^)(void))onComplete { // Use decryptionQueue as synchronisation because decryptions require room keys diff --git a/MatrixSDK/EventStream/MXEventStreamService.swift b/MatrixSDK/EventStream/MXEventStreamService.swift new file mode 100644 index 0000000000..d01c2cdede --- /dev/null +++ b/MatrixSDK/EventStream/MXEventStreamService.swift @@ -0,0 +1,44 @@ +// +// Copyright 2022 The Matrix.org Foundation C.I.C +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +/// Manages the adding, removing MXLiveEventListeners and dispatching of events to those listeners. +@objcMembers public class MXEventStreamService: NSObject { + + private let multicastDelegate: MXMulticastDelegate = MXMulticastDelegate() + + public func add(eventStreamListener: MXLiveEventListener) { + multicastDelegate.addDelegate(eventStreamListener) + } + + public func remove(eventStreamListener: MXLiveEventListener) { + multicastDelegate.removeDelegate(eventStreamListener) + } + + public func dispatchSessionStateChanged(state: MXSessionState) { + multicastDelegate.invoke({ listener in listener.onSessionStateChanged(state: state) }) + } + + public func dispatchLiveEventDecryptionAttempted(event: MXEvent, result: MXEventDecryptionResult) { + multicastDelegate.invoke({ listener in listener.onLiveEventDecryptionAttempted(event: event, result: result) }) + } + + public func dispatchOnLiveToDevice(event: MXEvent) { + multicastDelegate.invoke({ listener in listener.onLiveToDeviceEvent(event: event)}) + } +} + diff --git a/MatrixSDK/EventStream/MXLiveEventListener.swift b/MatrixSDK/EventStream/MXLiveEventListener.swift new file mode 100644 index 0000000000..9d790ddb5e --- /dev/null +++ b/MatrixSDK/EventStream/MXLiveEventListener.swift @@ -0,0 +1,30 @@ +// +// Copyright 2022 The Matrix.org Foundation C.I.C +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +/// Protocol used to monitor events of a specific session +@objc +public protocol MXLiveEventListener: AnyObject { + + /// Monitor changes to session state + func onSessionStateChanged(state: MXSessionState) + + /// Monitor decryption attempts + func onLiveEventDecryptionAttempted(event: MXEvent, result:MXEventDecryptionResult) + + /// Monitor to device events + func onLiveToDeviceEvent(event: MXEvent) + +} diff --git a/MatrixSDK/MXSession.h b/MatrixSDK/MXSession.h index d190cbaded..06535548c1 100644 --- a/MatrixSDK/MXSession.h +++ b/MatrixSDK/MXSession.h @@ -348,6 +348,7 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; @class MXHomeserverCapabilitiesService; @class MXThreadingService; @class MXCapabilities; +@class MXEventStreamService; #pragma mark - MXSession /** @@ -493,6 +494,11 @@ FOUNDATION_EXPORT NSString *const kMXSessionNoRoomTag; */ @property (nonatomic, readonly) MXThreadingService *threadingService NS_REFINED_FOR_SWIFT; +/** + Service used to monitor live events of the session. + */ +@property (nonatomic, readonly) MXEventStreamService *eventStreamService; + /** Flag indicating the session can be paused. */ diff --git a/MatrixSDK/MXSession.m b/MatrixSDK/MXSession.m index 9f9dd4f260..1e4fc46db6 100644 --- a/MatrixSDK/MXSession.m +++ b/MatrixSDK/MXSession.m @@ -243,6 +243,7 @@ - (id)initWithMatrixRestClient:(MXRestClient*)mxRestClient name:MXSpaceService.didBuildSpaceGraph object:_spaceService]; _threadingService = [[MXThreadingService alloc] initWithSession:self]; + _eventStreamService = [[MXEventStreamService alloc] init]; [self setIdentityServer:mxRestClient.identityServer andAccessToken:mxRestClient.credentials.identityServerAccessToken]; @@ -329,6 +330,7 @@ - (void)setState:(MXSessionState)state NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter]; [notificationCenter postNotificationName:kMXSessionStateDidChangeNotification object:self userInfo:nil]; + [_eventStreamService dispatchSessionStateChangedWithState:state]; } } @@ -1883,18 +1885,8 @@ - (void)handleToDeviceEvent:(MXEvent *)event onComplete:(void (^)(void))onComple onComplete(); }; - switch (event.eventType) - { - case MXEventTypeRoomKey: - { - [_crypto handleRoomKeyEvent:event onComplete:onHandleToDeviceEventDone]; - break; - } - - default: - onHandleToDeviceEventDone(); - break; - } + + [_crypto handleToDeviceEvent:event onComplete:onHandleToDeviceEventDone]; } /** diff --git a/MatrixSDK/Utils/MXBugReportRestClient.h b/MatrixSDK/Utils/MXBugReportRestClient.h index e8cf5647d7..0e0e294baf 100644 --- a/MatrixSDK/Utils/MXBugReportRestClient.h +++ b/MatrixSDK/Utils/MXBugReportRestClient.h @@ -51,7 +51,7 @@ typedef enum : NSUInteger @param bugReportEndpoint the endpoint URL. @return a MXBugReportRestClient instance. */ -- (instancetype)initWithBugReportEndpoint:(NSString *)bugReportEndpoint; +- (nonnull instancetype)initWithBugReportEndpoint:(NSString *)bugReportEndpoint; /** Send a bug report. @@ -74,7 +74,7 @@ typedef enum : NSUInteger sendFiles:(NSArray*)files attachGitHubLabels:(NSArray*)gitHubLabels progress:(void (^)(MXBugReportState state, NSProgress *progress))progress - success:(void (^)(void))success + success:(void (^)(NSString *reportUrl))success failure:(void (^)(NSError *error))failure; /** diff --git a/MatrixSDK/Utils/MXBugReportRestClient.m b/MatrixSDK/Utils/MXBugReportRestClient.m index 4b52834534..51c6e4c5b3 100644 --- a/MatrixSDK/Utils/MXBugReportRestClient.m +++ b/MatrixSDK/Utils/MXBugReportRestClient.m @@ -59,7 +59,7 @@ @interface MXBugReportRestClient () @implementation MXBugReportRestClient -- (instancetype)initWithBugReportEndpoint:(NSString *)theBugReportEndpoint +- (nonnull instancetype)initWithBugReportEndpoint:(NSString *)theBugReportEndpoint { self = [super init]; if (self) @@ -98,7 +98,7 @@ - (instancetype)initWithBugReportEndpoint:(NSString *)theBugReportEndpoint return self; } -- (void)sendBugReport:(NSString *)text sendLogs:(BOOL)sendLogs sendCrashLog:(BOOL)sendCrashLog sendFiles:(NSArray*)files attachGitHubLabels:(NSArray*)gitHubLabels progress:(void (^)(MXBugReportState, NSProgress *))progress success:(void (^)(void))success failure:(void (^)(NSError *))failure +- (void)sendBugReport:(NSString *)text sendLogs:(BOOL)sendLogs sendCrashLog:(BOOL)sendCrashLog sendFiles:(NSArray*)files attachGitHubLabels:(NSArray*)gitHubLabels progress:(void (^)(MXBugReportState, NSProgress *))progress success:(void (^)(NSString*))success failure:(void (^)(NSError *))failure { if (_state != MXBugReportStateReady) { @@ -124,7 +124,7 @@ - (void)sendBugReport:(NSString *)text sendLogs:(BOOL)sendLogs sendCrashLog:(BOO } } --(void)sendBugReport:(NSString *)text sendFiles:(NSArray*)files attachGitHubLabels:(NSArray*)gitHubLabels progress:(void (^)(MXBugReportState, NSProgress *))progress success:(void (^)(void))success failure:(void (^)(NSError *))failure +-(void)sendBugReport:(NSString *)text sendFiles:(NSArray*)files attachGitHubLabels:(NSArray*)gitHubLabels progress:(void (^)(MXBugReportState, NSProgress *))progress success:(void (^)(NSString*))success failure:(void (^)(NSError *))failure { // The bugreport api needs at least app and version to render well NSParameterAssert(_appName && _version); @@ -276,10 +276,15 @@ -(void)sendBugReport:(NSString *)text sendFiles:(NSArray*)files attachGi else { MXLogDebug(@"[MXBugReport] sendBugReport: report done in %.3fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000); - + + NSString *reportUrl = nil; + if ([response isKindOfClass:[NSDictionary class]]) { + NSDictionary *responseDictionary = (NSDictionary*)responseObject; + reportUrl = responseDictionary[@"report_url"]; + } if (success) { - success(); + success(reportUrl); } } }]; @@ -316,9 +321,12 @@ - (void)zipFiles:(BOOL)logs crashLog:(BOOL)crashLog progress:(void (^)(MXBugRepo if (logFiles.count) { _state = MXBugReportStateProgressZipping; - + NSProgress *zipProgress = [NSProgress progressWithTotalUnitCount:logFiles.count]; - progress(_state, zipProgress); + if (progress) + { + progress(_state, zipProgress); + } MXWeakify(self); dispatch_async(dispatchQueue, ^{ diff --git a/MatrixSDKTests/MXCryptoTests.m b/MatrixSDKTests/MXCryptoTests.m index 2fa3049d1b..41ed873b4d 100644 --- a/MatrixSDKTests/MXCryptoTests.m +++ b/MatrixSDKTests/MXCryptoTests.m @@ -1893,7 +1893,7 @@ - (void)testRoomKeyReshare newContent[@"session_key"] = sessionInfo.session.sessionKey; toDeviceEvent.clearEvent.wireContent = newContent; - [bobSession.crypto handleRoomKeyEvent:toDeviceEvent onComplete:^{}]; + [bobSession.crypto handleToDeviceEvent:toDeviceEvent onComplete:^{}]; // We still must be able to decrypt the event // ie, the implementation must have ignored the new room key with the advanced outbound group @@ -1963,7 +1963,7 @@ - (void)testLateRoomKey }]; // Reinject the m.room_key event. This mimics a room_key event that arrives after message events. - [bobSession.crypto handleRoomKeyEvent:toDeviceEvent onComplete:^{}]; + [bobSession.crypto handleToDeviceEvent:toDeviceEvent onComplete:^{}]; }]; }]; }]; diff --git a/MatrixSDKTests/MXRoomSummaryTests.m b/MatrixSDKTests/MXRoomSummaryTests.m index 395ed09a9b..363269249b 100644 --- a/MatrixSDKTests/MXRoomSummaryTests.m +++ b/MatrixSDKTests/MXRoomSummaryTests.m @@ -1398,7 +1398,7 @@ - (void)testLateRoomKey // Attempt a new decryption [bobSession decryptEvents:@[event] inTimeline:nil onComplete:^(NSArray *failedEvents) { // Reinject the m.room_key event. This mimics a room_key event that arrives after message events. - [bobSession.crypto handleRoomKeyEvent:toDeviceEvent onComplete:^{}]; + [bobSession.crypto handleToDeviceEvent:toDeviceEvent onComplete:^{}]; }]; break;