2 * Copyright (c) 2015 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * SOSViewManager.c - Implementation of a view manager
28 #include <Security/SecureObjectSync/SOSViewManager.h>
29 #include <Security/SecureObjectSync/SOSInternal.h>
32 /* SOSViewManager implementation. */
33 struct __OpaqueSOSViewManager
{
35 CFMutableDictionaryRef views
;
38 const CFStringRef kSOSContextChildInfoKey
= CFSTR("cntx");
39 const CFStringRef kSOSFunctionChildInfoKey
= CFSTR("fctn");
40 const CFStringRef kSOSViewNamesChildInfoKey
= CFSTR("vwns");
43 static CFStringRef
SOSViewManagerCopyFormatDescription(CFTypeRef cf
, CFDictionaryRef formatOptions
) {
44 SOSViewManagerRef vmgr
= (SOSViewManagerRef
)cf
;
45 CFStringRef desc
= CFStringCreateWithFormat(kCFAllocatorDefault
, formatOptions
, CFSTR("<ViewManager %@ >"), vmgr
->views
);
49 static void SOSViewManagerDestroy(CFTypeRef cf
) {
50 SOSViewManagerRef vmgr
= (SOSViewManagerRef
)cf
;
51 CFReleaseSafe(vmgr
->views
);
54 CFGiblisFor(SOSViewManager
);
57 static SOSViewManagerRef
SOSViewManagerCreate(CFAllocatorRef allocator
, CFErrorRef
*error
) {
58 SOSViewManagerRef vmgr
= NULL
;
59 vmgr
= CFTypeAllocate(SOSViewManager
, struct __OpaqueSOSViewManager
, allocator
);
61 vmgr
->views
= CFDictionaryCreateMutableForCFTypes(allocator
);
65 CFGiblisGetSingleton(SOSViewManagerRef
, SOSGetViewManager
, sSOSViewManager
, ^{
66 *sSOSViewManager
= SOSViewManagerCreate(kCFAllocatorDefault
, NULL
);
70 static CFStringRef
CFStringCreateWithViewNames(CFArrayRef viewNames
) {
71 CFIndex count
= CFArrayGetCount(viewNames
);
72 CFMutableArrayRef mvn
= CFArrayCreateMutableCopy(kCFAllocatorDefault
, count
, viewNames
);
73 CFArraySortValues(mvn
, CFRangeMake(0, count
), (CFComparatorFunction
)CFStringCompare
, 0);
74 CFStringRef string
= CFStringCreateByCombiningStrings(kCFAllocatorDefault
, mvn
, CFSTR(":"));
79 static SOSViewRef
SOSViewManangerCopyViewWithName(SOSViewManagerRef vmgr
, CFMutableDictionaryRef referencedViews
, CFStringRef viewName
, bool isConcrete
, CFErrorRef
*error
) {
80 SOSViewRef view
= (SOSViewRef
)CFDictionaryGetValue(vmgr
->views
, viewName
);
83 SOSViewSetConcrete(view
, true);
86 view
= SOSViewCreate(CFGetAllocator(vmgr
), isConcrete
, NULL
, error
);
88 CFDictionarySetValue(vmgr
->views
, viewName
, view
);
90 // TODO: Query for the initial manifest.
94 CFDictionarySetValue(referencedViews
, viewName
, kCFBooleanTrue
);
95 else if (!CFDictionaryContainsKey(referencedViews
, viewName
))
96 CFDictionarySetValue(referencedViews
, viewName
, kCFBooleanFalse
);
101 static SOSViewRef
SOSViewManangerCopyCompositeViewWithNames(SOSViewManagerRef vmgr
, CFMutableDictionaryRef referencedViews
, CFArrayRef viewNames
, CFErrorRef
*error
) {
102 CFStringRef compositeName
= CFStringCreateWithViewNames(viewNames
);
103 SOSViewRef compositeView
= (SOSViewRef
)CFDictionaryGetValue(vmgr
->views
, compositeName
);
105 CFDictionarySetValue(referencedViews
, compositeName
, kCFBooleanTrue
);
106 CFRetain(compositeView
);
108 compositeView
= SOSViewCreate(CFGetAllocator(vmgr
), true, NULL
, error
);
110 // Find the views for each name, and add the new view as a child to each one.
111 CFStringRef viewName
;
112 CFArrayForEachC(viewNames
, viewName
) {
113 SOSViewRef parent
= SOSViewManangerCopyViewWithName(vmgr
, referencedViews
, viewName
, false, error
);
115 CFReleaseNull(compositeView
);
118 SOSViewAddChild(parent
, compositeView
);
119 // Update the composite view's manifest by adding each parents manifest.
120 // TODO: Potentially move this out of the loop and create a single multi way manifest union operation
121 SOSManifestRef pmf
= SOSViewCopyManifest(parent
, error
);
122 SOSViewUpdateManifest(compositeView
, kSOSDataSourceSOSTransaction
, NULL
, pmf
, error
);
125 CFDictionarySetValue(vmgr
->views
, viewName
, compositeView
);
128 CFReleaseSafe(compositeName
);
129 return compositeView
;
132 static bool SOSViewManangerAddChildWithInfo(SOSViewManagerRef vmgr
, CFMutableDictionaryRef referencedViews
, CFDictionaryRef childInfo
, CFErrorRef
*error
) {
133 CFArrayRef viewNames
= (CFArrayRef
)CFDictionaryGetValue(childInfo
, kSOSViewNamesChildInfoKey
);
134 // const void *context = (const void *)CFDictionaryGetValue(childInfo, kSOSContextChildInfoKey);
135 // const void *func = (const void *)CFDictionaryGetValue(childInfo, kSOSFunctionChildInfoKey);
137 CFIndex count
= CFArrayGetCount(viewNames
);
139 CFStringRef key
= CFArrayGetValueAtIndex(viewNames
, 0);
140 SOSViewRef view
= SOSViewManangerCopyViewWithName(vmgr
, referencedViews
, key
, true, error
);
142 //SOSViewAddClient(view, context, func);
143 if (view
) count
++; // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING
144 } else if (count
> 1) {
145 SOSViewRef view
= SOSViewManangerCopyCompositeViewWithNames(vmgr
, referencedViews
, viewNames
, error
);
147 //SOSViewAddClient(view, context, func);
148 if (view
) count
++; // TODO: REMOVE MOVE -- HERE ONLY FOR COMPILER WARNING
154 struct SOSViewManagerContext
{
155 SOSViewManagerRef vmgr
;
156 CFDictionaryRef referencedViews
;
159 static void SOSViewManagerUpdateView(const void *key
, const void *value
, void *context
) {
160 struct SOSViewManagerContext
*vmc
= context
;
161 CFBooleanRef isConcrete
= CFDictionaryGetValue(vmc
->referencedViews
, key
);
163 CFDictionaryRemoveValue(vmc
->vmgr
->views
, key
);
164 } else if (CFBooleanGetValue(isConcrete
) == 0) {
165 SOSViewRef view
= (SOSViewRef
)CFDictionaryGetValue(vmc
->vmgr
->views
, key
);
166 SOSViewSetConcrete(view
, false);
170 bool SOSViewManagerSetChildren(SOSViewManagerRef vmgr
, CFArrayRef children
, CFErrorRef
*error
) {
172 CFMutableDictionaryRef referencedViews
= CFDictionaryCreateMutableForCFTypes(kCFAllocatorDefault
);
173 CFDictionaryRef childInfo
;
174 CFArrayForEachC(children
, childInfo
) {
175 ok
&= SOSViewManangerAddChildWithInfo(vmgr
, referencedViews
, childInfo
, error
);
178 // Potentially populate all views here.
180 // Cleanup, remove any views we no longer reference, and set any views which need not be concrete as such.
181 struct SOSViewManagerContext vmc
= {
183 .referencedViews
= referencedViews
,
185 CFDictionaryApplyFunction(vmgr
->views
, SOSViewManagerUpdateView
, &vmc
);
186 CFRetainSafe(referencedViews
);