Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 1.11.9 #7772

Merged
merged 28 commits into from
Apr 2, 2024
Merged
Changes from 4 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
6301a1f
Merge branch 'master' into develop
pixlwave Mar 5, 2024
2ec3ae1
Prepare for new sprint
pixlwave Mar 5, 2024
a1d59b3
Increase decryption failure grace period
BillCarsonFr Mar 6, 2024
5a85651
Add .xcprivacy info files to the main app, the notification service e…
stefanceriu Mar 19, 2024
92be17d
Add privacy accessed API declaration for system boot time
stefanceriu Mar 19, 2024
4d3d82f
Switch the github actions to the macos-14 runner
stefanceriu Mar 19, 2024
c1036cb
Use the latest version of the sonarcloud github action
stefanceriu Mar 19, 2024
b1c6ac4
Remove inherently broken tests
stefanceriu Mar 19, 2024
608f760
Switch UI tests to iPhone 15, fix the broken ones
stefanceriu Mar 19, 2024
c89637d
Merge pull request #7766 from element-hq/stefan/privacyInfo
stefanceriu Mar 19, 2024
b6b7652
Bump analytics event to v0.15.0
BillCarsonFr Mar 27, 2024
6945e3f
Update changelog
BillCarsonFr Mar 27, 2024
31a2b12
code review
BillCarsonFr Mar 28, 2024
09af055
rename changelog
BillCarsonFr Mar 28, 2024
95fd61f
convert DecryptionFailureTracker to swift + tests
BillCarsonFr Mar 29, 2024
50310d6
Merge pull request #7768 from element-hq/valere/udate_analytics_event
BillCarsonFr Mar 29, 2024
0a65287
DecryptionTracker: Permanent vs Temporary UTD
BillCarsonFr Mar 29, 2024
1d633e8
Add more test for convertion to analytics error
BillCarsonFr Mar 29, 2024
0b8fb85
Merge pull request #7764 from element-hq/valere/increase_decryption_g…
Velin92 Apr 2, 2024
520d22a
Merge pull request #7770 from element-hq/valere/permanent_vs_temporar…
Velin92 Apr 2, 2024
f6a46d2
Merge branch 'develop' into valere/swiftify_decryption_tracker
BillCarsonFr Apr 2, 2024
56e6653
post merge fix
BillCarsonFr Apr 2, 2024
421e861
Merge pull request #7769 from element-hq/valere/swiftify_decryption_t…
Velin92 Apr 2, 2024
cc068ab
Translated using Weblate (Belarusian)
kapatych-be Mar 26, 2024
a92c842
Translated using Weblate (Estonian)
Apr 1, 2024
19cd5b1
Merge pull request #7771 from RiotTranslateBot/weblate-riot-ios-riot-ios
Velin92 Apr 2, 2024
487a4f7
version++
Velin92 Apr 2, 2024
c2b17a0
Update CHANGES.md
Velin92 Apr 2, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions Riot/Modules/Analytics/DecryptionFailureTracker.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*
Copyright 2018 New Vector Ltd

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 "DecryptionFailureTracker.h"
#import "GeneratedInterface-Swift.h"


// Call `checkFailures` every `CHECK_INTERVAL`
#define CHECK_INTERVAL 10

// Give events a chance to be decrypted by waiting `GRACE_PERIOD` before counting
// and reporting them as failures
#define GRACE_PERIOD 30

// E2E failures analytics category.
NSString *const kDecryptionFailureTrackerAnalyticsCategory = @"e2e.failure";

@interface DecryptionFailureTracker()
{
// Reported failures
// Every `CHECK_INTERVAL`, this list is checked for failures that happened
// more than`GRACE_PERIOD` ago. Those that did are reported to the delegate.
NSMutableDictionary<NSString* /* eventId */, DecryptionFailure*> *reportedFailures;

// Event ids of failures that were tracked previously
NSMutableSet<NSString*> *trackedEvents;

// Timer for periodic check
NSTimer *checkFailuresTimer;
}
@end

@implementation DecryptionFailureTracker

+ (instancetype)sharedInstance
{
static DecryptionFailureTracker *sharedInstance = nil;
static dispatch_once_t onceToken;

dispatch_once(&onceToken, ^{
sharedInstance = [[DecryptionFailureTracker alloc] init];
});

return sharedInstance;
}

- (instancetype)init
{
self = [super init];
if (self)
{
reportedFailures = [NSMutableDictionary dictionary];
trackedEvents = [NSMutableSet set];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidDecrypt:) name:kMXEventDidDecryptNotification object:nil];

checkFailuresTimer = [NSTimer scheduledTimerWithTimeInterval:CHECK_INTERVAL
target:self
selector:@selector(checkFailures)
userInfo:nil
repeats:YES];
}
return self;
}

- (void)reportUnableToDecryptErrorForEvent:(MXEvent *)event withRoomState:(MXRoomState *)roomState myUser:(NSString *)userId
{
if (reportedFailures[event.eventId] || [trackedEvents containsObject:event.eventId])
{
return;
}

// Filter out "expected" UTDs
// We cannot decrypt messages sent before the user joined the room
MXRoomMember *myUser = [roomState.members memberWithUserId:userId];
if (!myUser || myUser.membership != MXMembershipJoin)
{
return;
}

NSString *failedEventId = event.eventId;
DecryptionFailureReason reason;

// Categorise the error
switch (event.decryptionError.code)
{
case MXDecryptingErrorUnknownInboundSessionIdCode:
reason = DecryptionFailureReasonOlmKeysNotSent;
break;

case MXDecryptingErrorOlmCode:
reason = DecryptionFailureReasonOlmIndexError;
break;

default:
// All other error codes will be tracked as `OlmUnspecifiedError` and will include `context` containing
// the actual error code and localized description
reason = DecryptionFailureReasonUnspecified;
break;
}

NSString *context = [NSString stringWithFormat:@"code: %ld, description: %@", event.decryptionError.code, event.decryptionError.localizedDescription];
reportedFailures[event.eventId] = [[DecryptionFailure alloc] initWithFailedEventId:failedEventId
reason:reason
context:context];
}

- (void)dispatch
{
[self checkFailures];
}

#pragma mark - Private methods

/**
Mark reported failures that occured before tsNow - GRACE_PERIOD as failures that should be
tracked.
*/
- (void)checkFailures
{
if (!_delegate)
{
return;
}

NSTimeInterval tsNow = [NSDate date].timeIntervalSince1970;

NSMutableArray *failuresToTrack = [NSMutableArray array];

for (DecryptionFailure *reportedFailure in reportedFailures.allValues)
{
if (reportedFailure.ts < tsNow - GRACE_PERIOD)
{
[failuresToTrack addObject:reportedFailure];
[reportedFailures removeObjectForKey:reportedFailure.failedEventId];
[trackedEvents addObject:reportedFailure.failedEventId];
}
}

if (failuresToTrack.count)
{
// Sort failures by error reason
NSMutableDictionary<NSNumber*, NSNumber*> *failuresCounts = [NSMutableDictionary dictionary];
for (DecryptionFailure *failure in failuresToTrack)
{
failuresCounts[@(failure.reason)] = @(failuresCounts[@(failure.reason)].unsignedIntegerValue + 1);
[self.delegate trackE2EEError:failure.reason context:failure.context];
}

MXLogDebug(@"[DecryptionFailureTracker] trackFailures: %@", failuresCounts);
}
}

- (void)eventDidDecrypt:(NSNotification *)notif
{
// Could be an event in the reportedFailures, remove it
MXEvent *event = notif.object;
[reportedFailures removeObjectForKey:event.eventId];
}

@end