Provision device from QRCode.

NEEDS DESIGN - will likely have an intermediate "device manager" screen.

* extracted QRCode Scanner into re-usable ViewController

// FREEBIE
This commit is contained in:
Michael Kirk 2016-08-18 19:47:21 -04:00
parent 6545161192
commit 84156698c4
16 changed files with 377 additions and 126 deletions

View File

@ -3,7 +3,8 @@ source 'https://github.com/CocoaPods/Specs.git'
target 'Signal' do
pod 'SocketRocket', :git => 'https://github.com/facebook/SocketRocket.git'
pod 'SignalServiceKit', :git => 'https://github.com/WhisperSystems/SignalServiceKit.git'
#pod 'SignalServiceKit', :git => 'https://github.com/WhisperSystems/SignalServiceKit.git'
pod 'SignalServiceKit', path: '../SignalServiceKit'
pod 'OpenSSL', '~> 1.0.208'
pod 'PastelogKit', '~> 1.3'
pod 'FFCircularProgressView', '~> 0.5'

View File

@ -119,19 +119,16 @@ DEPENDENCIES:
- OpenSSL (~> 1.0.208)
- PastelogKit (~> 1.3)
- SCWaveformView (~> 1.0)
- SignalServiceKit (from `https://github.com/WhisperSystems/SignalServiceKit.git`)
- SignalServiceKit (from `../SignalServiceKit`)
- SocketRocket (from `https://github.com/facebook/SocketRocket.git`)
EXTERNAL SOURCES:
SignalServiceKit:
:git: https://github.com/WhisperSystems/SignalServiceKit.git
:path: "../SignalServiceKit"
SocketRocket:
:git: https://github.com/facebook/SocketRocket.git
CHECKOUT OPTIONS:
SignalServiceKit:
:commit: 1d0b645fc98545ba09d2828c1908689d3052ca4c
:git: https://github.com/WhisperSystems/SignalServiceKit.git
SocketRocket:
:commit: 8096fef47d582bff8ae3758c9ae7af1d55ea53d6
:git: https://github.com/facebook/SocketRocket.git
@ -161,6 +158,6 @@ SPEC CHECKSUMS:
UnionFind: c33be5adb12983981d6e827ea94fc7f9e370f52d
YapDatabase: 713d4018cfacbd6e77dd430710ca84730e450980
PODFILE CHECKSUM: 060ff4edf8b7a110984cb2c1ffef3f6e19a6b8b6
PODFILE CHECKSUM: fa9416a71a75bf01fde5554c0505c69f88921ab7
COCOAPODS: 1.0.1

View File

@ -18,6 +18,10 @@
45843D1F1D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; };
45843D201D2236B30013E85A /* OWSContactsSearcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */; };
45843D221D223BA10013E85A /* OWSContactsSearcherTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */; };
458E38311D6682450094BD24 /* OWSQRCodeScanningViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */; };
458E38341D66873D0094BD24 /* OWSLinkDeviceViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */; };
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */; };
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */; };
459C3F0D1C9B3A1B003ACF51 /* TSMessageAdapterTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */; };
45C681B71D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
45C681B81D305A580050903A /* OWSCall.m in Sources */ = {isa = PBXBuildFile; fileRef = 45C681B61D305A580050903A /* OWSCall.m */; };
@ -519,6 +523,13 @@
45843D1D1D2236B30013E85A /* OWSContactsSearcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSContactsSearcher.h; sourceTree = "<group>"; };
45843D1E1D2236B30013E85A /* OWSContactsSearcher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcher.m; sourceTree = "<group>"; };
45843D211D223BA10013E85A /* OWSContactsSearcherTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSContactsSearcherTest.m; sourceTree = "<group>"; };
458E382F1D6682450094BD24 /* OWSQRCodeScanningViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSQRCodeScanningViewController.h; sourceTree = "<group>"; };
458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSQRCodeScanningViewController.m; sourceTree = "<group>"; };
458E38321D66873D0094BD24 /* OWSLinkDeviceViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSLinkDeviceViewController.h; sourceTree = "<group>"; };
458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSLinkDeviceViewController.m; sourceTree = "<group>"; };
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSDeviceProvisioningURLParser.h; sourceTree = "<group>"; };
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSDeviceProvisioningURLParser.m; sourceTree = "<group>"; };
458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OWSDeviceProvisioningURLParserTest.m; path = Models/OWSDeviceProvisioningURLParserTest.m; sourceTree = "<group>"; };
459C3F0C1C9B3A1B003ACF51 /* TSMessageAdapterTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSMessageAdapterTest.m; path = "view controllers/Signals/TSMessageAdapters/TSMessageAdapterTest.m"; sourceTree = "<group>"; };
45C681B51D305A580050903A /* OWSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSCall.h; sourceTree = "<group>"; };
45C681B61D305A580050903A /* OWSCall.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSCall.m; sourceTree = "<group>"; };
@ -1113,13 +1124,6 @@
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
457F3AB01D1470CF00C51351 /* view controllers */ = {
isa = PBXGroup;
children = (
);
name = "view controllers";
sourceTree = "<group>";
};
457F3AC01D14A0F700C51351 /* Models */ = {
isa = PBXGroup;
children = (
@ -1134,10 +1138,20 @@
45C681B61D305A580050903A /* OWSCall.m */,
453D28B81D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.h */,
453D28B91D332DB100D523F0 /* OWSMessagesBubblesSizeCalculator.m */,
458E38351D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.h */,
458E38361D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m */,
);
path = Models;
sourceTree = "<group>";
};
458E38381D6699110094BD24 /* Models */ = {
isa = PBXGroup;
children = (
458E38391D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m */,
);
name = Models;
sourceTree = "<group>";
};
459C3F0E1C9B3A20003ACF51 /* TSMessageAdapters */ = {
isa = PBXGroup;
children = (
@ -1678,6 +1692,8 @@
B6BADBE61B88D1AC0086A80D /* LockInteractionController.m */,
76EB050B18170B33006006FC /* InCallViewController.h */,
76EB050C18170B33006006FC /* InCallViewController.m */,
458E382F1D6682450094BD24 /* OWSQRCodeScanningViewController.h */,
458E38301D6682450094BD24 /* OWSQRCodeScanningViewController.m */,
);
name = "View Controllers";
path = "view controllers";
@ -1803,7 +1819,7 @@
B660F66C1C29867F00687D6E /* test */ = {
isa = PBXGroup;
children = (
457F3AB01D1470CF00C51351 /* view controllers */,
458E38381D6699110094BD24 /* Models */,
459C3F0E1C9B3A20003ACF51 /* TSMessageAdapters */,
B660F66D1C29867F00687D6E /* audio */,
B660F6731C29867F00687D6E /* call */,
@ -2220,6 +2236,8 @@
B66B9F7C1AEAF40500E2E609 /* NotificationSettingsOptionsViewController.m */,
FCD274E91A5AFDDB00202277 /* AboutTableViewController.h */,
FCD274EA1A5AFDDB00202277 /* AboutTableViewController.m */,
458E38321D66873D0094BD24 /* OWSLinkDeviceViewController.h */,
458E38331D66873D0094BD24 /* OWSLinkDeviceViewController.m */,
);
name = Settings;
sourceTree = "<group>";
@ -2614,6 +2632,7 @@
76EB060218170B33006006FC /* InitiatorSessionDescriptor.m in Sources */,
76EB05FC18170B33006006FC /* CallConnectUtil_Server.m in Sources */,
B6DA6B071B8A2F9A00CA6F98 /* AppStoreRating.m in Sources */,
458E38311D6682450094BD24 /* OWSQRCodeScanningViewController.m in Sources */,
76EB062418170B33006006FC /* PriorityQueue.m in Sources */,
B6BADBE71B88D1AC0086A80D /* LockInteractionController.m in Sources */,
76EB061A18170B33006006FC /* DiscardingLog.m in Sources */,
@ -2698,12 +2717,14 @@
E197B61118BBEC1A00F073E5 /* AudioProcessor.m in Sources */,
FCAC964019FEF99A0046DFC5 /* InboxTableViewCell.m in Sources */,
76EB05EA18170B33006006FC /* CallProgress.m in Sources */,
458E38371D668EBF0094BD24 /* OWSDeviceProvisioningURLParser.m in Sources */,
FCFA64B41A24F3880007FB87 /* UIColor+OWS.m in Sources */,
76EB05C218170B33006006FC /* DhPacketSharedSecretHashes.m in Sources */,
B6C93C4E199567AD00EDF894 /* DebugLogger.m in Sources */,
76EB063218170B33006006FC /* Crc32.m in Sources */,
E197B62418BBF5BB00F073E5 /* SoundPlayer.m in Sources */,
E197B61018BBEC1A00F073E5 /* EncodedAudioPacket.m in Sources */,
458E38341D66873D0094BD24 /* OWSLinkDeviceViewController.m in Sources */,
76EB063618170B33006006FC /* DataUtil.m in Sources */,
E197B60C18BBEC1A00F073E5 /* AudioPacker.m in Sources */,
E197B61218BBEC1A00F073E5 /* AudioStretcher.m in Sources */,
@ -2840,6 +2861,7 @@
B660F72C1C29988E00687D6E /* HttpRequestUtil.m in Sources */,
B660F72D1C29988E00687D6E /* HttpResponse.m in Sources */,
B660F72E1C29988E00687D6E /* HttpManager.m in Sources */,
458E383A1D6699FA0094BD24 /* OWSDeviceProvisioningURLParserTest.m in Sources */,
B660F72F1C29988E00687D6E /* HttpSocket.m in Sources */,
B660F7301C29988E00687D6E /* IpAddress.m in Sources */,
B660F7311C29988E00687D6E /* IpEndPoint.m in Sources */,

View File

@ -0,0 +1,15 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
NS_ASSUME_NONNULL_BEGIN
@interface OWSDeviceProvisioningURLParser : NSObject
@property (readonly, getter=isValid) BOOL valid;
@property (nonatomic, readonly) NSString *ephemeralDeviceId;
@property (nonatomic, readonly) NSData *publicKey;
- (instancetype)initWithProvisioningURL:(NSString *)provisioningURL;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,39 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSDeviceProvisioningURLParser.h"
#import "NSData+Base64.h"
#import <AxolotlKit/NSData+keyVersionByte.h>
NS_ASSUME_NONNULL_BEGIN
NSString *const OWSQueryItemNameEphemeralDeviceIdKey = @"uuid";
NSString *const OWSQueryItemNameEncodedPublicKeyKey = @"pub_key";
@implementation OWSDeviceProvisioningURLParser
- (instancetype)initWithProvisioningURL:(NSString *)provisioningURL
{
self = [super init];
if (!self) {
return self;
}
NSURLComponents *components = [NSURLComponents componentsWithString:provisioningURL];
for (NSURLQueryItem *queryItem in [components queryItems]) {
if ([queryItem.name isEqualToString:OWSQueryItemNameEphemeralDeviceIdKey]) {
_ephemeralDeviceId = queryItem.value;
} else if ([queryItem.name isEqualToString:OWSQueryItemNameEncodedPublicKeyKey]) {
NSString *encodedPublicKey = queryItem.value;
_publicKey = [[NSData dataFromBase64String:encodedPublicKey] removeKeyType];
} else {
DDLogWarn(@"Unkown query item in provisioning string: %@", queryItem.name);
}
}
_valid = _ephemeralDeviceId && _publicKey;
return self;
}
@end
NS_ASSUME_NONNULL_END

View File

@ -1408,8 +1408,8 @@ A0 09 9A FF A8 8A 09 99</string>
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
<rect key="frame" x="15" y="11" width="200" height="21"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Network Status" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uNq-FV-lwt">
<rect key="frame" x="15" y="12" width="200" height="19.5"/>
<constraints>
<constraint firstAttribute="width" constant="200" id="q6L-Sa-lrA"/>
</constraints>
@ -1474,9 +1474,29 @@ A0 09 9A FF A8 8A 09 99</string>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="dkL-Nz-E6H" style="IBUITableViewCellStyleDefault" id="Xx7-pz-aLN" userLabel="Advanced Cell">
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hrc-lZ-NeA" style="IBUITableViewCellStyleDefault" id="wZ8-fs-Ylw" userLabel="Linked Devices Cell">
<rect key="frame" x="0.0" y="314" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="wZ8-fs-Ylw" id="Ua5-nw-s2z">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Linked Devices" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hrc-lZ-NeA">
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="tWr-1v-Sq9" kind="push" id="LTQ-a4-Xbb"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="dkL-Nz-E6H" style="IBUITableViewCellStyleDefault" id="Xx7-pz-aLN" userLabel="Advanced Cell">
<rect key="frame" x="0.0" y="358" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="Xx7-pz-aLN" id="pMA-vR-8Ae">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
@ -1492,7 +1512,7 @@ A0 09 9A FF A8 8A 09 99</string>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="qeN-f1-cIQ" style="IBUITableViewCellStyleDefault" id="EI4-kQ-MMA" userLabel="About Cell">
<rect key="frame" x="0.0" y="358" width="320" height="44"/>
<rect key="frame" x="0.0" y="402" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="EI4-kQ-MMA" id="czg-5p-aVz">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
@ -1513,7 +1533,7 @@ A0 09 9A FF A8 8A 09 99</string>
<tableViewSection id="FdD-MV-PUQ">
<cells>
<tableViewCell autoresizesSubviews="NO" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="100" id="R82-FT-SEA" userLabel="Destroy Account Cell">
<rect key="frame" x="0.0" y="402" width="320" height="100"/>
<rect key="frame" x="0.0" y="446" width="320" height="100"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="R82-FT-SEA" id="Ok9-fE-WhB">
<rect key="frame" x="0.0" y="0.0" width="320" height="99.5"/>
@ -1564,6 +1584,7 @@ A0 09 9A FF A8 8A 09 99</string>
<outlet property="aboutLabel" destination="qeN-f1-cIQ" id="kmc-iU-NK5"/>
<outlet property="advancedLabel" destination="dkL-Nz-E6H" id="HUw-SB-apQ"/>
<outlet property="destroyAccountButton" destination="4Mk-ly-6fq" id="6Xj-Rb-kfF"/>
<outlet property="linkedDevicesLabel" destination="hrc-lZ-NeA" id="VkD-E5-2kW"/>
<outlet property="networkStatusHeader" destination="uNq-FV-lwt" id="vca-cC-nXG"/>
<outlet property="networkStatusLabel" destination="tg3-dQ-odw" id="l6J-8y-maW"/>
<outlet property="notificationsLabel" destination="tRQ-1p-6aT" id="sbi-Q3-Mge"/>
@ -1577,6 +1598,25 @@ A0 09 9A FF A8 8A 09 99</string>
</objects>
<point key="canvasLocation" x="-2860" y="-3154"/>
</scene>
<!--Link Device-->
<scene sceneID="all-Be-y2s">
<objects>
<viewController id="tWr-1v-Sq9" customClass="OWSLinkDeviceViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="HSZ-fb-tHK"/>
<viewControllerLayoutGuide type="bottom" id="nre-8Q-MvI"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="XYT-jy-1yR">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" title="Link Device" id="OnR-Ni-zff"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="lPR-Bk-TZT" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-2415" y="-3154"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="aWR-d3-s5V">
<objects>

View File

@ -0,0 +1,7 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSQRCodeScanningViewController.h"
@interface OWSLinkDeviceViewController : OWSQRCodeScanningViewController
@end

View File

@ -0,0 +1,55 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSLinkDeviceViewController.h"
#import "OWSDeviceProvisioningURLParser.h"
#import <SignalServiceKit/ECKeyPair+OWSPrivateKey.h>
#import <SignalServiceKit/OWSDeviceProvisioner.h>
#import <SignalServiceKit/TSStorageManager+IdentityKeyStore.h>
#import <SignalServiceKit/TSStorageManager+keyingMaterial.h>
NS_ASSUME_NONNULL_BEGIN
@implementation OWSLinkDeviceViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
}
- (void)didDetectQRCodeWithString:(NSString *)string
{
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 *myPrivateKey = [[TSStorageManager sharedManager] identityKeyPair].ows_privateKey;
NSString *accountIdentifier = [TSStorageManager localNumber];
OWSDeviceProvisioner *provisioner = [[OWSDeviceProvisioner alloc] initWithMyPublicKey:myPublicKey
myPrivateKey:myPrivateKey
theirPublicKey:parser.publicKey
theirEphemeralDeviceId:parser.ephemeralDeviceId
accountIdentifier:accountIdentifier];
[provisioner provisionWithSuccess:^{
DDLogInfo(@"Successfully provisioned device.");
}
failure:^(NSError *error) {
DDLogError(@"Failed to provision device with error: %@", error);
}];
// TODO show progress. Maybe even incremental with progress callback in provisioner.
}
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,16 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
@interface OWSQRCodeScanningViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureDevice *device;
@property (nonatomic, strong) AVCaptureDeviceInput *input;
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer;
@property (nonatomic, strong) UIView *highlightView;
@end

View File

@ -0,0 +1,85 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSQRCodeScanningViewController.h"
#import "UIColor+OWS.h"
@implementation OWSQRCodeScanningViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = NSLocalizedString(@"SCAN_KEY", @"");
self.highlightView = [[UIView alloc] init];
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin
| UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin;
self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor;
self.highlightView.layer.borderWidth = 4;
[self.view addSubview:self.highlightView];
self.session = [[AVCaptureSession alloc] init];
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
if (self.input) {
[self.session addInput:self.input];
} else {
DDLogDebug(@"Error: %@", error);
}
self.output = [[AVCaptureMetadataOutput alloc] init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[self.session addOutput:self.output];
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.prevLayer.frame = self.view.bounds;
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer insertSublayer:self.prevLayer atIndex:0];
[self.session startRunning];
[self.view bringSubviewToFront:self.highlightView];
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputMetadataObjects:(NSArray *)metadataObjects
fromConnection:(AVCaptureConnection *)connection
{
CGRect highlightViewRect = CGRectZero;
AVMetadataMachineReadableCodeObject *barCodeObject;
NSString *detectionString = nil;
NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ];
for (AVMetadataObject *metadata in metadataObjects) {
for (NSString *type in barCodeTypes) {
if ([metadata.type isEqualToString:type]) {
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer
transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
highlightViewRect = barCodeObject.bounds;
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
break;
}
}
if (detectionString != nil) {
[self didDetectQRCodeWithString:detectionString];
[self.session stopRunning];
break;
}
}
self.highlightView.frame = highlightViewRect;
}
- (void)didDetectQRCodeWithString:(NSString *)string
{
// Override in subclass. Subclass is responsible for dismissing this view controller.
DDLogInfo(@"Scanned QRCode with string value: %@", string);
}
@end

View File

@ -4,18 +4,11 @@
//
// Created by Christine Corbett Moran on 3/29/14.
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import <AVFoundation/AVFoundation.h>
#import <UIKit/UIKit.h>
@interface ScanIdentityBarcodeViewController : UIViewController <AVCaptureMetadataOutputObjectsDelegate>
#import "OWSQRCodeScanningViewController.h"
@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureDevice *device;
@property (nonatomic, strong) AVCaptureDeviceInput *input;
@property (nonatomic, strong) AVCaptureMetadataOutput *output;
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *prevLayer;
@interface ScanIdentityBarcodeViewController : OWSQRCodeScanningViewController
@property (nonatomic, strong) UIView *highlightView;
@property (nonatomic, strong) NSData *identityKey;
@end

View File

@ -6,104 +6,35 @@
// Copyright (c) 2014 Open Whisper Systems. All rights reserved.
//
#import "NSData+Base64.h"
#import "ScanIdentityBarcodeViewController.h"
#import "UIColor+OWS.h"
#import "ScanIdentityBarcodeViewController.h"
#import "NSData+Base64.h"
@implementation ScanIdentityBarcodeViewController
- (void)viewDidLoad {
[super viewDidLoad];
- (void)didDetectQRCodeWithString:(NSString *)string
{
NSData *data = [NSData dataFromBase64String:string];
NSString *dialogTitle;
NSString *dialogDescription;
self.title = NSLocalizedString(@"SCAN_KEY", @"");
self.highlightView = [[UIView alloc] init];
self.highlightView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin |
UIViewAutoresizingFlexibleBottomMargin;
self.highlightView.layer.borderColor = [UIColor ows_greenColor].CGColor;
self.highlightView.layer.borderWidth = 4;
[self.view addSubview:self.highlightView];
self.session = [[AVCaptureSession alloc] init];
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = nil;
self.input = [AVCaptureDeviceInput deviceInputWithDevice:self.device error:&error];
if (self.input) {
[self.session addInput:self.input];
if ([data isEqualToData:self.identityKey]) {
dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @"");
dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @"");
} else {
DDLogDebug(@"Error: %@", error);
dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @"");
dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @"");
}
self.output = [[AVCaptureMetadataOutput alloc] init];
[self.output setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
[self.session addOutput:self.output];
self.output.metadataObjectTypes = [self.output availableMetadataObjectTypes];
self.prevLayer = [AVCaptureVideoPreviewLayer layerWithSession:self.session];
self.prevLayer.frame = self.view.bounds;
self.prevLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
[self.view.layer insertSublayer:self.prevLayer atIndex:0];
[self.session startRunning];
[self.view bringSubviewToFront:self.highlightView];
}
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputMetadataObjects:(NSArray *)metadataObjects
fromConnection:(AVCaptureConnection *)connection {
CGRect highlightViewRect = CGRectZero;
AVMetadataMachineReadableCodeObject *barCodeObject;
NSString *detectionString = nil;
NSArray *barCodeTypes = @[ AVMetadataObjectTypeQRCode ];
for (AVMetadataObject *metadata in metadataObjects) {
for (NSString *type in barCodeTypes) {
if ([metadata.type isEqualToString:type]) {
barCodeObject = (AVMetadataMachineReadableCodeObject *)[self.prevLayer
transformedMetadataObjectForMetadataObject:(AVMetadataMachineReadableCodeObject *)metadata];
highlightViewRect = barCodeObject.bounds;
detectionString = [(AVMetadataMachineReadableCodeObject *)metadata stringValue];
break;
}
}
if (detectionString != nil) {
NSData *detectionData = [NSData dataFromBase64String:detectionString];
NSString *dialogTitle;
NSString *dialogDescription;
if ([detectionData isEqualToData:self.identityKey]) {
dialogTitle = NSLocalizedString(@"SCAN_KEY_VERIFIED_TITLE", @"");
dialogDescription = NSLocalizedString(@"SCAN_KEY_VERIFIED_TEXT", @"");
} else {
dialogTitle = NSLocalizedString(@"SCAN_KEY_CONFLICT_TITLE", @"");
dialogDescription = NSLocalizedString(@"SCAN_KEY_CONFLICT_TEXT", @"");
}
[self.session stopRunning];
UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle
message:dialogDescription
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:controller
animated:YES
completion:^{
[self performSelector:@selector(dismissScannerAfterSuccesfullScan)
withObject:nil
afterDelay:5];
}];
break;
}
}
self.highlightView.frame = highlightViewRect;
UIAlertController *controller = [UIAlertController alertControllerWithTitle:dialogTitle
message:dialogDescription
preferredStyle:UIAlertControllerStyleAlert];
[self
presentViewController:controller
animated:YES
completion:^{
[self performSelector:@selector(dismissScannerAfterSuccesfullScan) withObject:nil afterDelay:5];
}];
}
#pragma mark - Action
@ -111,7 +42,7 @@
- (void)dismissScannerAfterSuccesfullScan {
[self dismissViewControllerAnimated:YES
completion:^{
[self closeButtonAction:nil];
[self closeButtonAction:nil];
}];
}

View File

@ -16,6 +16,7 @@
@property (strong, nonatomic) IBOutlet UILabel *networkStatusHeader;
@property (strong, nonatomic) IBOutlet UILabel *privacyLabel;
@property (strong, nonatomic) IBOutlet UILabel *notificationsLabel;
@property (strong, nonatomic) IBOutlet UILabel *linkedDevicesLabel;
@property (strong, nonatomic) IBOutlet UILabel *advancedLabel;
@property (strong, nonatomic) IBOutlet UILabel *aboutLabel;
@property (strong, nonatomic) IBOutlet UIButton *destroyAccountButton;

View File

@ -33,16 +33,16 @@
#define kRegisteredNumberRow 0
#define kPrivacyRow 0
#define kNotificationRow 1
#define kAdvancedRow 2
#define kAboutRow 3
#define kAdvancedRow 3
#define kAboutRow 4
#define kNetworkRow 0
#define kUnregisterRow 0
typedef enum {
kRegisteredRows = 1,
kGeneralRows = 4,
kRegisteredRows = 1,
kGeneralRows = 5,
kNetworkStatusRows = 1,
kUnregisterRows = 1,
kUnregisterRows = 1,
} kRowsForSection;
typedef enum {
@ -79,6 +79,8 @@ typedef enum {
self.advancedLabel.text = NSLocalizedString(@"SETTINGS_ADVANCED_TITLE", @"");
self.aboutLabel.text = NSLocalizedString(@"SETTINGS_ABOUT", @"");
self.notificationsLabel.text = NSLocalizedString(@"SETTINGS_NOTIFICATIONS", nil);
self.linkedDevicesLabel.text = NSLocalizedString(
@"LINKED_DEVICES_LABEL", @"table cell label, when pressed takes you to manage your linked devices.");
[self.destroyAccountButton setTitle:NSLocalizedString(@"SETTINGS_DELETE_ACCOUNT_BUTTON", @"")
forState:UIControlStateNormal];
}

View File

@ -0,0 +1,47 @@
// Copyright © 2016 Open Whisper Systems. All rights reserved.
#import "OWSDeviceProvisioningURLParser.h"
#import <SignalServiceKit/NSData+Base64.h>
#import <XCTest/XCTest.h>
@interface OWSDeviceProvisioningURLParserTest : XCTestCase
@end
@implementation OWSDeviceProvisioningURLParserTest
- (void)testValid
{
OWSDeviceProvisioningURLParser *parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@""];
XCTAssertFalse(parser.isValid);
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=MTIz"];
XCTAssertFalse(parser.isValid);
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?pub_key=MTIz"];
XCTAssertFalse(parser.isValid);
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/uuid=asd&pub_key=MTIz"];
XCTAssertFalse(parser.isValid);
parser = [[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
XCTAssert(parser.isValid);
}
- (void)testPublicKey
{
OWSDeviceProvisioningURLParser *parser =
[[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
XCTAssertEqualObjects(@"MTIz", [parser.publicKey base64EncodedString]);
}
- (void)testEphemeralDeviceId
{
OWSDeviceProvisioningURLParser *parser =
[[OWSDeviceProvisioningURLParser alloc] initWithProvisioningURL:@"ts:/?uuid=asd&pub_key=MTIz"];
XCTAssertEqualObjects(@"asd", parser.ephemeralDeviceId);
}
@end