Scanning an invalid QR code shows an error dialog

* From the error dialog you are able to back out of scanning or try again. Adds English localization for this message.

  Adds an extra flag in OWSQRCodeScanningViewController to make sure that we don’t handle captureResults when capture is disabled (this was racing before because the call to [capture stop] is async and that was causing the cancel case to present the error dialog multiple times.

  Fixes Signal-iOS#1347

* Fixes appearance of race with starting capture
  Also marks the capture variable as atomic since it is accessed on
  multiple threads.

// FREEBIE
pull/1/head
Matthew Douglass 9 years ago committed by Michael Kirk
parent 40d6550fca
commit bbfffdf79f

@ -62,6 +62,37 @@ NS_ASSUME_NONNULL_BEGIN
// pragma mark - OWSQRScannerDelegate // pragma mark - OWSQRScannerDelegate
- (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)string - (void)controller:(OWSQRCodeScanningViewController *)controller didDetectQRCodeWithString:(NSString *)string
{ {
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:string];
if (!parser.isValid) {
DDLogError(@"Unable to parse provisioning params from QRCode: %@", string);
NSString* title = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_TITLE", @"report an invalid linking code");
NSString* body = NSLocalizedString(@"LINK_DEVICE_INVALID_CODE_BODY", @"report an invalid linking code");
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title
message:body
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"TXT_CANCEL_TITLE", nil)
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController popViewControllerAnimated:YES];
});
}];
[alertController addAction:cancelAction];
UIAlertAction *proceedAction =
[UIAlertAction actionWithTitle:NSLocalizedString(@"LINK_DEVICE_RESTART", @"attempt another linking")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[self.qrScanningController startCapture];
}];
[alertController addAction:proceedAction];
[self presentViewController:alertController animated:YES completion:nil];
} else {
NSString *title NSString *title
= NSLocalizedString(@"LINK_DEVICE_PERMISSION_ALERT_TITLE", @"confirm the users intent to link a new device"); = NSLocalizedString(@"LINK_DEVICE_PERMISSION_ALERT_TITLE", @"confirm the users intent to link a new device");
NSString *linkingDescription NSString *linkingDescription
@ -85,22 +116,16 @@ NS_ASSUME_NONNULL_BEGIN
[UIAlertAction actionWithTitle:NSLocalizedString(@"CONFIRM_LINK_NEW_DEVICE_ACTION", @"Button text") [UIAlertAction actionWithTitle:NSLocalizedString(@"CONFIRM_LINK_NEW_DEVICE_ACTION", @"Button text")
style:UIAlertActionStyleDefault style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) { handler:^(UIAlertAction *action) {
[self provisionWithString:string]; [self provisionWithParser:parser];
}]; }];
[alertController addAction:proceedAction]; [alertController addAction:proceedAction];
[self presentViewController:alertController animated:YES completion:nil]; [self presentViewController:alertController animated:YES completion:nil];
}
} }
- (void)provisionWithString:(NSString *)string - (void)provisionWithParser:(OWSDeviceProvisioningURLParser *)parser
{ {
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:string];
if (!parser.isValid) {
DDLogError(@"Unable to parse provisioning params from QRCode: %@", string);
return;
}
NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey; NSData *myPublicKey = [[TSStorageManager sharedManager] identityKeyPair].publicKey;
NSData *myPrivateKey = [[TSStorageManager sharedManager] identityKeyPair].ows_privateKey; NSData *myPrivateKey = [[TSStorageManager sharedManager] identityKeyPair].ows_privateKey;
NSString *accountIdentifier = [TSStorageManager localNumber]; NSString *accountIdentifier = [TSStorageManager localNumber];
@ -123,7 +148,7 @@ NS_ASSUME_NONNULL_BEGIN
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self presentViewController:[self retryAlertControllerWithError:error [self presentViewController:[self retryAlertControllerWithError:error
retryBlock:^{ retryBlock:^{
[self provisionWithString:string]; [self provisionWithParser:parser];
}] }]
animated:YES animated:YES
completion:nil]; completion:nil];

@ -8,7 +8,7 @@
@interface OWSQRCodeScanningViewController () @interface OWSQRCodeScanningViewController ()
@property (nonatomic) BOOL captureEnabled; @property (nonatomic) BOOL captureEnabled;
@property (nonatomic, strong) ZXCapture *capture; @property (atomic, strong) ZXCapture *capture;
@property UIView *maskingView; @property UIView *maskingView;
@property CALayer *maskingLayer; @property CALayer *maskingLayer;
@ -97,14 +97,17 @@
dispatch_async(dispatch_get_main_queue(), ^{ dispatch_async(dispatch_get_main_queue(), ^{
[self.view.layer addSublayer:self.capture.layer]; [self.view.layer addSublayer:self.capture.layer];
[self.view bringSubviewToFront:self.maskingView]; [self.view bringSubviewToFront:self.maskingView];
[self.capture start];
}); });
}); });
} } else {
[self.capture start]; [self.capture start];
}
} }
- (void)stopCapture - (void)stopCapture
{ {
self.captureEnabled = NO;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self.capture stop]; [self.capture stop];
}); });
@ -137,6 +140,8 @@
- (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result - (void)captureResult:(ZXCapture *)capture result:(ZXResult *)result
{ {
if (!self.captureEnabled)
return;
[self stopCapture]; [self stopCapture];
// TODO bounding rectangle // TODO bounding rectangle

Loading…
Cancel
Save