]>
Commit | Line | Data |
---|---|---|
43bfd57e | 1 | /* |
afb19109 | 2 | * Copyright (c) 2017-2019 Apple Inc. All rights reserved. |
43bfd57e A |
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 | /* | |
25 | * InterfaceNamerControlPrefs.c | |
26 | * - definitions for accessing InterfaceNamer control preferences | |
27 | */ | |
28 | ||
29 | /* | |
30 | * Modification History | |
31 | * | |
32 | * January 12, 2017 Allan Nathanson (ajn@apple.com) | |
33 | * - created | |
34 | */ | |
35 | ||
36 | #include <TargetConditionals.h> | |
37 | #include <SystemConfiguration/SystemConfiguration.h> | |
38 | #include <SystemConfiguration/SCPrivate.h> | |
39 | #include <SystemConfiguration/scprefs_observer.h> | |
40 | #include "InterfaceNamerControlPrefs.h" | |
41 | ||
43bfd57e A |
42 | /* |
43 | * kInterfaceNamerControlPrefsID | |
44 | * - identifies the InterfaceNamer preferences file that contains 'AllowNewInterfaces' | |
45 | */ | |
46 | #define kInterfaceNamerControlPrefsIDStr "com.apple.InterfaceNamer.control.plist" | |
47 | #define kInterfaceNamerControlPrefsID CFSTR(kInterfaceNamerControlPrefsIDStr) | |
48 | ||
49 | /* | |
50 | * kAllowNewInterfaces | |
51 | * - indicates whether InterfaceNamer is allowed to create new interfaces | |
52 | * while the screen is locked or not | |
53 | */ | |
54 | #define kAllowNewInterfaces CFSTR("AllowNewInterfaces") | |
55 | ||
56 | static SCPreferencesRef S_prefs; | |
57 | static InterfaceNamerControlPrefsCallBack S_callback; | |
58 | ||
59 | static SCPreferencesRef | |
60 | InterfaceNamerControlPrefsGet(void) | |
61 | { | |
62 | if (S_prefs == NULL) { | |
63 | InterfaceNamerControlPrefsInit(NULL, NULL); | |
64 | } | |
65 | ||
66 | return (S_prefs); | |
67 | } | |
68 | ||
69 | static void | |
70 | prefs_changed(void * arg) | |
71 | { | |
72 | #pragma unused(arg) | |
43bfd57e A |
73 | /* get the current value */ |
74 | if (S_callback != NULL) { | |
75 | (*S_callback)(S_prefs); | |
76 | } | |
77 | ||
43bfd57e A |
78 | return; |
79 | } | |
80 | ||
81 | #if TARGET_OS_IPHONE | |
82 | /* | |
83 | * kInterfaceNamerControlManangedPrefsID | |
84 | * - identifies the location of the managed preferences file | |
85 | */ | |
86 | #define kManagedPrefsDirStr "/Library/Managed Preferences/mobile/" | |
87 | #define kInterfaceNamerControlManagedPrefsID CFSTR(kManagedPrefsDirStr \ | |
88 | kInterfaceNamerControlPrefsIDStr) | |
89 | static SCPreferencesRef S_managed_prefs; | |
90 | ||
91 | static SCPreferencesRef | |
92 | InterfaceNamerControlManagedPrefsGet(void) | |
93 | { | |
94 | if (S_managed_prefs == NULL) { | |
95 | CFMutableDictionaryRef options; | |
96 | ||
97 | options = CFDictionaryCreateMutable(NULL, | |
98 | 0, | |
99 | &kCFTypeDictionaryKeyCallBacks, | |
100 | &kCFTypeDictionaryValueCallBacks); | |
101 | CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue); | |
102 | S_managed_prefs = SCPreferencesCreateWithOptions(NULL, | |
103 | CFSTR("InterfaceNamerControlPrefs"), | |
104 | kInterfaceNamerControlManagedPrefsID, | |
105 | NULL, | |
106 | options); | |
107 | CFRelease(options); | |
108 | } | |
109 | return (S_managed_prefs); | |
110 | } | |
111 | ||
112 | static void | |
113 | enable_prefs_observer(CFRunLoopRef runloop) | |
114 | { | |
115 | CFRunLoopSourceContext context; | |
116 | dispatch_queue_t queue; | |
117 | CFRunLoopSourceRef source; | |
118 | ||
afb19109 | 119 | memset(&context, 0, sizeof(context)); |
43bfd57e A |
120 | context.perform = prefs_changed; |
121 | source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); | |
122 | CFRunLoopAddSource(runloop, source, kCFRunLoopCommonModes); | |
123 | queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); | |
124 | _scprefs_observer_watch(scprefs_observer_type_global, | |
125 | kInterfaceNamerControlPrefsIDStr, | |
126 | queue, | |
127 | ^{ | |
128 | if (source != NULL) { | |
129 | CFRunLoopSourceSignal(source); | |
130 | if (runloop != NULL) { | |
131 | CFRunLoopWakeUp(runloop); | |
132 | } | |
133 | }; | |
134 | }); | |
135 | return; | |
136 | } | |
137 | ||
138 | #else /* TARGET_OS_IPHONE */ | |
139 | ||
140 | static void | |
141 | enable_prefs_observer(CFRunLoopRef runloop) | |
142 | { | |
143 | #pragma unused(runloop) | |
144 | return; | |
145 | } | |
146 | ||
147 | #endif /* TARGET_OS_IPHONE */ | |
148 | ||
149 | static void | |
150 | InterfaceNamerControlPrefsChanged(SCPreferencesRef prefs, | |
151 | SCPreferencesNotification type, | |
152 | void *info) | |
153 | { | |
154 | #pragma unused(prefs) | |
155 | #pragma unused(type) | |
156 | #pragma unused(info) | |
157 | prefs_changed(NULL); | |
158 | return; | |
159 | } | |
160 | ||
161 | __private_extern__ SCPreferencesRef | |
162 | InterfaceNamerControlPrefsInit(CFRunLoopRef runloop, | |
163 | InterfaceNamerControlPrefsCallBack callback) | |
164 | { | |
165 | CFMutableDictionaryRef options; | |
166 | ||
167 | options = CFDictionaryCreateMutable(NULL, | |
168 | 0, | |
169 | &kCFTypeDictionaryKeyCallBacks, | |
170 | &kCFTypeDictionaryValueCallBacks); | |
171 | CFDictionarySetValue(options, kSCPreferencesOptionRemoveWhenEmpty, kCFBooleanTrue); | |
172 | S_prefs = SCPreferencesCreateWithOptions(NULL, | |
173 | CFSTR("InterfaceNamerControlPrefs"), | |
174 | kInterfaceNamerControlPrefsID, | |
175 | NULL, | |
176 | options); | |
177 | CFRelease(options); | |
178 | ||
179 | if ((runloop != NULL) && (callback != NULL)) { | |
180 | S_callback = callback; | |
181 | if (!SCPreferencesSetCallback(S_prefs, InterfaceNamerControlPrefsChanged, NULL)) { | |
182 | SC_log(LOG_NOTICE, "SCPreferencesSetCallBack() failed: %s", SCErrorString(SCError())); | |
183 | goto done; | |
184 | } | |
185 | ||
186 | if (!SCPreferencesScheduleWithRunLoop(S_prefs, runloop, kCFRunLoopCommonModes)) { | |
187 | SC_log(LOG_NOTICE, "SCPreferencesScheduleWithRunLoop() failed: %s", SCErrorString(SCError())); | |
188 | (void) SCPreferencesSetCallback(S_prefs, NULL, NULL); | |
189 | } | |
190 | ||
191 | enable_prefs_observer(runloop); | |
192 | } | |
193 | ||
194 | done : | |
195 | return (S_prefs); | |
196 | } | |
197 | ||
198 | static Boolean | |
199 | InterfaceNamerControlPrefsSave(void) | |
200 | { | |
201 | Boolean saved = FALSE; | |
202 | ||
203 | if (S_prefs != NULL) { | |
204 | saved = SCPreferencesCommitChanges(S_prefs); | |
205 | SCPreferencesSynchronize(S_prefs); | |
206 | } | |
207 | return (saved); | |
208 | } | |
209 | ||
210 | static CFBooleanRef | |
211 | prefs_get_boolean(CFStringRef key) | |
212 | { | |
213 | CFBooleanRef b = NULL; | |
214 | SCPreferencesRef prefs; | |
215 | ||
216 | #if TARGET_OS_IPHONE | |
217 | prefs = InterfaceNamerControlManagedPrefsGet(); | |
218 | if (prefs != NULL) { | |
219 | b = SCPreferencesGetValue(prefs, key); | |
220 | b = isA_CFBoolean(b); | |
221 | if (b != NULL) { | |
222 | return (b); | |
223 | } | |
224 | } | |
225 | #endif /* TARGET_OS_IPHONE */ | |
226 | ||
227 | prefs = InterfaceNamerControlPrefsGet(); | |
228 | if (prefs != NULL) { | |
229 | b = SCPreferencesGetValue(prefs, key); | |
230 | b = isA_CFBoolean(b); | |
231 | } | |
232 | return (b); | |
233 | } | |
234 | ||
235 | static void | |
236 | prefs_set_boolean(CFStringRef key, CFBooleanRef b) | |
237 | { | |
238 | SCPreferencesRef prefs; | |
239 | ||
240 | prefs = InterfaceNamerControlPrefsGet(); | |
241 | if (prefs != NULL) { | |
242 | if (isA_CFBoolean(b) == NULL) { | |
243 | SCPreferencesRemoveValue(prefs, key); | |
244 | } | |
245 | else { | |
246 | SCPreferencesSetValue(prefs, key, b); | |
247 | } | |
248 | } | |
249 | return; | |
250 | } | |
251 | ||
252 | static void | |
253 | InterfaceNamerControlPrefsRefresh(void) | |
254 | { | |
255 | if (S_prefs != NULL) { | |
256 | SCPreferencesSynchronize(S_prefs); | |
257 | } | |
258 | #if TARGET_OS_IPHONE | |
259 | if (S_managed_prefs != NULL) { | |
260 | SCPreferencesSynchronize(S_managed_prefs); | |
261 | } | |
262 | #endif /* TARGET_OS_IPHONE */ | |
263 | return; | |
264 | } | |
265 | ||
266 | /** | |
267 | ** Get | |
268 | **/ | |
269 | __private_extern__ Boolean | |
270 | InterfaceNamerControlPrefsAllowNewInterfaces(void) | |
271 | { | |
272 | CFBooleanRef b; | |
273 | Boolean allow = FALSE; | |
274 | ||
275 | b = prefs_get_boolean(kAllowNewInterfaces); | |
276 | if (b != NULL) { | |
277 | allow = CFBooleanGetValue(b); | |
278 | } | |
279 | /* flush the backing store */ | |
280 | InterfaceNamerControlPrefsRefresh(); | |
281 | return (allow); | |
282 | } | |
283 | ||
284 | /** | |
285 | ** Set | |
286 | **/ | |
287 | __private_extern__ Boolean | |
288 | InterfaceNamerControlPrefsSetAllowNewInterfaces(Boolean allow) | |
289 | { | |
290 | if (allow) { | |
291 | prefs_set_boolean(kAllowNewInterfaces, kCFBooleanTrue); | |
292 | } else { | |
293 | prefs_set_boolean(kAllowNewInterfaces, NULL); | |
294 | } | |
295 | return (InterfaceNamerControlPrefsSave()); | |
296 | } |