2 // SyncViewController.m
5 // Created by john on 10/22/12.
9 #import "SyncViewController.h"
10 #import "MyKeychain.h"
12 #import <CKBridge/SOSCloudKeychainClient.h>
13 #import <SecureObjectSync/SOSCloudCircle.h>
14 #import <SecureObjectSync/SOSCloudCircleInternal.h>
16 #import <dispatch/dispatch.h>
18 #import <CoreFoundation/CoreFoundation.h>
19 #import <CoreFoundation/CFUserNotification.h>
21 #import <QuartzCore/QuartzCore.h>
22 #import <Regressions/SOSTestDataSource.h>
23 #import <securityd/SOSCloudCircleServer.h>
24 #import <CKBridge/SOSCloudKeychainConstants.h>
25 #import "PeerListCell.h"
26 #import <utilities/SecCFRelease.h>
28 __unused static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
30 @interface SyncViewController ()
33 @implementation SyncViewController
38 // Do any additional setup after loading the view, typically from a nib.
39 [self setStatus:@"Idle…"];
40 [self updateSyncingEnabledSwitch];
42 notify_register_dispatch(kSOSCCCircleChangedNotification, ¬ificationToken,
43 dispatch_get_main_queue(),
44 ^(int tokenx __unused) {
46 [self setStatus:@"Got circle changed notification."];
47 [self flashChangeLight];
48 [self updateSyncingEnabledSwitch];
49 [self updateMemberCounts];
50 [_peerList reloadData];
51 [_applicantList reloadData];
53 [_acceptButton setEnabled:NO];
55 [self updateStatusCircleColor];
57 // _stateChangedC.color = [UIColor redColor];
58 // [_stateChangedC setNeedsDisplay];
61 - (void)didReceiveMemoryWarning
63 [super didReceiveMemoryWarning];
64 // Dispose of any resources that can be recreated.
67 - (void)updateSyncingEnabledSwitch
69 // Set the visual state of switch based on membership in circle
70 CFErrorRef error = NULL;
71 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
72 BOOL switchIsOn = (ccstatus == kSOSCCInCircle || ccstatus == kSOSCCRequestPending);
73 [_syncingEnabled setOn:switchIsOn animated:NO];
75 CFStringRef circleStatusStr = SOSCCGetStatusDescription(ccstatus);
76 [_circleStatus setText:CFBridgingRelease(circleStatusStr)];
77 [_updateCount setText:[NSString stringWithFormat:@"%d", notificationCount]];
79 // TODO: Maybe update spinny for pending?!?
81 NSLog(@"ccstatus: %@ (%d), error: %@", SOSCCGetStatusDescription(ccstatus), ccstatus, error);
84 - (void)updateStatusCircleColor
86 switch (SOSCCThisDeviceIsInCircle(NULL))
89 _stateChangedC.color = [UIColor greenColor];
91 case kSOSCCRequestPending:
92 _stateChangedC.color = [UIColor yellowColor];
95 _stateChangedC.color = [UIColor redColor];
98 [_stateChangedC setNeedsDisplay];
101 - (void)updateMemberCounts
103 CFArrayRef foundApplicants = SOSCCCopyApplicantPeerInfo(NULL);
104 CFIndex applicantCount = foundApplicants ? CFArrayGetCount(foundApplicants) : -1;
105 [_applicantCount setText:[NSString stringWithFormat:@"%ld", (long)applicantCount]];
107 CFArrayRef foundPeers = SOSCCCopyPeerPeerInfo(NULL);
108 CFIndex peerCount = foundPeers ? CFArrayGetCount(foundPeers) : -1;
109 [_peerCount setText:[NSString stringWithFormat:@"%ld", (long)peerCount]];
111 [_acceptButton setEnabled:(applicantCount > 0)? YES: NO];
113 [self updateStatusCircleColor];
115 CFReleaseSafe(foundApplicants);
116 CFReleaseSafe(foundPeers);
119 + (void)requestToJoinCircle
121 // Set the visual state of switch based on membership in circle
123 CFErrorRef error = NULL;
124 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
127 case kSOSCCCircleAbsent:
128 bx = SOSCCResetToOffering(&error);
130 case kSOSCCNotInCircle:
131 bx = SOSCCRequestToJoinCircle(&error);
134 NSLog(@"Request to join circle with bad status: %@ (%d)", SOSCCGetStatusDescription(ccstatus), ccstatus);
138 NSLog(@"requestToJoinCircle Error: %@", error);
141 - (IBAction)acceptAllApplicants:(id)sender
143 CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
145 SOSCCAcceptApplicants(applicants, NULL);
146 CFRelease(applicants);
150 - (IBAction)handleEnableSyncing:(id)sender
152 dispatch_queue_t workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
153 if ([sender isOn]) // i.e. we are trying to turn on syncing
155 dispatch_async(workq, ^ {
156 NSLog(@"Keychain syncing is being turned ON");
157 [[self class] requestToJoinCircle];
162 dispatch_async(workq, ^ {
163 NSLog(@"Keychain syncing is being turned OFF");
164 CFErrorRef error = NULL;
165 bool bx = SOSCCRemoveThisDeviceFromCircle(&error);
167 NSLog(@"SOSCCRemoveThisDeviceFromCircle: %@", error);
172 - (void)flashChangeLight
174 CABasicAnimation *theAnimation = NULL;
176 theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
177 theAnimation.duration=0.75;
178 theAnimation.repeatCount=5; //HUGE_VALF;
179 theAnimation.autoreverses=YES;
180 theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
181 theAnimation.toValue=[NSNumber numberWithFloat:0.0];
182 [_stateChangedC.layer addAnimation:theAnimation forKey:@"animateOpacity"];
185 - (void)setStatus:(NSString *)message
187 NSLog(@"%@", message);
188 _statusMessage.text = message;
192 // MARK: Table view handling
194 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
196 PeerListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PeerTableCell" forIndexPath:(NSIndexPath *)indexPath];
199 NSLog(@"cellForRowAtIndexPath : cell was nil");
200 cell = [[PeerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"PeerTableCell"];
203 NSArray *list = NULL;
204 NSArray *hilighted = NULL;
205 if (tableView == _peerList) {
206 list = (__bridge_transfer NSArray*)SOSCCCopyPeerPeerInfo(NULL);
207 hilighted = (__bridge_transfer NSArray*)SOSCCCopyConcurringPeerPeerInfo(NULL);
209 list = (__bridge_transfer NSArray*)SOSCCCopyApplicantPeerInfo(NULL);
213 cell.peerCircle.text = @"A";
214 SOSPeerInfoRef pi = (__bridge SOSPeerInfoRef) list[[indexPath row]];
216 cell.peerName.text = (__bridge NSString*) SOSPeerInfoGetPeerName(pi);
217 if ([hilighted containsObject: (__bridge id)pi])
218 cell.peerName.textColor = [UIColor greenColor];
221 cell.peerName.text = @"Null List";
227 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
231 if (tableView == _peerList) {
232 list = (__bridge_transfer NSArray*) SOSCCCopyPeerPeerInfo(NULL);
234 list = (__bridge_transfer NSArray*) SOSCCCopyApplicantPeerInfo(NULL);