Merge pull request #1012 from vector-im/keys_export

E2E keys export: Add an "Export keys" button to the settings
This commit is contained in:
manuroe
2017-02-06 15:50:14 +01:00
committed by GitHub
3 changed files with 127 additions and 11 deletions
@@ -20,7 +20,7 @@
#import "MediaPickerViewController.h"
@interface SettingsViewController : MXKViewController<UITextFieldDelegate, MediaPickerViewControllerDelegate, UITableViewDelegate, UITableViewDataSource, MXKDeviceViewDelegate>
@interface SettingsViewController : MXKViewController<UITextFieldDelegate, MediaPickerViewControllerDelegate, UITableViewDelegate, UITableViewDataSource, MXKDeviceViewDelegate, UIDocumentInteractionControllerDelegate>
@property (nonatomic) IBOutlet UITableView *tableView;
+124 -10
View File
@@ -1,5 +1,6 @@
/*
Copyright 2015 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -27,6 +28,8 @@
#import <Photos/Photos.h>
#import <MediaPlayer/MediaPlayer.h>
#import "MXKEncryptionKeysExportView.h"
#import "OLMKit/OLMKit.h"
enum {
@@ -70,6 +73,10 @@ enum {
#define LABS_CRYPTO_INDEX 0
#define LABS_COUNT 1
#define CRYPTOGRAPHY_INFO_INDEX 0
#define CRYPTOGRAPHY_EXPORT_INDEX 1
#define CRYPTOGRAPHY_COUNT 2
#define SECTION_TITLE_PADDING_WHEN_HIDDEN 0.01f
typedef void (^blockSettingsViewController_onReadyToDestroy)();
@@ -137,6 +144,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
//
UIAlertController *resetPwdAlertController;
// The document interaction Controller used to export e2e keys
UIDocumentInteractionController *documentInteractionController;
NSURL *keyExportsFile;
NSTimer *keyExportsFileDeletionTimer;
}
/**
@@ -220,6 +232,13 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
- (void)destroy
{
if (documentInteractionController)
{
[documentInteractionController dismissPreviewAnimated:NO];
[documentInteractionController dismissMenuAnimated:NO];
documentInteractionController = nil;
}
if (isSavingInProgress || isResetPwdInProgress || isEmailBindingInProgress)
{
__weak typeof(self) weakSelf = self;
@@ -798,7 +817,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
// Check whether this section is visible.
if (self.mainSession.crypto)
{
count = 1;
count = CRYPTOGRAPHY_COUNT;
}
}
return count;
@@ -1323,16 +1342,39 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
}
else if (section == SETTINGS_SECTION_CRYPTOGRAPHY_INDEX)
{
MXKTableViewCell *cryptoCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCell defaultReuseIdentifier]];
if (!cryptoCell)
if (row == CRYPTOGRAPHY_INFO_INDEX)
{
cryptoCell = [[MXKTableViewCell alloc] init];
MXKTableViewCell *cryptoCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCell defaultReuseIdentifier]];
if (!cryptoCell)
{
cryptoCell = [[MXKTableViewCell alloc] init];
}
cryptoCell.textLabel.attributedText = [self cryptographyInformation];
cryptoCell.textLabel.numberOfLines = 0;
cell = cryptoCell;
}
else if (row == CRYPTOGRAPHY_EXPORT_INDEX)
{
MXKTableViewCellWithButton *exportKeysBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]];
if (!exportKeysBtnCell)
{
exportKeysBtnCell = [[MXKTableViewCellWithButton alloc] init];
}
NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil);
[exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal];
[exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted];
[exportKeysBtnCell.mxkButton setTintColor:kVectorColorGreen];
exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17];
[exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside];
[exportKeysBtnCell.mxkButton addTarget:self action:@selector(exportEncryptionKeys:) forControlEvents:UIControlEventTouchUpInside];
exportKeysBtnCell.mxkButton.accessibilityIdentifier = nil;
cell = exportKeysBtnCell;
}
cryptoCell.textLabel.attributedText = [self cryptographyInformation];
cryptoCell.textLabel.numberOfLines = 0;
cell = cryptoCell;
}
return cell;
@@ -1427,7 +1469,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
[label sizeToFit];
return label.frame.size.height + 16;
}
else if (indexPath.section == SETTINGS_SECTION_CRYPTOGRAPHY_INDEX)
else if (indexPath.section == SETTINGS_SECTION_CRYPTOGRAPHY_INDEX && indexPath.row == CRYPTOGRAPHY_INFO_INDEX)
{
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 50)];
label.numberOfLines = 0;
@@ -2180,6 +2222,65 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
[self presentViewController:navigationController animated:YES completion:nil];
}
- (void)exportEncryptionKeys:(UITapGestureRecognizer *)recognizer
{
[currentAlert dismiss:NO];
MXKEncryptionKeysExportView *exportView = [[MXKEncryptionKeysExportView alloc] initWithMatrixSession:self.mainSession];
currentAlert = exportView;
// Use a temporary file for the export
keyExportsFile = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:@"riot-keys.txt"]];
// Make sure the file is empty
[self deleteKeyExportFile];
// Show the export dialog
__weak typeof(self) weakSelf = self;
[exportView showInViewController:self toExportKeysToFile:keyExportsFile onComplete:^(BOOL success) {
if (weakSelf && success)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
// Let another app handling this file
self->documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:keyExportsFile];
[self->documentInteractionController setDelegate:self];
if ([self->documentInteractionController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES])
{
// We want to delete the temp keys file after it has been processed by the other app.
// We use [UIDocumentInteractionControllerDelegate didEndSendingToApplication] for that
// but it is not reliable for all cases (see http://stackoverflow.com/a/21867096).
// So, arm a timer to auto delete the file after 10mins.
keyExportsFileDeletionTimer = [NSTimer scheduledTimerWithTimeInterval:600 target:self selector:@selector(deleteKeyExportFile) userInfo:self repeats:NO];
}
else
{
self->documentInteractionController = nil;
[self deleteKeyExportFile];
}
}
}];
}
- (void)deleteKeyExportFile
{
// Cancel the deletion timer if it is still here
if (keyExportsFileDeletionTimer)
{
[keyExportsFileDeletionTimer invalidate];
keyExportsFileDeletionTimer = nil;
}
// And delete the file
if (keyExportsFile && [[NSFileManager defaultManager] fileExistsAtPath:keyExportsFile.path])
{
[[NSFileManager defaultManager] removeItemAtPath:keyExportsFile.path error:nil];
}
}
#pragma mark - MediaPickerViewController Delegate
- (void)dismissMediaPicker
@@ -2449,4 +2550,17 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
[self presentViewController:resetPwdAlertController animated:YES completion:nil];
}
#pragma mark - UIDocumentInteractionControllerDelegate
- (void)documentInteractionController:(UIDocumentInteractionController *)controller didEndSendingToApplication:(NSString *)application
{
// If iOS wants to call this method, this is the right time to remove the file
[self deleteKeyExportFile];
}
- (void)documentInteractionControllerDidDismissOptionsMenu:(UIDocumentInteractionController *)controller
{
documentInteractionController = nil;
}
@end