From 77b5642ec27bdbde1630a5631077af6aa4e3c9f8 Mon Sep 17 00:00:00 2001 From: Thilo Molitor Date: Mon, 12 Aug 2024 16:41:56 +0200 Subject: [PATCH] Show HUD while loading omemo keys the first time 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. --- Monal/Classes/MLChatViewHelper.m | 2 +- Monal/Classes/MLContact.m | 1 + Monal/Classes/MLOMEMO.m | 14 +-- Monal/Classes/chatViewController.m | 164 +++++++++++++++++++---------- 4 files changed, 121 insertions(+), 60 deletions(-) diff --git a/Monal/Classes/MLChatViewHelper.m b/Monal/Classes/MLChatViewHelper.m index e8738e41b5..b9cea10f12 100644 --- a/Monal/Classes/MLChatViewHelper.m +++ b/Monal/Classes/MLChatViewHelper.m @@ -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]; }]]; diff --git a/Monal/Classes/MLContact.m b/Monal/Classes/MLContact.m index 5532729a75..5e55a1058b 100644 --- a/Monal/Classes/MLContact.m +++ b/Monal/Classes/MLContact.m @@ -620,6 +620,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 diff --git a/Monal/Classes/MLOMEMO.m b/Monal/Classes/MLOMEMO.m index 450399c992..cf127794b7 100644 --- a/Monal/Classes/MLOMEMO.m +++ b/Monal/Classes/MLOMEMO.m @@ -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]; } } diff --git a/Monal/Classes/chatViewController.m b/Monal/Classes/chatViewController.m index 615add3ff2..d5fc278cd4 100644 --- a/Monal/Classes/chatViewController.m +++ b/Monal/Classes/chatViewController.m @@ -66,6 +66,7 @@ @interface chatViewController()* messageList; @@ -781,7 +782,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]; @@ -847,58 +848,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 @@ -3196,6 +3147,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)