Skip to content

Commit

Permalink
Show HUD while loading omemo keys the first time
Browse files Browse the repository at this point in the history
When opening a new chat and not having any omemo keys/devices for this
contact, we try to fetch the omemo devicelist+bundles while showing a
progress HUD.
If we do not succeed fetching those, we display a warning to the user
and disable encryption.
  • Loading branch information
tmolitor-stud-tu committed Aug 12, 2024
1 parent f65c577 commit 29c8039
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 60 deletions.
2 changes: 1 addition & 1 deletion Monal/Classes/MLChatViewHelper.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ +(void) toggleEncryptionForContact:(MLContact*) contact withSelf:(id) andSelf af
if(![contact toggleEncryption:!contact.isEncrypted])
{
// Show a warning when no device keys could be found and the user tries to enable encryption -> encryption is not possible
UIAlertController* alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Encryption Not Supported", @"") message:NSLocalizedString(@"This contact does not appear to have any devices that support encryption.", @"") preferredStyle:UIAlertControllerStyleAlert];
UIAlertController* alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Encryption Not Supported", @"") message:NSLocalizedString(@"This contact does not appear to have any devices that support encryption, please try again later if you think this is wrong.", @"") preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Close", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction* action __unused) {
[alert dismissViewControllerAnimated:YES completion:nil];
}]];
Expand Down
1 change: 1 addition & 0 deletions Monal/Classes/MLContact.m
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,7 @@ -(BOOL) toggleEncryption:(BOOL) encrypt
if(self.isGroup == NO)
{
NSSet* knownDevices = [account.omemo knownDevicesForAddressName:self.contactJid];
DDLogVerbose(@"Current isEncrypted=%@, encrypt=%@, knownDevices=%@", bool2str(self.isEncrypted), bool2str(encrypt), knownDevices);
if(!self.isEncrypted && encrypt && knownDevices.count == 0)
{
// request devicelist again
Expand Down
14 changes: 8 additions & 6 deletions Monal/Classes/MLOMEMO.m
Original file line number Diff line number Diff line change
Expand Up @@ -1323,12 +1323,14 @@ -(void) subscribeAndFetchDevicelistIfNoSessionExistsForJid:(NSString*) buddyJid
{
DDLogVerbose(@"No omemo session for %@", buddyJid);
MLContact* contact = [MLContact createContactFromJid:buddyJid andAccountNo:self.account.accountNo];
//only do so if we don't receive automatic headline pushes of the devicelist
if(!contact.isSubscribedTo)
{
DDLogVerbose(@"Fetching devicelist with subscribe from contact: %@", contact);
[self queryOMEMODevices:buddyJid withSubscribe:YES];
}
//only subscribe if we don't receive automatic headline pushes of the devicelist
DDLogVerbose(@"Fetching devicelist %@ from contact: %@", !contact.isSubscribedTo ? @"with subscribe" : @"without subscribe", contact);
[self queryOMEMODevices:buddyJid withSubscribe:!contact.isSubscribedTo];
}
else
{
//make sure we don't show the omemo key fetching hud forever
[self sendFetchUpdateNotificationForJid:buddyJid];
}
}

Expand Down
164 changes: 111 additions & 53 deletions Monal/Classes/chatViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ @interface chatViewController()<ChatInputActionDelegage, UISearchControllerDeleg
@property (nonatomic, assign) NSInteger thisday;
@property (nonatomic, strong) MBProgressHUD* uploadHUD;
@property (nonatomic, strong) MBProgressHUD* gpsHUD;
@property (nonatomic, strong) MBProgressHUD* omemoHUD;
@property (nonatomic, strong) UIBarButtonItem* callButton;

@property (nonatomic, strong) NSMutableArray<MLMessage*>* messageList;
Expand Down Expand Up @@ -775,7 +776,7 @@ -(void) viewWillAppear:(BOOL)animated
[nc addObserver:self selector:@selector(handleDeletedMessage:) name:kMonalDeletedMessageNotice object:nil];
[nc addObserver:self selector:@selector(handleSentMessage:) name:kMonalSentMessageNotice object:nil];
[nc addObserver:self selector:@selector(handleMessageError:) name:kMonalMessageErrorNotice object:nil];

[nc addObserver:self selector:@selector(handleOmemoFetchStateUpdate:) name:kMonalOmemoFetchingStateUpdate object:nil];

[nc addObserver:self selector:@selector(dismissKeyboard:) name:UIApplicationDidEnterBackgroundNotification object:nil];
[nc addObserver:self selector:@selector(handleForeGround) name:kMonalRefresh object:nil];
Expand Down Expand Up @@ -841,58 +842,8 @@ -(void) viewWillAppear:(BOOL)animated
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
#ifndef DISABLE_OMEMO
if(self.xmppAccount && [[DataLayer sharedInstance] isAccountEnabled:self.xmppAccount.accountNo])
{
BOOL omemoDeviceForContactFound = NO;
if(!self.contact.isGroup)
omemoDeviceForContactFound = [self.xmppAccount.omemo knownDevicesForAddressName:self.contact.contactJid].count > 0;
else
{
omemoDeviceForContactFound = NO;
for(NSDictionary* participant in [[DataLayer sharedInstance] getMembersAndParticipantsOfMuc:self.contact.contactJid forAccountId:self.xmppAccount.accountNo])
{
if(participant[@"participant_jid"])
omemoDeviceForContactFound |= [self.xmppAccount.omemo knownDevicesForAddressName:participant[@"participant_jid"]].count > 0;
else if(participant[@"member_jid"])
omemoDeviceForContactFound |= [self.xmppAccount.omemo knownDevicesForAddressName:participant[@"member_jid"]].count > 0;
if(omemoDeviceForContactFound)
break;
}
}
if(!omemoDeviceForContactFound && self.contact.isEncrypted)
{
if(!self.contact.isGroup && [[HelperTools splitJid:self.contact.contactJid][@"host"] isEqualToString:@"cheogram.com"])
{
// cheogram.com does not support OMEMO encryption as it is a PSTN gateway
// --> disable it
self.contact.isEncrypted = NO;
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
}
else if(self.contact.isGroup && ![self.contact.mucType isEqualToString:@"group"])
{
// a channel type muc has OMEMO encryption enabled, but channels don't support encryption
// --> disable it
self.contact.isEncrypted = NO;
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
}
else if(!self.contact.isGroup || (self.contact.isGroup && [self.contact.mucType isEqualToString:@"group"]))
{
// a 1:1 contact or a group type muc has OMEMO encryption enabled
UIAlertController* alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"No OMEMO keys found", @"") message:NSLocalizedString(@"This contact may not support OMEMO encrypted messages. Please try to enable encryption again in a few seconds, if you think this is wrong.", @"") preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Disable Encryption", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// Disable encryption
self.contact.isEncrypted = NO;
[self updateUIElements];
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
[alert dismissViewControllerAnimated:YES completion:nil];
}]];

[self presentViewController:alert animated:YES completion:nil];
}
}
}
#endif
[self checkOmemoSupportWithAlert:NO];

[self refreshCounter];

//init the floating last message button
Expand Down Expand Up @@ -3183,6 +3134,113 @@ -(void) stopEditing
self.editingCallback(nil); //dismiss swipe action
}

-(void) checkOmemoSupportWithAlert:(BOOL) showWarning
{
#ifndef DISABLE_OMEMO
if(self.xmppAccount && [[DataLayer sharedInstance] isAccountEnabled:self.xmppAccount.accountNo])
{
BOOL omemoDeviceForContactFound = NO;
if(!self.contact.isGroup)
omemoDeviceForContactFound = [self.xmppAccount.omemo knownDevicesForAddressName:self.contact.contactJid].count > 0;
else
{
omemoDeviceForContactFound = NO;
for(NSDictionary* participant in [[DataLayer sharedInstance] getMembersAndParticipantsOfMuc:self.contact.contactJid forAccountId:self.xmppAccount.accountNo])
{
if(participant[@"participant_jid"])
omemoDeviceForContactFound |= [self.xmppAccount.omemo knownDevicesForAddressName:participant[@"participant_jid"]].count > 0;
else if(participant[@"member_jid"])
omemoDeviceForContactFound |= [self.xmppAccount.omemo knownDevicesForAddressName:participant[@"member_jid"]].count > 0;
if(omemoDeviceForContactFound)
break;
}
}
if(!omemoDeviceForContactFound && self.contact.isEncrypted)
{
if(!self.contact.isGroup && [[HelperTools splitJid:self.contact.contactJid][@"host"] isEqualToString:@"cheogram.com"])
{
// cheogram.com does not support OMEMO encryption as it is a PSTN gateway
// --> disable it
self.contact.isEncrypted = NO;
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
}
else if(self.contact.isGroup && ![self.contact.mucType isEqualToString:@"group"])
{
// a channel type muc has OMEMO encryption enabled, but channels don't support encryption
// --> disable it
self.contact.isEncrypted = NO;
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
}
else if(!self.contact.isGroup || (self.contact.isGroup && [self.contact.mucType isEqualToString:@"group"]))
{
[self hideOmemoHUD];
if(showWarning)
{
DDLogWarn(@"Showing omemo not supported alert for: %@", self.contact);
UIAlertController* alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"No OMEMO keys found", @"") message:NSLocalizedString(@"This contact may not support OMEMO encrypted messages. Please try to enable encryption again in a few seconds, if you think this is wrong.", @"") preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Disable Encryption", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
// Disable encryption
self.contact.isEncrypted = NO;
[self updateUIElements];
[[DataLayer sharedInstance] disableEncryptForJid:self.contact.contactJid andAccountNo:self.contact.accountId];
[alert dismissViewControllerAnimated:YES completion:nil];
}]];
[self presentViewController:alert animated:YES completion:nil];
}
else
{
// async dispatch is needed to show hud on chat open
// we won't do this twice, because the user won't be able to change isEncrypted to YES,
// unless we have omemo devices for that contact
dispatch_async(dispatch_get_main_queue(), ^{
[self showOmemoHUD];
});
// request omemo devicelist
[self.xmppAccount.omemo subscribeAndFetchDevicelistIfNoSessionExistsForJid:self.contact.contactJid];
}
}
}
else
[self hideOmemoHUD];
}
#endif
}

-(void) showOmemoHUD
{
DDLogVerbose(@"Showing omemo HUD...");
if(!self.omemoHUD)
{
self.omemoHUD = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
self.omemoHUD.removeFromSuperViewOnHide = YES;
self.omemoHUD.label.text = NSLocalizedString(@"Loading OMEMO keys", @"");
}
else
self.omemoHUD.hidden = NO;
}

-(void) hideOmemoHUD
{
DDLogVerbose(@"Hiding omemo HUD...");
self.omemoHUD.hidden = YES;
}

-(void) handleOmemoFetchStateUpdate:(NSNotification*) notification
{
xmpp* account = notification.object;
MLContact* contact = [MLContact createContactFromJid:notification.userInfo[@"jid"] andAccountNo:account.accountNo];
if(self.contact && [self.contact isEqualToContact:contact])
{
DDLogDebug(@"Got omemo fetching update: %@ --> %@", contact, notification.userInfo);
if(!((NSNumber*)notification.userInfo[@"isFetching"]).boolValue)
dispatch_async(dispatch_get_main_queue(), ^{
//recheck support and show alert if needed
DDLogVerbose(@"Rechecking omemo support with alert, if needed...");
[self checkOmemoSupportWithAlert:YES];
});
}
}

-(void) showUploadHUD
{
if(!self.uploadHUD)
Expand Down

0 comments on commit 29c8039

Please sign in to comment.