X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/SharedWebCredentialViewService/SWCViewController.m?ds=sidebyside diff --git a/SharedWebCredentialViewService/SWCViewController.m b/SharedWebCredentialViewService/SWCViewController.m new file mode 100755 index 00000000..87c85b42 --- /dev/null +++ b/SharedWebCredentialViewService/SWCViewController.m @@ -0,0 +1,428 @@ +// +// SWCViewController.m +// SharedWebCredentialViewService +// +// Copyright (c) 2014 Apple Inc. All Rights Reserved. +// + +#import "SWCViewController.h" +#import +#import + +#import +#import + +#include +#include +#include "SharedWebCredential/swcagent_client.h" + +const NSString* SWC_PASSWORD_KEY = @"spwd"; +const NSString* SWC_ACCOUNT_KEY = @"acct"; +const NSString* SWC_SERVER_KEY = @"srvr"; + +// +// SWCDictionaryAdditions +// + +@interface NSDictionary (SWCDictionaryAdditions) +- (NSComparisonResult) compareCredentialDictionaryAscending:(NSDictionary *)other; +@end + +@implementation NSDictionary (SWCDictionaryAdditions) +- (NSComparisonResult)compareCredentialDictionaryAscending:(NSDictionary *)other +{ + NSComparisonResult result; + NSString *str1 = [self objectForKey:SWC_ACCOUNT_KEY], *str2 = [other objectForKey:SWC_ACCOUNT_KEY]; + if (!str1) str1 = @""; + if (!str2) str2 = @""; + + // primary sort by account name + result = [str1 localizedCaseInsensitiveCompare:str2]; + if (result == NSOrderedSame) { + // secondary sort by domain name + NSString *str3 = [self objectForKey:SWC_SERVER_KEY], *str4 = [other objectForKey:SWC_SERVER_KEY]; + if (!str3) str3 = @""; + if (!str4) str4 = @""; + + result = [str3 localizedCaseInsensitiveCompare:str4]; + } + + return result; +} +@end + + +// +// SWCItemCell +// +@interface SWCItemCell : UITableViewCell +{ + NSDictionary *_dict; + BOOL _isTicked; + UIView *_bottomLine; + UIView *_bottomLineSelected; + UIView *_topLine; + UIView *_topLineSelected; + BOOL _showSeparator; + BOOL _showTopSeparator; +} + +- (id)initWithDictionary:(NSDictionary *)dict; +@property (nonatomic, readonly) id userInfo; +@property (nonatomic, assign) BOOL showSeparator; +@end + +@implementation SWCItemCell + +@synthesize showSeparator = _showSeparator; + +- (id)initWithDictionary:(NSDictionary *)dict +{ + if ((self = [super initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil])) + { + _dict = dict; + + self.selectionStyle = UITableViewCellSelectionStyleNone; + + self.backgroundColor = [UIColor colorWithWhite:0.1 alpha:0.005]; + + self.textLabel.textColor = [UIColor blackColor]; + self.textLabel.textAlignment = NSTextAlignmentLeft; + self.textLabel.AdjustsFontSizeToFitWidth = YES; + self.textLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + + NSString *title = [dict objectForKey:SWC_ACCOUNT_KEY]; + self.textLabel.text = title ? title : @"--"; + + self.detailTextLabel.textColor = [UIColor darkGrayColor]; + self.detailTextLabel.textAlignment = NSTextAlignmentLeft; + self.detailTextLabel.AdjustsFontSizeToFitWidth = YES; + self.detailTextLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; + + NSString *subtitle = [dict objectForKey:SWC_SERVER_KEY]; + self.detailTextLabel.text = subtitle ? subtitle : @"--"; + + self.backgroundView = [[UIView alloc] init]; + self.backgroundView.backgroundColor = self.backgroundColor; + + self.imageView.image = [self _checkmarkImage: NO]; + self.imageView.hidden = YES; + + } + + return self; +} + +- (void)setTicked: (BOOL) selected +{ + _isTicked = selected; +} + +- (void)layoutSubviews +{ + + if (_bottomLine) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_bottomLine setFrame:CGRectMake(0, self.frame.size.height - (1 / scale), self.frame.size.width, 1 / scale)]; + } + + if (_bottomLineSelected) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_bottomLineSelected setFrame:CGRectMake(0, self.frame.size.height - (1 / scale), self.frame.size.width, 1 / scale)]; + } + + if (_topLine) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_topLine setFrame:CGRectMake(0, 0, self.frame.size.width, 1 / scale)]; + } + + if (_topLineSelected) { + CGFloat scale = [[UIScreen mainScreen] scale]; + [_topLineSelected setFrame:CGRectMake(0, 0, self.frame.size.width, 1 / scale)]; + } + + if (_isTicked) + { + self.imageView.hidden = NO; + } else { + self.imageView.hidden = YES; + } + + [super layoutSubviews]; + +} + +- (void)setShowSeparator:(BOOL)showSeparator { + if (_showSeparator != showSeparator) { + _showSeparator = showSeparator; + + if (_showSeparator) { + if (!_bottomLine) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _bottomLine = [[UIView alloc] initWithFrame:rectZero]; + _bottomLine.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.backgroundView addSubview:_bottomLine]; + } + if (!_bottomLineSelected) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _bottomLineSelected = [[UIView alloc] initWithFrame:rectZero]; + _bottomLineSelected.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.selectedBackgroundView addSubview: _bottomLineSelected]; + } + + } else { + if (_bottomLine) { + [_bottomLine removeFromSuperview]; + _bottomLine = nil; + } + if (_bottomLineSelected) { + [_bottomLineSelected removeFromSuperview]; + _bottomLineSelected = nil; + } + } + } +} + +- (void)setShowTopSeparator:(BOOL)showTopSeparator { + if (_showTopSeparator != showTopSeparator) { + _showTopSeparator = showTopSeparator; + + if (_showTopSeparator) { + if (!_topLine) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _topLine = [[UIView alloc] initWithFrame:rectZero]; + _topLine.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.backgroundView addSubview:_topLine]; + } + if (!_topLineSelected) { + CGRect rectZero = CGRectMake(0, 0, 0, 0); + _topLineSelected = [[UIView alloc] initWithFrame:rectZero]; + _topLineSelected.backgroundColor = [UIColor colorWithWhite:.5 alpha:.5]; + [self.selectedBackgroundView addSubview: _topLineSelected]; + } + + } else { + if (_topLine) { + [_topLine removeFromSuperview]; + _topLine = nil; + } + if (_topLineSelected) { + [_topLineSelected removeFromSuperview]; + _topLineSelected = nil; + } + } + } +} + +@end + + +// +// SWCViewController +// + +@interface SWCViewController () +{ + NSMutableArray *_credentials; // array of NSDictionary + UILabel *_topLabel; + UILabel *_middleLabel; + UITableView *_table; + NSDictionary *_selectedDict; + NSIndexPath *_selectedCell; +} + +@end + +@implementation SWCViewController + +- (NSDictionary *)selectedItem +{ + return _selectedDict; +} + +- (void)setCredentials:(NSArray *)inArray +{ + NSMutableArray *credentials = [[NSMutableArray alloc] initWithArray:inArray]; + [credentials sortUsingSelector:@selector(compareCredentialDictionaryAscending:)]; + _credentials = credentials; + if (_table) + [_table reloadData]; +} + +- (void)_enableTable +{ + [_table setUserInteractionEnabled:YES]; +} + +- (UITableView *)tableView +{ + if (_table == nil) { + _table = [[UITableView alloc] init]; + [_table setTranslatesAutoresizingMaskIntoConstraints:NO]; + [_table setAutoresizingMask:UIViewAutoresizingNone]; + [_table setBackgroundColor:[UIColor clearColor]]; + [_table setSeparatorStyle:UITableViewCellSeparatorStyleNone]; + } + [_table sizeToFit]; + + return (UITableView *)_table; +} + +-(void)loadView +{ + + UIView* view = [[UIView alloc] init]; + + UITableView* table = [self tableView]; + [table setDelegate: self]; + [table setDataSource: self]; + + [view addSubview: table]; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + CFArrayRef credentialList = swca_copy_pairs(swca_copy_pairs_request_id, &auditToken, &error); + if (error) { + NSLog(@"Unable to get accounts: %@", [(__bridge NSError*)error localizedDescription]); + } + + [self setCredentials:(__bridge NSArray*)credentialList]; + if (credentialList) { + CFRelease(credentialList); + } + + + NSDictionary* views = NSDictionaryOfVariableBindings(table); + + if ([_credentials count] > 2) + { + + NSDictionary *metrics = @{@"height":@120.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[table]-|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]-|" options:0 metrics:metrics views:views]]; + + CGFloat scale = [[UIScreen mainScreen] scale]; + table.layer.borderWidth = 1.0 / scale; + table.layer.borderColor = [UIColor colorWithWhite:.5 alpha:.5].CGColor; + + [self setPreferredContentSize:CGSizeMake(0,140)]; + + } else if ([_credentials count] == 2) { + + NSDictionary *metrics = @{@"height":@90.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[table]|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]-|" options:0 metrics:metrics views:views]]; + + [self setPreferredContentSize:CGSizeMake(0,90)]; + [table setScrollEnabled: NO]; + + } else { // [_credentials count] == 1 + + NSDictionary *metrics = @{@"height":@45.0}; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[table]|" options:0 metrics:metrics views:views]]; + [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[table(height)]|" options:0 metrics:metrics views:views]]; + + [self setPreferredContentSize:CGSizeMake(0,45)]; + [table setScrollEnabled: NO]; + + } + + [self setView:view]; +} + +-(void)viewWillAppear:(BOOL)animated +{ + + // Select the first cell by default + + NSDictionary *dict = [_credentials objectAtIndex: 0]; + _selectedDict = dict; + _selectedCell = [NSIndexPath indexPathForItem:0 inSection: 0]; + SWCItemCell *cell = (SWCItemCell *)[_table cellForRowAtIndexPath: _selectedCell]; + [cell setTicked: YES]; + [_table selectRowAtIndexPath: _selectedCell animated: NO scrollPosition: UITableViewScrollPositionTop]; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + bool result = swca_set_selection(swca_set_selection_request_id, + &auditToken, (__bridge CFDictionaryRef)dict, &error); + if (!result) { + NSLog(@"Unable to select item: %@", [(__bridge NSError*)error localizedDescription]); + } + + [super viewWillAppear:animated]; +} + + +// +// UITableView delegate methods +// + +- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section +{ + return [_credentials count]; +} + +- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + NSUInteger row = indexPath.row; + + NSDictionary *dict = [_credentials objectAtIndex:row]; + _selectedDict = dict; + + CFErrorRef error = NULL; + audit_token_t auditToken = {}; + memset(&auditToken, 0, sizeof(auditToken)); + bool result = swca_set_selection(swca_set_selection_request_id, + &auditToken, (__bridge CFDictionaryRef)dict, &error); + if (!result) { + NSLog(@"Unable to select item: %@", [(__bridge NSError*)error localizedDescription]); + } + + _selectedCell = indexPath; + SWCItemCell *cell = (SWCItemCell *)[tableView cellForRowAtIndexPath: indexPath]; + [cell setTicked: YES]; + [cell layoutSubviews]; +} + +- (void) tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath +{ + SWCItemCell *cell = (SWCItemCell *)[tableView cellForRowAtIndexPath: indexPath]; + [cell setTicked: NO]; + [cell layoutSubviews]; + +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + + NSDictionary *dict = [_credentials objectAtIndex:[indexPath row]]; + SWCItemCell *cell = [[SWCItemCell alloc] initWithDictionary:dict]; + + // show separator on top cell if there's only or or two items + if ([_credentials count] <= 2) { + cell.showTopSeparator = YES; + } else { + cell.showSeparator = YES; + + if (indexPath.row == 0) + { + cell.showTopSeparator = YES; + } + + } + + if (_selectedCell == indexPath) + { + [cell setTicked: YES]; + } else { + [cell setTicked: NO]; + } + + return cell; +} + + +@end