Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(510)

Unified Diff: remoting/client/ios/keychain_wrapper.mm

Issue 2854273002: [CRD iOS] Implementing save to keychain and user defaults for login info. Refactor remoting service. (Closed)
Patch Set: Removing authenticate with refresh token from pub api. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « remoting/client/ios/keychain_wrapper.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: remoting/client/ios/keychain_wrapper.mm
diff --git a/remoting/client/ios/keychain_wrapper.mm b/remoting/client/ios/keychain_wrapper.mm
new file mode 100644
index 0000000000000000000000000000000000000000..c1ae602c8ce20a8acc90d09a27a5df4e17550d68
--- /dev/null
+++ b/remoting/client/ios/keychain_wrapper.mm
@@ -0,0 +1,206 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+#import "remoting/client/ios/keychain_wrapper.h"
+
+#import "remoting/client/ios/domain/host_info.h"
+
+static const UInt8 kKeychainItemIdentifier[] = "org.chromium.RemoteDesktop\0";
+
+@interface KeychainWrapper () {
+ NSMutableDictionary* _keychainData;
+ NSMutableDictionary* _userInfoQuery;
+}
+@end
+
+@implementation KeychainWrapper
+
+- (id)init {
+ if ((self = [super init])) {
+ OSStatus keychainErr = noErr;
+ _userInfoQuery = [[NSMutableDictionary alloc] init];
+ [_userInfoQuery setObject:(__bridge id)kSecClassGenericPassword
+ forKey:(__bridge id)kSecClass];
+ NSData* keychainItemID =
+ [NSData dataWithBytes:kKeychainItemIdentifier
+ length:strlen((const char*)kKeychainItemIdentifier)];
+ [_userInfoQuery setObject:keychainItemID
+ forKey:(__bridge id)kSecAttrGeneric];
+ [_userInfoQuery setObject:(__bridge id)kSecMatchLimitOne
+ forKey:(__bridge id)kSecMatchLimit];
+ [_userInfoQuery setObject:(__bridge id)kCFBooleanTrue
+ forKey:(__bridge id)kSecReturnAttributes];
+
+ CFMutableDictionaryRef outDictionary = nil;
+ keychainErr = SecItemCopyMatching((__bridge CFDictionaryRef)_userInfoQuery,
+ (CFTypeRef*)&outDictionary);
+ if (keychainErr == noErr) {
+ _keychainData = [self
+ secItemFormatToDictionary:(__bridge_transfer NSMutableDictionary*)
+ outDictionary];
+ } else if (keychainErr == errSecItemNotFound) {
+ [self resetKeychainItem];
+
+ if (outDictionary) {
+ CFRelease(outDictionary);
+ _keychainData = nil;
+ }
+ } else {
+ NSLog(@"Serious error.");
+ if (outDictionary) {
+ CFRelease(outDictionary);
+ _keychainData = nil;
+ }
+ }
+ }
+ return self;
+}
+
+- (void)setRefreshToken:(NSString*)refreshToken {
+ [self setObject:refreshToken forKey:(__bridge id)kSecValueData];
+}
+
+- (NSString*)refreshToken {
+ return [self objectForKey:(__bridge id)kSecValueData];
+}
+
+// Implement the mySetObject:forKey method, which writes attributes to the
+// keychain:
+- (void)setObject:(id)inObject forKey:(id)key {
+ if (inObject == nil)
+ return;
+ id currentObject = [_keychainData objectForKey:key];
+ if (![currentObject isEqual:inObject]) {
+ [_keychainData setObject:inObject forKey:key];
+ [self writeToKeychain];
+ }
+}
+
+// Implement the myObjectForKey: method, which reads an attribute value from a
+// dictionary:
+- (id)objectForKey:(id)key {
+ return [_keychainData objectForKey:key];
+}
+
+- (void)resetKeychainItem {
+ if (!_keychainData) {
+ _keychainData = [[NSMutableDictionary alloc] init];
+ } else if (_keychainData) {
+ NSMutableDictionary* tmpDictionary =
+ [self dictionaryToSecItemFormat:_keychainData];
+ OSStatus errorcode = SecItemDelete((__bridge CFDictionaryRef)tmpDictionary);
+ if (errorcode == errSecItemNotFound) {
+ // this is ok.
+ } else if (errorcode != noErr) {
+ NSLog(@"Problem deleting current keychain item.");
+ }
+ }
+
+ [_keychainData setObject:@"gaia_refresh_token"
+ forKey:(__bridge id)kSecAttrLabel];
+ [_keychainData setObject:@"Gaia fresh token"
+ forKey:(__bridge id)kSecAttrDescription];
+ [_keychainData setObject:@"" forKey:(__bridge id)kSecValueData];
+}
+
+- (NSMutableDictionary*)dictionaryToSecItemFormat:
+ (NSDictionary*)dictionaryToConvert {
+ NSMutableDictionary* returnDictionary =
+ [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
+
+ NSData* keychainItemID =
+ [NSData dataWithBytes:kKeychainItemIdentifier
+ length:strlen((const char*)kKeychainItemIdentifier)];
+ [returnDictionary setObject:keychainItemID
+ forKey:(__bridge id)kSecAttrGeneric];
+ [returnDictionary setObject:(__bridge id)kSecClassGenericPassword
+ forKey:(__bridge id)kSecClass];
+
+ NSString* passwordString =
+ [dictionaryToConvert objectForKey:(__bridge id)kSecValueData];
+ [returnDictionary
+ setObject:[passwordString dataUsingEncoding:NSUTF8StringEncoding]
+ forKey:(__bridge id)kSecValueData];
+ return returnDictionary;
+}
+
+- (NSMutableDictionary*)secItemFormatToDictionary:
+ (NSDictionary*)dictionaryToConvert {
+ NSMutableDictionary* returnDictionary =
+ [NSMutableDictionary dictionaryWithDictionary:dictionaryToConvert];
+
+ [returnDictionary setObject:(__bridge id)kCFBooleanTrue
+ forKey:(__bridge id)kSecReturnData];
+ [returnDictionary setObject:(__bridge id)kSecClassGenericPassword
+ forKey:(__bridge id)kSecClass];
+
+ CFDataRef passwordData = NULL;
+ OSStatus keychainError = noErr;
+ keychainError = SecItemCopyMatching(
+ (__bridge CFDictionaryRef)returnDictionary, (CFTypeRef*)&passwordData);
+ if (keychainError == noErr) {
+ [returnDictionary removeObjectForKey:(__bridge id)kSecReturnData];
+
+ NSString* password = [[NSString alloc]
+ initWithBytes:[(__bridge_transfer NSData*)passwordData bytes]
+ length:[(__bridge NSData*)passwordData length]
+ encoding:NSUTF8StringEncoding];
+ [returnDictionary setObject:password forKey:(__bridge id)kSecValueData];
+ } else if (keychainError == errSecItemNotFound) {
+ NSLog(@"Nothing was found in the keychain.");
+ if (passwordData) {
+ CFRelease(passwordData);
+ passwordData = nil;
+ }
+ } else {
+ NSLog(@"Serious error.\n");
+ if (passwordData) {
+ CFRelease(passwordData);
+ passwordData = nil;
+ }
+ }
+ return returnDictionary;
+}
+
+- (void)writeToKeychain {
+ CFDictionaryRef attributes = nil;
+ NSMutableDictionary* updateItem = nil;
+
+ if (SecItemCopyMatching((__bridge CFDictionaryRef)_userInfoQuery,
+ (CFTypeRef*)&attributes) == noErr) {
+ updateItem = [NSMutableDictionary
+ dictionaryWithDictionary:(__bridge_transfer NSDictionary*)attributes];
+
+ [updateItem setObject:[_userInfoQuery objectForKey:(__bridge id)kSecClass]
+ forKey:(__bridge id)kSecClass];
+
+ NSMutableDictionary* tempCheck =
+ [self dictionaryToSecItemFormat:_keychainData];
+ [tempCheck removeObjectForKey:(__bridge id)kSecClass];
+
+ OSStatus errorcode = SecItemUpdate((__bridge CFDictionaryRef)updateItem,
+ (__bridge CFDictionaryRef)tempCheck);
+ if (errorcode != noErr) {
+ NSLog(@"Couldn't update the Keychain Item. %d", (int)errorcode);
+ }
+ } else {
+ OSStatus errorcode =
+ SecItemAdd((__bridge CFDictionaryRef)
+ [self dictionaryToSecItemFormat:_keychainData],
+ NULL);
+ if (errorcode != noErr) {
+ NSLog(@"Couldn't add the Keychain Item. %d", (int)errorcode);
+ }
+ if (attributes) {
+ CFRelease(attributes);
+ attributes = nil;
+ }
+ }
+}
+
+@end
« no previous file with comments | « remoting/client/ios/keychain_wrapper.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698