]>
Commit | Line | Data |
---|---|---|
866f8763 A |
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 | |
866f8763 | 27 | #import <CloudKit/CKContainer_Private.h> |
3f0f0d49 | 28 | #import <CloudKit/CloudKit.h> |
866f8763 | 29 | #include <Security/SecureObjectSync/SOSCloudCircle.h> |
3f0f0d49 A |
30 | #import "keychain/ckks/CKKSCondition.h" |
31 | #import "keychain/ckks/CloudKitDependencies.h" | |
b54c578e | 32 | #import "keychain/ot/OTClique.h" |
3f0f0d49 A |
33 | |
34 | NS_ASSUME_NONNULL_BEGIN | |
866f8763 A |
35 | |
36 | /* | |
37 | * Implements a 'debouncer' to store the current CK account and circle state, and receive updates to it. | |
38 | * | |
b54c578e A |
39 | * You can register for CK account changes, SOS account changes, or to be informed only when both are in |
40 | * a valid state. | |
866f8763 A |
41 | * |
42 | * It will notify listeners on account state changes, so multiple repeated account state notifications with the same state are filtered by this class. | |
43 | * 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 | |
44 | * always receive the next update, preventing them from getting a stale state and missing an immediate update. | |
45 | */ | |
46 | ||
b54c578e | 47 | // This enum represents the combined states of a CK account and the SOS account |
866f8763 A |
48 | typedef NS_ENUM(NSInteger, CKKSAccountStatus) { |
49 | /* Set at initialization. This means we haven't figured out what the account state is. */ | |
3f0f0d49 | 50 | CKKSAccountStatusUnknown = 0, |
866f8763 | 51 | /* We have an iCloud account and are in-circle */ |
3f0f0d49 | 52 | CKKSAccountStatusAvailable = 1, |
866f8763 | 53 | /* No iCloud account is logged in on this device, or we're out of circle */ |
3f0f0d49 | 54 | CKKSAccountStatusNoAccount = 3, |
866f8763 | 55 | }; |
b54c578e | 56 | NSString* CKKSAccountStatusToString(CKKSAccountStatus status); |
866f8763 | 57 | |
79b9da22 A |
58 | @interface SOSAccountStatus : NSObject |
59 | @property SOSCCStatus status; | |
60 | @property (nullable) NSError* error; | |
61 | - (instancetype)init:(SOSCCStatus)status error:error; | |
62 | @end | |
63 | ||
84aacf34 A |
64 | @interface OTCliqueStatusWrapper : NSObject |
65 | @property (readonly) CliqueStatus status; | |
66 | - (instancetype)initWithStatus:(CliqueStatus)status; | |
67 | @end | |
68 | ||
b54c578e A |
69 | @protocol CKKSOctagonStatusMemoizer |
70 | - (void)triggerOctagonStatusFetch; | |
71 | ||
72 | @property (readonly, nullable) OTCliqueStatusWrapper* octagonStatus; | |
73 | @property (readonly, nullable) NSString* octagonPeerID; | |
74 | ||
75 | // A little bit of a abstraction violation, but it'll do. | |
76 | - (void)setHSA2iCloudAccountStatus:(CKKSAccountStatus)status; | |
77 | @end | |
78 | ||
79 | #pragma mark -- Listener Protocols | |
84aacf34 | 80 | |
b54c578e A |
81 | @protocol CKKSCloudKitAccountStateListener <NSObject> |
82 | - (void)cloudkitAccountStateChange:(CKAccountInfo* _Nullable)oldAccountInfo to:(CKAccountInfo*)currentAccountInfo; | |
83 | @end | |
84 | @protocol CKKSCloudKitAccountStateTrackingProvider <NSObject> | |
85 | - (dispatch_semaphore_t)registerForNotificationsOfCloudKitAccountStatusChange:(id<CKKSCloudKitAccountStateListener>)listener; | |
866f8763 A |
86 | @end |
87 | ||
b54c578e A |
88 | #pragma mark -- Tracker |
89 | ||
90 | @interface CKKSAccountStateTracker : NSObject <CKKSCloudKitAccountStateTrackingProvider, | |
91 | CKKSOctagonStatusMemoizer> | |
3f0f0d49 | 92 | @property CKKSCondition* finishedInitialDispatches; |
866f8763 A |
93 | |
94 | // If you use these, please be aware they could change out from under you at any time | |
3f0f0d49 | 95 | @property (nullable) CKAccountInfo* currentCKAccountInfo; |
b54c578e | 96 | @property CKKSCondition* ckAccountInfoInitialized; |
866f8763 | 97 | |
ecaf5866 | 98 | |
866f8763 | 99 | // Fetched and memoized from CloudKit; we can't afford deadlocks with their callbacks |
3f0f0d49 A |
100 | @property (nullable, copy) NSString* ckdeviceID; |
101 | @property (nullable) NSError* ckdeviceIDError; | |
102 | @property CKKSCondition* ckdeviceIDInitialized; | |
866f8763 | 103 | |
b54c578e A |
104 | // Fetched and memoized from SOS. Not otherwise used. |
105 | @property (nullable) SOSAccountStatus* currentCircleStatus; | |
3f0f0d49 A |
106 | @property (nullable) NSString* accountCirclePeerID; |
107 | @property (nullable) NSError* accountCirclePeerIDError; | |
866f8763 A |
108 | @property CKKSCondition* accountCirclePeerIDInitialized; |
109 | ||
b54c578e A |
110 | // Filled and memoized for quick reference. Don't use for anything vital. |
111 | // This will only fetch the status for the default context. | |
112 | @property (readonly, nullable) OTCliqueStatusWrapper* octagonStatus; | |
113 | @property (readonly, nullable) NSString* octagonPeerID; | |
114 | @property (readonly) CKKSCondition* octagonInformationInitialized; | |
115 | ||
116 | // Filled by Octagon, as it's fairly hard to compute. | |
117 | @property (readonly) CKKSAccountStatus hsa2iCloudAccountStatus; | |
118 | @property (readonly) CKKSCondition* hsa2iCloudAccountInitialized; | |
119 | ||
3f0f0d49 | 120 | - (instancetype)init:(CKContainer*)container nsnotificationCenterClass:(Class<CKKSNSNotificationCenter>)nsnotificationCenterClass; |
866f8763 | 121 | |
b54c578e A |
122 | - (dispatch_semaphore_t)registerForNotificationsOfCloudKitAccountStatusChange:(id<CKKSCloudKitAccountStateListener>)listener; |
123 | ||
124 | // Call this to refetch the Octagon status | |
125 | - (void)triggerOctagonStatusFetch; | |
866f8763 A |
126 | |
127 | // Methods useful for testing: | |
b54c578e | 128 | - (void)performInitialDispatches; |
866f8763 A |
129 | |
130 | // Call this to simulate a notification (and pause the calling thread until all notifications are delivered) | |
3f0f0d49 A |
131 | - (void)notifyCKAccountStatusChangeAndWaitForSignal; |
132 | - (void)notifyCircleStatusChangeAndWaitForSignal; | |
133 | ||
134 | - (dispatch_group_t _Nullable)checkForAllDeliveries; | |
866f8763 | 135 | |
b54c578e A |
136 | - (void)setHSA2iCloudAccountStatus:(CKKSAccountStatus)status; |
137 | ||
79b9da22 | 138 | + (SOSAccountStatus*)getCircleStatus; |
3f0f0d49 A |
139 | + (void)fetchCirclePeerID:(void (^)(NSString* _Nullable peerID, NSError* _Nullable error))callback; |
140 | + (NSString*)stringFromAccountStatus:(CKKSAccountStatus)status; | |
866f8763 A |
141 | |
142 | @end | |
143 | ||
3f0f0d49 A |
144 | NS_ASSUME_NONNULL_END |
145 | #endif // OCTAGON |