]> git.saurik.com Git - apple/security.git/blob - Keychain/SyncViewController.m
Security-57031.1.35.tar.gz
[apple/security.git] / Keychain / SyncViewController.m
1 //
2 // SyncViewController.m
3 // Keychain
4 //
5 // Created by john on 10/22/12.
6 //
7 //
8
9 #import "SyncViewController.h"
10 #import "MyKeychain.h"
11
12 #import <CKBridge/SOSCloudKeychainClient.h>
13 #import <SecureObjectSync/SOSCloudCircle.h>
14 #import <SecureObjectSync/SOSCloudCircleInternal.h>
15 #import <notify.h>
16 #import <dispatch/dispatch.h>
17
18 #import <CoreFoundation/CoreFoundation.h>
19 #import <CoreFoundation/CFUserNotification.h>
20
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>
27
28 __unused static const uint64_t maxTimeToWaitInSeconds = 30ull * NSEC_PER_SEC;
29
30 @interface SyncViewController ()
31 @end
32
33 @implementation SyncViewController
34
35 - (void)viewDidLoad
36 {
37 [super viewDidLoad];
38 // Do any additional setup after loading the view, typically from a nib.
39 [self setStatus:@"Idle…"];
40 [self updateSyncingEnabledSwitch];
41
42 notify_register_dispatch(kSOSCCCircleChangedNotification, &notificationToken,
43 dispatch_get_main_queue(),
44 ^(int tokenx __unused) {
45 notificationCount++;
46 [self setStatus:@"Got circle changed notification."];
47 [self flashChangeLight];
48 [self updateSyncingEnabledSwitch];
49 [self updateMemberCounts];
50 [_peerList reloadData];
51 [_applicantList reloadData];
52 });
53 [_acceptButton setEnabled:NO];
54
55 [self updateStatusCircleColor];
56
57 // _stateChangedC.color = [UIColor redColor];
58 // [_stateChangedC setNeedsDisplay];
59 }
60
61 - (void)didReceiveMemoryWarning
62 {
63 [super didReceiveMemoryWarning];
64 // Dispose of any resources that can be recreated.
65 }
66
67 - (void)updateSyncingEnabledSwitch
68 {
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];
74
75 CFStringRef circleStatusStr = SOSCCGetStatusDescription(ccstatus);
76 [_circleStatus setText:CFBridgingRelease(circleStatusStr)];
77 [_updateCount setText:[NSString stringWithFormat:@"%d", notificationCount]];
78
79 // TODO: Maybe update spinny for pending?!?
80
81 NSLog(@"ccstatus: %@ (%d), error: %@", SOSCCGetStatusDescription(ccstatus), ccstatus, error);
82 }
83
84 - (void)updateStatusCircleColor
85 {
86 switch (SOSCCThisDeviceIsInCircle(NULL))
87 {
88 case kSOSCCInCircle:
89 _stateChangedC.color = [UIColor greenColor];
90 break;
91 case kSOSCCRequestPending:
92 _stateChangedC.color = [UIColor yellowColor];
93 break;
94 default:
95 _stateChangedC.color = [UIColor redColor];
96 break;
97 }
98 [_stateChangedC setNeedsDisplay];
99 }
100
101 - (void)updateMemberCounts
102 {
103 CFArrayRef foundApplicants = SOSCCCopyApplicantPeerInfo(NULL);
104 CFIndex applicantCount = foundApplicants ? CFArrayGetCount(foundApplicants) : -1;
105 [_applicantCount setText:[NSString stringWithFormat:@"%ld", (long)applicantCount]];
106
107 CFArrayRef foundPeers = SOSCCCopyPeerPeerInfo(NULL);
108 CFIndex peerCount = foundPeers ? CFArrayGetCount(foundPeers) : -1;
109 [_peerCount setText:[NSString stringWithFormat:@"%ld", (long)peerCount]];
110
111 [_acceptButton setEnabled:(applicantCount > 0)? YES: NO];
112
113 [self updateStatusCircleColor];
114
115 CFReleaseSafe(foundApplicants);
116 CFReleaseSafe(foundPeers);
117 }
118
119 + (void)requestToJoinCircle
120 {
121 // Set the visual state of switch based on membership in circle
122 bool bx = true;
123 CFErrorRef error = NULL;
124 SOSCCStatus ccstatus = SOSCCThisDeviceIsInCircle(&error);
125
126 switch (ccstatus) {
127 case kSOSCCCircleAbsent:
128 bx = SOSCCResetToOffering(&error);
129 break;
130 case kSOSCCNotInCircle:
131 bx = SOSCCRequestToJoinCircle(&error);
132 break;
133 default:
134 NSLog(@"Request to join circle with bad status: %@ (%d)", SOSCCGetStatusDescription(ccstatus), ccstatus);
135 break;
136 }
137 if (!bx)
138 NSLog(@"requestToJoinCircle Error: %@", error);
139 }
140
141 - (IBAction)acceptAllApplicants:(id)sender
142 {
143 CFArrayRef applicants = SOSCCCopyApplicantPeerInfo(NULL);
144 if (applicants) {
145 SOSCCAcceptApplicants(applicants, NULL);
146 CFRelease(applicants);
147 }
148 }
149
150 - (IBAction)handleEnableSyncing:(id)sender
151 {
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
154 {
155 dispatch_async(workq, ^ {
156 NSLog(@"Keychain syncing is being turned ON");
157 [[self class] requestToJoinCircle];
158 });
159 }
160 else
161 {
162 dispatch_async(workq, ^ {
163 NSLog(@"Keychain syncing is being turned OFF");
164 CFErrorRef error = NULL;
165 bool bx = SOSCCRemoveThisDeviceFromCircle(&error);
166 if (!bx)
167 NSLog(@"SOSCCRemoveThisDeviceFromCircle: %@", error);
168 });
169 }
170 }
171
172 - (void)flashChangeLight
173 {
174 CABasicAnimation *theAnimation = NULL;
175
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"];
183 }
184
185 - (void)setStatus:(NSString *)message
186 {
187 NSLog(@"%@", message);
188 _statusMessage.text = message;
189 }
190
191 //
192 // MARK: Table view handling
193 //
194 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
195 {
196 PeerListCell *cell = [tableView dequeueReusableCellWithIdentifier:@"PeerTableCell" forIndexPath:(NSIndexPath *)indexPath];
197 if (cell == nil)
198 {
199 NSLog(@"cellForRowAtIndexPath : cell was nil");
200 cell = [[PeerListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"PeerTableCell"];
201 }
202
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);
208 } else {
209 list = (__bridge_transfer NSArray*)SOSCCCopyApplicantPeerInfo(NULL);
210 }
211
212 if (list) {
213 cell.peerCircle.text = @"A";
214 SOSPeerInfoRef pi = (__bridge SOSPeerInfoRef) list[[indexPath row]];
215 if (pi) {
216 cell.peerName.text = (__bridge NSString*) SOSPeerInfoGetPeerName(pi);
217 if ([hilighted containsObject: (__bridge id)pi])
218 cell.peerName.textColor = [UIColor greenColor];
219 }
220 } else {
221 cell.peerName.text = @"Null List";
222 }
223
224 return cell;
225 }
226
227 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
228 {
229 NSArray* list = nil;
230
231 if (tableView == _peerList) {
232 list = (__bridge_transfer NSArray*) SOSCCCopyPeerPeerInfo(NULL);
233 } else {
234 list = (__bridge_transfer NSArray*) SOSCCCopyApplicantPeerInfo(NULL);
235 }
236
237 return [list count];
238 }
239
240 @end
241