]> git.saurik.com Git - apple/security.git/blob - keychain/ckks/CKKSCKAccountStateTracker.h
Security-58286.270.3.0.1.tar.gz
[apple/security.git] / keychain / ckks / CKKSCKAccountStateTracker.h
1 /*
2 * Copyright (c) 2017 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #import <Foundation/Foundation.h>
25
26 #if OCTAGON
27 #import <CloudKit/CKContainer_Private.h>
28 #import <CloudKit/CloudKit.h>
29 #include <Security/SecureObjectSync/SOSCloudCircle.h>
30 #import "keychain/ckks/CKKSCondition.h"
31 #import "keychain/ckks/CloudKitDependencies.h"
32
33 NS_ASSUME_NONNULL_BEGIN
34
35 /*
36 * Implements a 'debouncer' to store the current CK account and circle state, and receive updates to it.
37 *
38 * Will only be considered "logged in" if we both have a CK account and are 'in circle'.
39 *
40 * It will notify listeners on account state changes, so multiple repeated account state notifications with the same state are filtered by this class.
41 * Listeners can also get the 'current' state, no matter what it is. They will also then be atomically added to the notification queue, and so will
42 * always receive the next update, preventing them from getting a stale state and missing an immediate update.
43 */
44
45 typedef NS_ENUM(NSInteger, CKKSAccountStatus) {
46 /* Set at initialization. This means we haven't figured out what the account state is. */
47 CKKSAccountStatusUnknown = 0,
48 /* We have an iCloud account and are in-circle */
49 CKKSAccountStatusAvailable = 1,
50 /* No iCloud account is logged in on this device, or we're out of circle */
51 CKKSAccountStatusNoAccount = 3,
52 };
53
54 @interface SOSAccountStatus : NSObject
55 @property SOSCCStatus status;
56 @property (nullable) NSError* error;
57 - (instancetype)init:(SOSCCStatus)status error:error;
58 @end
59
60 /* CliqueStatus */
61
62 typedef NS_ENUM(NSInteger, CliqueStatus) {
63 CliqueStatusIn = 0, /*There is a clique and I am in it*/
64 CliqueStatusNotIn = 1, /*There is a clique and I am not in it - you should get a voucher to join or tell another peer to trust us*/
65 CliqueStatusPending = 2, /*For compatibility, keeping the pending state */
66 CliqueStatusAbsent = 3, /*There is no clique - you can establish one */
67 CliqueStatusNoCloudKitAccount = 4, /* no cloudkit account present */
68 CliqueStatusError = -1 /*unable to determine circle status, inspect CFError to find out why */
69 };
70 NSString* OTCliqueStatusToString(CliqueStatus status);
71 CliqueStatus OTCliqueStatusFromString(NSString* str);
72
73 @interface OTCliqueStatusWrapper : NSObject
74 @property (readonly) CliqueStatus status;
75 - (instancetype)initWithStatus:(CliqueStatus)status;
76 @end
77
78 /* End of clique status */
79
80 @protocol CKKSAccountStateListener <NSObject>
81 - (void)ckAccountStatusChange:(CKKSAccountStatus)oldStatus to:(CKKSAccountStatus)currentStatus;
82 @end
83
84 @interface CKKSCKAccountStateTracker : NSObject
85 @property CKKSCondition* finishedInitialDispatches;
86
87 // If you use these, please be aware they could change out from under you at any time
88 @property (nullable) CKAccountInfo* currentCKAccountInfo;
89 @property (nullable) SOSAccountStatus* currentCircleStatus;
90
91 @property (readonly,atomic) CKKSAccountStatus currentComputedAccountStatus;
92 @property (nullable,readonly,atomic) NSError* currentAccountError;
93 @property CKKSCondition* currentComputedAccountStatusValid;
94
95 // Fetched and memoized from CloudKit; we can't afford deadlocks with their callbacks
96 @property (nullable, copy) NSString* ckdeviceID;
97 @property (nullable) NSError* ckdeviceIDError;
98 @property CKKSCondition* ckdeviceIDInitialized;
99
100 // Fetched and memoized from the Account when we're in-circle; our threading model is strange
101 @property (nullable) NSString* accountCirclePeerID;
102 @property (nullable) NSError* accountCirclePeerIDError;
103 @property CKKSCondition* accountCirclePeerIDInitialized;
104
105 - (instancetype)init:(CKContainer*)container nsnotificationCenterClass:(Class<CKKSNSNotificationCenter>)nsnotificationCenterClass;
106
107 - (dispatch_semaphore_t)notifyOnAccountStatusChange:(id<CKKSAccountStateListener>)listener;
108
109 // Methods useful for testing:
110
111 // Call this to simulate a notification (and pause the calling thread until all notifications are delivered)
112 - (void)notifyCKAccountStatusChangeAndWaitForSignal;
113 - (void)notifyCircleStatusChangeAndWaitForSignal;
114
115 - (dispatch_group_t _Nullable)checkForAllDeliveries;
116
117 + (SOSAccountStatus*)getCircleStatus;
118 + (void)fetchCirclePeerID:(void (^)(NSString* _Nullable peerID, NSError* _Nullable error))callback;
119 + (NSString*)stringFromAccountStatus:(CKKSAccountStatus)status;
120
121 @end
122
123 NS_ASSUME_NONNULL_END
124 #endif // OCTAGON