Commit 0ad1be61 authored by Felix Paul Kühne's avatar Felix Paul Kühne

Added support for Touch ID to unlock app (closes #13378)

parent ae760aaf
......@@ -9,6 +9,7 @@
* Added support for system-wide search "CoreSpotlight"
* Added improved UI support for Right-to-Left languages
* Added support for the split-screen appearance in iOS 9 (#14840)
* Added support for Touch ID to unlock app (#13378)
* Added option to configure playback continuation (#14340, #14590)
* Added option to configure gestures (#15449)
* Added support for music albums with more than 1 disk (#14650)
......
......@@ -20,6 +20,16 @@
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<string>YES</string>
<key>Key</key>
<string>AllowTouchID</string>
<key>Title</key>
<string>SETTINGS_PASSCODE_LOCK_ALLOWTOUCHID</string>
<key>Type</key>
<string>PSToggleSwitchSpecifier</string>
</dict>
<dict>
<key>DefaultValue</key>
<true/>
......
B/* A single strings file, whose title is specified in your preferences schema. The strings files provide the localized content to display to the user for each of your preferences. */
......
B"CHOOSE_AUDIO_TRACK"="Choose Audio Track";
......
......@@ -62,6 +62,7 @@ NSString *const VLCDropboxSessionWasAuthorized = @"VLCDropboxSessionWasAuthorize
skipLoopFilterDefaultValue = kVLCSettingSkipLoopFilterNonRef;
NSDictionary *appDefaults = @{kVLCSettingPasscodeKey : @"",
kVLCSettingPasscodeAllowTouchID : @(1),
kVLCSettingContinueAudioInBackgroundKey : @(YES),
kVLCSettingStretchAudio : @(NO),
kVLCSettingTextEncoding : kVLCSettingTextEncodingDefaultValue,
......
......@@ -17,6 +17,7 @@
#define kVLCSettingPasscodeKey @"Passcode"
#define kVLCSettingPasscodeOnKey @"PasscodeProtection"
#define kVLCSettingPasscodeAllowTouchID @"AllowTouchID"
#define kVLCSettingContinueAudioInBackgroundKey @"BackgroundAudioPlayback"
#define kVLCSettingStretchAudio @"audio-time-stretch"
#define kVLCSettingStretchAudioOnValue @"1"
......
......@@ -14,6 +14,7 @@
#import "PAPasscodeViewController.h"
#import "VLCAppDelegate.h"
#import "SSKeychain.h"
#import <LocalAuthentication/LocalAuthentication.h>
NSString *const VLCPasscodeValidated = @"VLCPasscodeValidated";
......@@ -23,6 +24,8 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
{
PAPasscodeViewController *_passcodeLockController;
NSDictionary *_passcodeQuery;
BOOL _inValidation;
BOOL _inTouchID;
}
@end
......@@ -41,6 +44,32 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
return sharedInstance;
}
- (instancetype)init
{
self = [super init];
if (!self)
return nil;
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(appInForeground:)
name:UIApplicationDidBecomeActiveNotification
object:nil];
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)appInForeground:(NSNotification *)notification
{
/* our touch ID session is killed by the OS if the app moves to background, so re-init */
if (_inValidation) {
[self _touchIDQuery];
}
}
- (NSString *)_obtainPasscode
{
NSString *passcode = [SSKeychain passwordForService:VLCPasscode account:VLCPasscode];
......@@ -71,6 +100,11 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
- (void)validatePasscode
{
/* we may be called repeatedly as Touch ID uses an out-of-process dialog */
if (_inValidation)
return;
_inValidation = YES;
NSString *passcode = [self _obtainPasscode];
if ([passcode isEqualToString:@""]) {
[[NSNotificationCenter defaultCenter] postNotificationName:VLCPasscodeValidated object:self];
......@@ -88,8 +122,32 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:_passcodeLockController];
navCon.modalPresentationStyle = UIModalPresentationFullScreen;
[appDelegate.window.rootViewController presentViewController:navCon animated:NO completion:nil];
if (SYSTEM_RUNS_IOS8_OR_LATER) {
if ([[NSUserDefaults standardUserDefaults] boolForKey:kVLCSettingPasscodeAllowTouchID]) {
[self _touchIDQuery];
}
}
}
- (void)_touchIDQuery
{
/* don't launch multiple times */
if (_inTouchID)
return;
_inTouchID = YES;
LAContext *myContext = [[LAContext alloc] init];
if ([myContext canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:nil]) {
[myContext evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:NSLocalizedString(@"TOUCHID_UNLOCK", nil)
reply:^(BOOL success, NSError *error) {
if (success) {
[self PAPasscodeViewControllerDidEnterPasscode:nil];
} else if (error.code == LAErrorSystemCancel)
_inTouchID = NO;
}];
}
}
- (void)PAPasscodeViewControllerDidEnterPasscode:(PAPasscodeViewController *)controller
{
......@@ -97,6 +155,8 @@ NSString *const VLCPasscode = @"org.videolan.vlc-ios.passcode";
VLCAppDelegate *appDelegate = (VLCAppDelegate *)[UIApplication sharedApplication].delegate;
[appDelegate.window.rootViewController dismissViewControllerAnimated:YES completion:nil];
_inValidation = NO;
_inTouchID = NO;
}
- (void)PAPasscodeViewController:(PAPasscodeViewController *)controller didFailToEnterPasscode:(NSInteger)attempts
......
......@@ -249,6 +249,7 @@ static NSString *WiFiCellIdentifier = @"VLCMenuWiFiCell";
settingsVC.showCreditsFooter = NO;
viewController = settingsVC;
[self.settingsController willShow];
} else if (itemIndex == 1)
viewController = [[VLCAboutViewController alloc] init];
} else {
......
......@@ -16,4 +16,6 @@
@property (nonatomic, retain) IASKAppSettingsViewController *viewController;
- (void)willShow;
@end
......@@ -39,6 +39,22 @@
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)willShow
{
[self filterCellsWithAnimation:NO];
}
- (void)filterCellsWithAnimation:(BOOL)shouldAnimate
{
NSMutableSet *hideKeys = [[NSMutableSet alloc] init];
VLCKeychainCoordinator *keychainCoordinator = [VLCKeychainCoordinator defaultCoordinator];
if (![keychainCoordinator passcodeLockEnabled])
[hideKeys addObject:kVLCSettingPasscodeAllowTouchID];
[self.viewController setHiddenKeys:hideKeys animated:shouldAnimate];
}
- (void)settingDidChange:(NSNotification*)notification
{
if ([notification.object isEqual:kVLCSettingPasscodeOnKey]) {
......@@ -61,7 +77,10 @@
}
- (void)didChangePasscodeStatus:(BOOL)passcodeEnabled {
- (void)didChangePasscodeStatus:(BOOL)passcodeEnabled
{
[self filterCellsWithAnimation:YES];
BOOL spotlightEnabled = !passcodeEnabled;
[[MLMediaLibrary sharedMediaLibrary] setSpotlightIndexingEnabled:spotlightEnabled];
if (!spotlightEnabled) {
......
......@@ -142,6 +142,7 @@
7D74177A1AE2D3CE001F1997 /* VLCNavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D7417791AE2D3CE001F1997 /* VLCNavigationController.m */; };
7D84E4C61B41AB2800EA7D1F /* VideoToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C51B41AB2800EA7D1F /* VideoToolbox.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
7D84E4C91B41ABCE00EA7D1F /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D84E4C81B41ABCE00EA7D1F /* CoreMedia.framework */; };
7D8968711BD3058800F4EAAD /* LocalAuthentication.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7D8968701BD3058800F4EAAD /* LocalAuthentication.framework */; settings = {ATTRIBUTES = (Weak, ); }; };
7D89786F185DED88009BAB5D /* VLCDownloadViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D89786E185DED88009BAB5D /* VLCDownloadViewController.xib */; };
7D89787D185DF794009BAB5D /* VLCOpenNetworkStreamViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7D89787C185DF794009BAB5D /* VLCOpenNetworkStreamViewController.xib */; };
7D9289751877459B009108FD /* VLCFirstStepsThirdPageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7D9289731877459B009108FD /* VLCFirstStepsThirdPageViewController.m */; };
......@@ -612,6 +613,7 @@
7D8139CD1865211900D65504 /* ms */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ms; path = ms.lproj/Localizable.strings; sourceTree = "<group>"; };
7D84E4C51B41AB2800EA7D1F /* VideoToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = VideoToolbox.framework; path = System/Library/Frameworks/VideoToolbox.framework; sourceTree = SDKROOT; };
7D84E4C81B41ABCE00EA7D1F /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; };
7D8968701BD3058800F4EAAD /* LocalAuthentication.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = LocalAuthentication.framework; path = System/Library/Frameworks/LocalAuthentication.framework; sourceTree = SDKROOT; };
7D89786E185DED88009BAB5D /* VLCDownloadViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCDownloadViewController.xib; path = Resources/VLCDownloadViewController.xib; sourceTree = SOURCE_ROOT; };
7D89787C185DF794009BAB5D /* VLCOpenNetworkStreamViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = VLCOpenNetworkStreamViewController.xib; path = Resources/VLCOpenNetworkStreamViewController.xib; sourceTree = SOURCE_ROOT; };
7D8E19271B6BC186000D7C74 /* VLC WatchKit App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "VLC WatchKit App.entitlements"; sourceTree = "<group>"; };
......@@ -847,6 +849,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
7D8968711BD3058800F4EAAD /* LocalAuthentication.framework in Frameworks */,
DD2789E41B67A88600CED769 /* WatchConnectivity.framework in Frameworks */,
7D2DF7C31B67777D00FB78AB /* libc++.tbd in Frameworks */,
7D2DF7C11B67760100FB78AB /* libGTLTouchStaticLib.a in Frameworks */,
......@@ -1352,6 +1355,7 @@
7D94FCDD16DE7D1000F2623B /* Frameworks */ = {
isa = PBXGroup;
children = (
7D8968701BD3058800F4EAAD /* LocalAuthentication.framework */,
7DC71D0D1BC81F70001FACAA /* AVFoundation.framework */,
7DF28AE41BA31D9C0030C944 /* libSystem.tbd */,
7DF28AE21BA31D770030C944 /* libcommonCrypto.tbd */,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment