1/*
2 * Copyright (c) 2014 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/*      CFPlugIn.c
25        Copyright (c) 1999-2013, Apple Inc.  All rights reserved.
26        Responsibility: Tony Parker
27*/
28
29#include "CFBundle_Internal.h"
30#include "CFInternal.h"
31
32CONST_STRING_DECL(kCFPlugInDynamicRegistrationKey, "CFPlugInDynamicRegistration")
33CONST_STRING_DECL(kCFPlugInDynamicRegisterFunctionKey, "CFPlugInDynamicRegisterFunction")
34CONST_STRING_DECL(kCFPlugInUnloadFunctionKey, "CFPlugInUnloadFunction")
35CONST_STRING_DECL(kCFPlugInFactoriesKey, "CFPlugInFactories")
36CONST_STRING_DECL(kCFPlugInTypesKey, "CFPlugInTypes")
37
38CF_PRIVATE void __CFPlugInInitialize(void) {
39}
40
41/* ===================== Finding factories and creating instances ===================== */
42/* For plugIn hosts. */
43/* Functions for finding factories to create specific types and actually creating instances of a type. */
44
45CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInType(CFUUIDRef typeID) {
46    CFArrayRef array = _CFPFactoryFindCopyForType(typeID);
47    CFMutableArrayRef result = NULL;
48
49    if (array) {
50        SInt32 i, c = CFArrayGetCount(array);
51        result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
52        for (i = 0; i < c; i++) {
53            CFUUIDRef factoryId = _CFPFactoryCopyFactoryID((_CFPFactoryRef)CFArrayGetValueAtIndex(array, i));
54            if (factoryId) {
55                CFArrayAppendValue(result, factoryId);
56                CFRelease(factoryId);
57            }
58        }
59        CFRelease(array);
60    }
61    return result;
62}
63
64CF_EXPORT CFArrayRef CFPlugInFindFactoriesForPlugInTypeInPlugIn(CFUUIDRef typeID, CFPlugInRef plugIn) {
65    CFArrayRef array = _CFPFactoryFindCopyForType(typeID);
66    CFMutableArrayRef result = NULL;
67
68    if (array) {
69        SInt32 i, c = CFArrayGetCount(array);
70        _CFPFactoryRef factory;
71        result = CFArrayCreateMutable(kCFAllocatorSystemDefault, 0, &kCFTypeArrayCallBacks);
72        for (i = 0; i < c; i++) {
73            factory = (_CFPFactoryRef )CFArrayGetValueAtIndex(array, i);
74            CFPlugInRef factoryPlugIn = _CFPFactoryCopyPlugIn(factory);
75            if (factoryPlugIn == plugIn) {
76                CFUUIDRef factoryId = _CFPFactoryCopyFactoryID(factory);
77                CFArrayAppendValue(result, factoryId);
78                CFRelease(factoryId);
79            }
80            if (factoryPlugIn) CFRelease(factoryPlugIn);
81        }
82        CFRelease(array);
83    }
84    return result;
85}
86
87CF_EXPORT void *CFPlugInInstanceCreate(CFAllocatorRef allocator, CFUUIDRef factoryID, CFUUIDRef typeID) {
88    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
89    void *result = NULL;
90    if (!factory) {
91        /* MF:!!! No such factory. */
92        CFLog(__kCFLogPlugIn, CFSTR("Cannot find factory %@"), factoryID);
93    } else {
94        if (!_CFPFactorySupportsType(factory, typeID)) {
95            /* MF:!!! Factory does not support type. */
96            CFLog(__kCFLogPlugIn, CFSTR("Factory %@ does not support type %@"), factoryID, typeID);
97        } else {
98            result = _CFPFactoryCreateInstance(allocator, factory, typeID);
99        }
100    }
101    return result;
102}
103
104/* ===================== Registering factories and types ===================== */
105/* For plugIn writers who must dynamically register things. */
106/* Functions to register factory functions and to associate factories with types. */
107
108CF_EXPORT Boolean CFPlugInRegisterFactoryFunction(CFUUIDRef factoryID, CFPlugInFactoryFunction func) {
109    // Create factories without plugIns from default allocator
110    // MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists
111    // _CFPFactoryRef factory =
112    (void)_CFPFactoryCreate(kCFAllocatorSystemDefault, factoryID, func);
113    return true;
114}
115
116CF_EXPORT Boolean CFPlugInRegisterFactoryFunctionByName(CFUUIDRef factoryID, CFPlugInRef plugIn, CFStringRef functionName) {
117    // Create factories with plugIns from plugIn's allocator
118    // MF:!!! Should probably check that this worked, and maybe do some pre-checking to see if it already exists
119    // _CFPFactoryRef factory =
120    (void)_CFPFactoryCreateByName(CFGetAllocator(plugIn), factoryID, plugIn, functionName);
121    return true;
122}
123
124CF_EXPORT Boolean CFPlugInUnregisterFactory(CFUUIDRef factoryID) {
125    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
126
127    if (!factory) {
128        /* MF:!!! Error.  No factory registered for this ID. */
129    } else {
130        _CFPFactoryDisable(factory);
131    }
132    return true;
133}
134
135CF_EXPORT Boolean CFPlugInRegisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) {
136    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
137
138    if (!factory) {
139        /* MF:!!! Error.  Factory must be registered (and not disabled) before types can be associated with it. */
140    } else {
141        _CFPFactoryAddType(factory, typeID);
142    }
143    return true;
144}
145
146CF_EXPORT Boolean CFPlugInUnregisterPlugInType(CFUUIDRef factoryID, CFUUIDRef typeID) {
147    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
148
149    if (!factory) {
150        /* MF:!!! Error.  Could not find factory. */
151    } else {
152        _CFPFactoryRemoveType(factory, typeID);
153    }
154    return true;
155}
156
157
158/* ================= Registering instances ================= */
159/* When a new instance of a type is created, the instance is responsible for registering itself with the factory that created it and unregistering when it deallocates. */
160/* This means that an instance must keep track of the CFUUIDRef of the factory that created it so it can unregister when it goes away. */
161
162CF_EXPORT void CFPlugInAddInstanceForFactory(CFUUIDRef factoryID) {
163    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
164
165    if (!factory) {
166        /* MF:!!! Error.  Could not find factory. */
167    } else {
168        _CFPFactoryAddInstance(factory);
169    }
170}
171
172CF_EXPORT void CFPlugInRemoveInstanceForFactory(CFUUIDRef factoryID) {
173    _CFPFactoryRef factory = _CFPFactoryFind(factoryID, true);
174
175    if (!factory) {
176        /* MF:!!! Error.  Could not find factory. */
177    } else {
178        _CFPFactoryRemoveInstance(factory);
179    }
180}
181