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 <Security/SecureObjectSync/SOSCloudCircle.h>
14 #import <Security/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);
133 CFMutableSetRef viewsToEnable = CFSetCreateMutable(NULL, 0, NULL);
134 CFMutableSetRef viewsToDisable = CFSetCreateMutable(NULL, 0, NULL);
135 CFSetAddValue(viewsToEnable, (void*)kSOSViewWiFi);
136 CFSetAddValue(viewsToEnable, (void*)kSOSViewAutofillPasswords);
137 CFSetAddValue(viewsToEnable, (void*)kSOSViewSafariCreditCards);
138 CFSetAddValue(viewsToEnable, (void*)kSOSViewOtherSyncable);
140 bx = SOSCCViewSet(viewsToEnable, viewsToDisable);
141 CFRelease(viewsToEnable);
142 CFRelease(viewsToDisable);
146 NSLog(@"Request to join circle with bad status: %@ (%d)", SOSCCGetStatusDescription(ccstatus), ccstatus);
150 NSLog(@"requestToJoinCircle Error: %@", error);
153 - (IBAction)acceptAllApplicants:(id)sender
155 CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
157 SOSCCAcceptApplicants(applicants, NULL);
158 CFRelease(applicants);
162 - (IBAction)handleEnableSyncing:(id)sender
164 dispatch_queue_t workq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
165 if ([sender isOn]) // i.e. we are trying to turn on syncing
167 dispatch_async(workq, ^ {
168 NSLog(@"Keychain syncing is being turned ON");
169 [[self class] requestToJoinCircle];
174 dispatch_async(workq, ^ {
175 NSLog(@"Keychain syncing is being turned OFF");
176 CFErrorRef error = NULL;
177 bool bx = SOSCCRemoveThisDeviceFromCircle(&error);
179 NSLog(@"SOSCCRemoveThisDeviceFromCircle: %@", error);
184 - (void)flashChangeLight
186 CABasicAnimation *theAnimation = NULL;
188 theAnimation=[CABasicAnimation animationWithKeyPath:@"opacity"];
189 theAnimation.duration=0.75;
190 theAnimation.repeatCount=5; //HUGE_VALF;
191 theAnimation.autoreverses=YES;
192 theAnimation.fromValue=[NSNumber numberWithFloat:1.0];
193 theAnimation.toValue=[NSNumber numberWithFloat:0.0];
194 [_stateChangedC.layer addAnimation:theAnimation forKey:@"animateOpacity"];
197 - (void)setStatus:(NSString *)message
199 NSLog(@"%@", message);
200 _statusMessage.text = message;
204 // MARK: Table view handling
206 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
208 PeerListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PeerTableCell" forIndexPath:(NSIndexPath *)indexPath];
211 NSLog(@"cellForRowAtIndexPath : cell was nil");
212 cell = [[PeerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"PeerTableCell"];
215 NSArray *list = NULL;
216 NSArray *hilighted = NULL;
217 if (tableView == _peerList) {
218 list = (__bridge_transfer NSArray*)SOSCCCopyPeerPeerInfo(NULL);
219 hilighted = (__bridge_transfer NSArray*)SOSCCCopyConcurringPeerPeerInfo(NULL);
221 list = (__bridge_transfer NSArray*)SOSCCCopyApplicantPeerInfo(NULL);
225 cell.peerCircle.text = @"A";
226 SOSPeerInfoRef pi = (__bridge SOSPeerInfoRef) list[[indexPath row]];
228 cell.peerName.text = (__bridge NSString*) SOSPeerInfoGetPeerName(pi);
229 if ([hilighted containsObject: (__bridge id)pi])
230 cell.peerName.textColor = [UIColor greenColor];
233 cell.peerName.text = @"Null List";
239 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
243 if (tableView == _peerList) {
244 list = (__bridge_transfer NSArray*) SOSCCCopyPeerPeerInfo(NULL);
246 list = (__bridge_transfer NSArray*) SOSCCCopyApplicantPeerInfo(NULL);