]> git.saurik.com Git - apple/security.git/blobdiff - Keychain/SyncViewController.m
Security-57031.1.35.tar.gz
[apple/security.git] / Keychain / SyncViewController.m
diff --git a/Keychain/SyncViewController.m b/Keychain/SyncViewController.m
new file mode 100644 (file)
index 0000000..bdbe557
--- /dev/null
@@ -0,0 +1,241 @@
+//
+//  SyncViewController.m
+//  Keychain
+//
+//  Created by john on 10/22/12.
+//
+//
+
+#import "SyncViewController.h"
+#import "MyKeychain.h"
+
+#import <CKBridge/SOSCloudKeychainClient.h>
+#import <SecureObjectSync/SOSCloudCircle.h>
+#import <SecureObjectSync/SOSCloudCircleInternal.h>
+#import <notify.h>
+#import <dispatch/dispatch.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+#import <CoreFoundation/CFUserNotification.h>
+
+#import <QuartzCore/QuartzCore.h>
+#import <Regressions/SOSTestDataSource.h>
+#import <securityd/SOSCloudCircleServer.h>
+#import <CKBridge/SOSCloudKeychainConstants.h>
+#import "PeerListCell.h"
+#import <utilities/SecCFRelease.h>
+
+__unused static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
+
+@interface SyncViewController ()
+@end
+
+@implementation SyncViewController
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+       // Do any additional setup after loading the view, typically from a nib.
+    [self setStatus:@"Idle…"];
+    [self updateSyncingEnabledSwitch];
+
+    notify_register_dispatch(kSOSCCCircleChangedNotification, &notificationToken,
+        dispatch_get_main_queue(),
+        ^(int tokenx __unused) {
+            notificationCount++;
+            [self setStatus:@"Got circle changed notification."];
+            [self flashChangeLight];
+            [self updateSyncingEnabledSwitch];
+            [self updateMemberCounts];
+            [_peerList reloadData];
+            [_applicantList reloadData];
+        });
+    [_acceptButton setEnabled:NO];
+
+    [self updateStatusCircleColor];
+
+//    _stateChangedC.color = [UIColor redColor];
+//    [_stateChangedC setNeedsDisplay];
+}
+
+- (void)didReceiveMemoryWarning
+{
+    [super didReceiveMemoryWarning];
+    // Dispose of any resources that can be recreated.
+}
+
+- (void)updateSyncingEnabledSwitch
+{
+    // Set the visual state of switch based on membership in circle
+    CFErrorRef error = NULL;
+    SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
+    BOOL switchIsOn = (ccstatus == kSOSCCInCircle || ccstatus == kSOSCCRequestPending);
+    [_syncingEnabled setOn:switchIsOn animated:NO];
+
+    CFStringRef circleStatusStr = SOSCCGetStatusDescription(ccstatus);
+    [_circleStatus setText:CFBridgingRelease(circleStatusStr)];
+    [_updateCount setText:[NSString stringWithFormat:@"%d", notificationCount]];
+    
+    // TODO: Maybe update spinny for pending?!?
+
+    NSLog(@"ccstatus: %@ (%d), error: %@", SOSCCGetStatusDescription(ccstatus), ccstatus, error);
+}
+
+- (void)updateStatusCircleColor
+{
+    switch (SOSCCThisDeviceIsInCircle(NULL))
+    {
+        case kSOSCCInCircle:
+            _stateChangedC.color = [UIColor greenColor];
+            break;
+        case kSOSCCRequestPending:
+            _stateChangedC.color = [UIColor yellowColor];
+            break;
+        default:
+            _stateChangedC.color = [UIColor redColor];
+            break;
+    }
+    [_stateChangedC setNeedsDisplay];
+}
+
+- (void)updateMemberCounts
+{
+    CFArrayRef foundApplicants = SOSCCCopyApplicantPeerInfo(NULL);
+    CFIndex applicantCount = foundApplicants ? CFArrayGetCount(foundApplicants) : -1;
+    [_applicantCount setText:[NSString stringWithFormat:@"%ld", (long)applicantCount]];
+
+    CFArrayRef foundPeers = SOSCCCopyPeerPeerInfo(NULL);
+    CFIndex peerCount = foundPeers ? CFArrayGetCount(foundPeers) : -1;
+    [_peerCount setText:[NSString stringWithFormat:@"%ld", (long)peerCount]];
+
+    [_acceptButton setEnabled:(applicantCount > 0)? YES: NO];
+    
+    [self updateStatusCircleColor];
+
+    CFReleaseSafe(foundApplicants);
+    CFReleaseSafe(foundPeers);
+}
+
++ (void)requestToJoinCircle
+{
+    // Set the visual state of switch based on membership in circle
+    bool bx = true;
+    CFErrorRef error = NULL;
+    SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
+
+    switch (ccstatus) {
+        case kSOSCCCircleAbsent:
+            bx = SOSCCResetToOffering(&error);
+            break;
+        case kSOSCCNotInCircle:
+            bx = SOSCCRequestToJoinCircle(&error);
+            break;
+        default:
+            NSLog(@"Request to join circle with bad status:  %@ (%d)", SOSCCGetStatusDescription(ccstatus), ccstatus);
+            break;
+    }
+    if (!bx)
+        NSLog(@"requestToJoinCircle Error: %@", error);
+}
+
+- (IBAction)acceptAllApplicants:(id)sender
+{
+    CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
+    if (applicants) {
+        SOSCCAcceptApplicants(applicants, NULL);
+        CFRelease(applicants);
+    }
+}
+
+- (IBAction)handleEnableSyncing:(id)sender
+{
+    dispatch_queue_t workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+    if ([sender isOn])  // i.e. we are trying to turn on syncing
+    {
+        dispatch_async(workq, ^ {
+            NSLog(@"Keychain syncing is being turned ON");
+            [[self class] requestToJoinCircle];
+        });
+    }
+    else
+    {
+        dispatch_async(workq, ^ {
+            NSLog(@"Keychain syncing is being turned OFF");
+            CFErrorRef error = NULL;
+            bool bx = SOSCCRemoveThisDeviceFromCircle(&error);
+            if (!bx)
+                NSLog(@"SOSCCRemoveThisDeviceFromCircle: %@", error);
+        });
+    }
+}
+
+- (void)flashChangeLight
+{
+    CABasicAnimation *theAnimation = NULL;
+
+    theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
+    theAnimation.duration=0.75;
+    theAnimation.repeatCount=5;    //HUGE_VALF;
+    theAnimation.autoreverses=YES;
+    theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
+    theAnimation.toValue=[NSNumber numberWithFloat:0.0];
+    [_stateChangedC.layer addAnimation:theAnimation forKey:@"animateOpacity"];
+}
+
+- (void)setStatus:(NSString *)message
+{
+    NSLog(@"%@", message);
+    _statusMessage.text = message;
+}
+
+//
+// MARK: Table view handling
+//
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    PeerListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PeerTableCell" forIndexPath:(NSIndexPath *)indexPath];
+    if (cell == nil)
+    {
+        NSLog(@"cellForRowAtIndexPath : cell was nil");
+        cell = [[PeerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"PeerTableCell"];
+    }
+
+    NSArray *list = NULL;
+    NSArray *hilighted = NULL;
+    if (tableView == _peerList) {
+        list = (__bridge_transfer NSArray*)SOSCCCopyPeerPeerInfo(NULL);
+        hilighted = (__bridge_transfer NSArray*)SOSCCCopyConcurringPeerPeerInfo(NULL);
+    } else {
+        list = (__bridge_transfer NSArray*)SOSCCCopyApplicantPeerInfo(NULL);
+    }
+
+    if (list) {
+        cell.peerCircle.text = @"A";
+        SOSPeerInfoRef pi = (__bridge SOSPeerInfoRef) list[[indexPath row]];
+        if (pi) {
+            cell.peerName.text = (__bridge NSString*) SOSPeerInfoGetPeerName(pi);
+            if ([hilighted containsObject: (__bridge id)pi])
+                cell.peerName.textColor = [UIColor greenColor];
+        }
+    } else {
+        cell.peerName.text = @"Null List";
+    }
+    
+    return cell;
+}
+
+- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
+{
+    NSArray* list = nil;
+    
+    if (tableView == _peerList) {
+        list = (__bridge_transfer NSArray*) SOSCCCopyPeerPeerInfo(NULL);
+    } else {
+        list = (__bridge_transfer NSArray*) SOSCCCopyApplicantPeerInfo(NULL);
+    }
+    
+    return [list count];
+}
+
+@end
+