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