[Cocoa] Remove some more __has_include guards
[WebKit-https.git] / Source / WebKit2 / Shared / cf / ArgumentCodersCF.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ArgumentCodersCF.h"
28
29 #include "ArgumentDecoder.h"
30 #include "ArgumentEncoder.h"
31 #include "DataReference.h"
32 #include <WebCore/CFURLExtras.h>
33 #include <wtf/Vector.h>
34
35 #if USE(FOUNDATION)
36 #import <Foundation/Foundation.h>
37 #endif
38
39 #if USE(APPLE_INTERNAL_SDK)
40 #include <Security/SecIdentityPriv.h>
41 #endif
42
43 extern "C" SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, SecCertificateRef certificate, SecKeyRef privateKey);
44
45 #if PLATFORM(IOS)
46 #if USE(APPLE_INTERNAL_SDK)
47 #include <Security/SecKeyPriv.h>
48 #endif
49
50 extern "C" OSStatus SecKeyFindWithPersistentRef(CFDataRef persistentRef, SecKeyRef* lookedUpData);
51 #endif
52
53 #if HAVE(SEC_ACCESS_CONTROL)
54 #if USE(APPLE_INTERNAL_SDK)
55 #include <Security/SecAccessControlPriv.h>
56 #endif
57
58 extern "C" SecAccessControlRef SecAccessControlCreateFromData(CFAllocatorRef allocator, CFDataRef data, CFErrorRef *error);
59 extern "C" CFDataRef SecAccessControlCopyData(SecAccessControlRef access_control);
60 #endif
61
62 using namespace WebCore;
63
64 namespace IPC {
65
66 CFTypeRef tokenNullTypeRef()
67 {
68     static CFStringRef tokenNullType = CFSTR("WKNull");
69     return tokenNullType;
70 }
71
72 enum CFType {
73     CFArray,
74     CFBoolean,
75     CFData,
76     CFDate,
77     CFDictionary,
78     CFNull,
79     CFNumber,
80     CFString,
81     CFURL,
82     SecCertificate,
83     SecIdentity,
84 #if HAVE(SEC_KEYCHAIN)
85     SecKeychainItem,
86 #endif
87 #if HAVE(SEC_ACCESS_CONTROL)
88     SecAccessControl,
89 #endif
90     Null,
91     Unknown,
92 };
93
94 static CFType typeFromCFTypeRef(CFTypeRef type)
95 {
96     ASSERT(type);
97
98     if (type == tokenNullTypeRef())
99         return Null;
100
101     CFTypeID typeID = CFGetTypeID(type);
102     if (typeID == CFArrayGetTypeID())
103         return CFArray;
104     if (typeID == CFBooleanGetTypeID())
105         return CFBoolean;
106     if (typeID == CFDataGetTypeID())
107         return CFData;
108     if (typeID == CFDateGetTypeID())
109         return CFDate;
110     if (typeID == CFDictionaryGetTypeID())
111         return CFDictionary;
112     if (typeID == CFNullGetTypeID())
113         return CFNull;
114     if (typeID == CFNumberGetTypeID())
115         return CFNumber;
116     if (typeID == CFStringGetTypeID())
117         return CFString;
118     if (typeID == CFURLGetTypeID())
119         return CFURL;
120     if (typeID == SecCertificateGetTypeID())
121         return SecCertificate;
122     if (typeID == SecIdentityGetTypeID())
123         return SecIdentity;
124 #if HAVE(SEC_KEYCHAIN)
125     if (typeID == SecKeychainItemGetTypeID())
126         return SecKeychainItem;
127 #endif
128 #if HAVE(SEC_ACCESS_CONTROL)
129     if (typeID == SecAccessControlGetTypeID())
130         return SecAccessControl;
131 #endif
132
133     ASSERT_NOT_REACHED();
134     return Unknown;
135 }
136
137 void encode(ArgumentEncoder& encoder, CFTypeRef typeRef)
138 {
139     CFType type = typeFromCFTypeRef(typeRef);
140     encoder.encodeEnum(type);
141
142     switch (type) {
143     case CFArray:
144         encode(encoder, static_cast<CFArrayRef>(typeRef));
145         return;
146     case CFBoolean:
147         encode(encoder, static_cast<CFBooleanRef>(typeRef));
148         return;
149     case CFData:
150         encode(encoder, static_cast<CFDataRef>(typeRef));
151         return;
152     case CFDate:
153         encode(encoder, static_cast<CFDateRef>(typeRef));
154         return;
155     case CFDictionary:
156         encode(encoder, static_cast<CFDictionaryRef>(typeRef));
157         return;
158     case CFNull:
159         return;
160     case CFNumber:
161         encode(encoder, static_cast<CFNumberRef>(typeRef));
162         return;
163     case CFString:
164         encode(encoder, static_cast<CFStringRef>(typeRef));
165         return;
166     case CFURL:
167         encode(encoder, static_cast<CFURLRef>(typeRef));
168         return;
169     case SecCertificate:
170         encode(encoder, (SecCertificateRef)typeRef);
171         return;
172     case SecIdentity:
173         encode(encoder, (SecIdentityRef)(typeRef));
174         return;
175 #if HAVE(SEC_KEYCHAIN)
176     case SecKeychainItem:
177         encode(encoder, (SecKeychainItemRef)typeRef);
178         return;
179 #endif
180 #if HAVE(SEC_ACCESS_CONTROL)
181     case SecAccessControl:
182         encode(encoder, (SecAccessControlRef)typeRef);
183         return;
184 #endif
185     case Null:
186         return;
187     case Unknown:
188         break;
189     }
190
191     ASSERT_NOT_REACHED();
192 }
193
194 bool decode(ArgumentDecoder& decoder, RetainPtr<CFTypeRef>& result)
195 {
196     CFType type;
197     if (!decoder.decodeEnum(type))
198         return false;
199
200     switch (type) {
201     case CFArray: {
202         RetainPtr<CFArrayRef> array;
203         if (!decode(decoder, array))
204             return false;
205         result = adoptCF(array.leakRef());
206         return true;
207     }
208     case CFBoolean: {
209         RetainPtr<CFBooleanRef> boolean;
210         if (!decode(decoder, boolean))
211             return false;
212         result = adoptCF(boolean.leakRef());
213         return true;
214     }
215     case CFData: {
216         RetainPtr<CFDataRef> data;
217         if (!decode(decoder, data))
218             return false;
219         result = adoptCF(data.leakRef());
220         return true;
221     }
222     case CFDate: {
223         RetainPtr<CFDateRef> date;
224         if (!decode(decoder, date))
225             return false;
226         result = adoptCF(date.leakRef());
227         return true;
228     }
229     case CFDictionary: {
230         RetainPtr<CFDictionaryRef> dictionary;
231         if (!decode(decoder, dictionary))
232             return false;
233         result = adoptCF(dictionary.leakRef());
234         return true;
235     }
236     case CFNull:
237         result = adoptCF(kCFNull);
238         return true;
239     case CFNumber: {
240         RetainPtr<CFNumberRef> number;
241         if (!decode(decoder, number))
242             return false;
243         result = adoptCF(number.leakRef());
244         return true;
245     }
246     case CFString: {
247         RetainPtr<CFStringRef> string;
248         if (!decode(decoder, string))
249             return false;
250         result = adoptCF(string.leakRef());
251         return true;
252     }
253     case CFURL: {
254         RetainPtr<CFURLRef> url;
255         if (!decode(decoder, url))
256             return false;
257         result = adoptCF(url.leakRef());
258         return true;
259     }
260     case SecCertificate: {
261         RetainPtr<SecCertificateRef> certificate;
262         if (!decode(decoder, certificate))
263             return false;
264         result = adoptCF(certificate.leakRef());
265         return true;
266     }
267     case SecIdentity: {
268         RetainPtr<SecIdentityRef> identity;
269         if (!decode(decoder, identity))
270             return false;
271         result = adoptCF(identity.leakRef());
272         return true;
273     }
274 #if HAVE(SEC_KEYCHAIN)
275     case SecKeychainItem: {
276         RetainPtr<SecKeychainItemRef> keychainItem;
277         if (!decode(decoder, keychainItem))
278             return false;
279         result = adoptCF(keychainItem.leakRef());
280         return true;
281     }
282 #endif
283 #if HAVE(SEC_ACCESS_CONTROL)
284     case SecAccessControl: {
285         RetainPtr<SecAccessControlRef> accessControl;
286         if (!decode(decoder, accessControl))
287             return false;
288         result = adoptCF(accessControl.leakRef());
289         return true;
290     }
291 #endif
292     case Null:
293         result = tokenNullTypeRef();
294         return true;
295     case Unknown:
296         ASSERT_NOT_REACHED();
297         return false;
298     }
299
300     return false;
301 }
302
303 void encode(ArgumentEncoder& encoder, CFArrayRef array)
304 {
305     CFIndex size = CFArrayGetCount(array);
306     Vector<CFTypeRef, 32> values(size);
307
308     CFArrayGetValues(array, CFRangeMake(0, size), values.data());
309
310     encoder << static_cast<uint64_t>(size);
311
312     for (CFIndex i = 0; i < size; ++i) {
313         ASSERT(values[i]);
314
315         encode(encoder, values[i]);
316     }
317 }
318
319 bool decode(ArgumentDecoder& decoder, RetainPtr<CFArrayRef>& result)
320 {
321     uint64_t size;
322     if (!decoder.decode(size))
323         return false;
324
325     RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
326
327     for (size_t i = 0; i < size; ++i) {
328         RetainPtr<CFTypeRef> element;
329         if (!decode(decoder, element))
330             return false;
331
332         CFArrayAppendValue(array.get(), element.get());
333     }
334
335     result = adoptCF(array.leakRef());
336     return true;
337 }
338
339 void encode(ArgumentEncoder& encoder, CFBooleanRef boolean)
340 {
341     encoder << static_cast<bool>(CFBooleanGetValue(boolean));
342 }
343
344 bool decode(ArgumentDecoder& decoder, RetainPtr<CFBooleanRef>& result)
345 {
346     bool boolean;
347     if (!decoder.decode(boolean))
348         return false;
349
350     result = adoptCF(boolean ? kCFBooleanTrue : kCFBooleanFalse);
351     return true;
352 }
353
354 void encode(ArgumentEncoder& encoder, CFDataRef data)
355 {
356     CFIndex length = CFDataGetLength(data);
357     const UInt8* bytePtr = CFDataGetBytePtr(data);
358
359     encoder << IPC::DataReference(bytePtr, length);
360 }
361
362 bool decode(ArgumentDecoder& decoder, RetainPtr<CFDataRef>& result)
363 {
364     IPC::DataReference dataReference;
365     if (!decoder.decode(dataReference))
366         return false;
367
368     result = adoptCF(CFDataCreate(0, dataReference.data(), dataReference.size()));
369     return true;
370 }
371
372 void encode(ArgumentEncoder& encoder, CFDateRef date)
373 {
374     encoder << static_cast<double>(CFDateGetAbsoluteTime(date));
375 }
376
377 bool decode(ArgumentDecoder& decoder, RetainPtr<CFDateRef>& result)
378 {
379     double absoluteTime;
380     if (!decoder.decode(absoluteTime))
381         return false;
382
383     result = adoptCF(CFDateCreate(0, absoluteTime));
384     return true;
385 }
386
387 void encode(ArgumentEncoder& encoder, CFDictionaryRef dictionary)
388 {
389     CFIndex size = CFDictionaryGetCount(dictionary);
390     Vector<CFTypeRef, 32> keys(size);
391     Vector<CFTypeRef, 32> values(size);
392     
393     CFDictionaryGetKeysAndValues(dictionary, keys.data(), values.data());
394
395     encoder << static_cast<uint64_t>(size);
396
397     for (CFIndex i = 0; i < size; ++i) {
398         ASSERT(keys[i]);
399         ASSERT(CFGetTypeID(keys[i]) == CFStringGetTypeID());
400         ASSERT(values[i]);
401
402         // Ignore values we don't recognize.
403         if (typeFromCFTypeRef(values[i]) == Unknown)
404             continue;
405
406         encode(encoder, static_cast<CFStringRef>(keys[i]));
407         encode(encoder, values[i]);
408     }
409 }
410
411 bool decode(ArgumentDecoder& decoder, RetainPtr<CFDictionaryRef>& result)
412 {
413     uint64_t size;
414     if (!decoder.decode(size))
415         return false;
416
417     RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
418     for (uint64_t i = 0; i < size; ++i) {
419         // Try to decode the key name.
420         RetainPtr<CFStringRef> key;
421         if (!decode(decoder, key))
422             return false;
423
424         RetainPtr<CFTypeRef> value;
425         if (!decode(decoder, value))
426             return false;
427
428         CFDictionarySetValue(dictionary.get(), key.get(), value.get());
429     }
430
431     result = adoptCF(dictionary.leakRef());
432     return true;
433 }
434
435 void encode(ArgumentEncoder& encoder, CFNumberRef number)
436 {
437     CFNumberType numberType = CFNumberGetType(number);
438
439     Vector<uint8_t> buffer(CFNumberGetByteSize(number));
440     bool result = CFNumberGetValue(number, numberType, buffer.data());
441     ASSERT_UNUSED(result, result);
442
443     encoder.encodeEnum(numberType);
444     encoder << IPC::DataReference(buffer);
445 }
446
447 static size_t sizeForNumberType(CFNumberType numberType)
448 {
449     switch (numberType) {
450     case kCFNumberSInt8Type:
451         return sizeof(SInt8);
452     case kCFNumberSInt16Type:
453         return sizeof(SInt16);
454     case kCFNumberSInt32Type:
455         return sizeof(SInt32);
456     case kCFNumberSInt64Type:
457         return sizeof(SInt64);
458     case kCFNumberFloat32Type:
459         return sizeof(Float32);
460     case kCFNumberFloat64Type:
461         return sizeof(Float64);
462     case kCFNumberCharType:
463         return sizeof(char);
464     case kCFNumberShortType:
465         return sizeof(short);
466     case kCFNumberIntType:
467         return sizeof(int);
468     case kCFNumberLongType:
469         return sizeof(long);
470     case kCFNumberLongLongType:
471         return sizeof(long long);
472     case kCFNumberFloatType:
473         return sizeof(float);
474     case kCFNumberDoubleType:
475         return sizeof(double);
476     case kCFNumberCFIndexType:
477         return sizeof(CFIndex);
478     case kCFNumberNSIntegerType:
479 #ifdef __LP64__
480         return sizeof(long);
481 #else
482         return sizeof(int);
483 #endif
484     case kCFNumberCGFloatType:
485 #ifdef __LP64__
486         return sizeof(double);
487 #else
488         return sizeof(float);
489 #endif
490     }
491
492     return 0;
493 }
494
495 bool decode(ArgumentDecoder& decoder, RetainPtr<CFNumberRef>& result)
496 {
497     CFNumberType numberType;
498     if (!decoder.decodeEnum(numberType))
499         return false;
500
501     IPC::DataReference dataReference;
502     if (!decoder.decode(dataReference))
503         return false;
504
505     size_t neededBufferSize = sizeForNumberType(numberType);
506     if (!neededBufferSize || dataReference.size() != neededBufferSize)
507         return false;
508
509     ASSERT(dataReference.data());
510     CFNumberRef number = CFNumberCreate(0, numberType, dataReference.data());
511     result = adoptCF(number);
512
513     return true;
514 }
515
516 void encode(ArgumentEncoder& encoder, CFStringRef string)
517 {
518     CFIndex length = CFStringGetLength(string);
519     CFStringEncoding encoding = CFStringGetFastestEncoding(string);
520
521     CFRange range = CFRangeMake(0, length);
522     CFIndex bufferLength = 0;
523
524     CFIndex numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, 0, 0, &bufferLength);
525     ASSERT(numConvertedBytes == length);
526
527     Vector<UInt8, 128> buffer(bufferLength);
528     numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, buffer.data(), buffer.size(), &bufferLength);
529     ASSERT(numConvertedBytes == length);
530
531     encoder.encodeEnum(encoding);
532     encoder << IPC::DataReference(buffer);
533 }
534
535 bool decode(ArgumentDecoder& decoder, RetainPtr<CFStringRef>& result)
536 {
537     CFStringEncoding encoding;
538     if (!decoder.decodeEnum(encoding))
539         return false;
540
541     if (!CFStringIsEncodingAvailable(encoding))
542         return false;
543     
544     IPC::DataReference dataReference;
545     if (!decoder.decode(dataReference))
546         return false;
547
548     CFStringRef string = CFStringCreateWithBytes(0, dataReference.data(), dataReference.size(), encoding, false);
549     if (!string)
550         return false;
551
552     result = adoptCF(string);
553     return true;
554 }
555
556 void encode(ArgumentEncoder& encoder, CFURLRef url)
557 {
558     CFURLRef baseURL = CFURLGetBaseURL(url);
559     encoder << static_cast<bool>(baseURL);
560     if (baseURL)
561         encode(encoder, baseURL);
562
563     URLCharBuffer urlBytes;
564     getURLBytes(url, urlBytes);
565     IPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(urlBytes.data()), urlBytes.size());
566     encoder << dataReference;
567 }
568
569 bool decode(ArgumentDecoder& decoder, RetainPtr<CFURLRef>& result)
570 {
571     RetainPtr<CFURLRef> baseURL;
572     bool hasBaseURL;
573     if (!decoder.decode(hasBaseURL))
574         return false;
575     if (hasBaseURL) {
576         if (!decode(decoder, baseURL))
577             return false;
578     }
579
580     IPC::DataReference urlBytes;
581     if (!decoder.decode(urlBytes))
582         return false;
583
584 #if USE(FOUNDATION)
585     // FIXME: Move this to ArgumentCodersCFMac.mm and change this file back to be C++
586     // instead of Objective-C++.
587     if (urlBytes.isEmpty()) {
588         // CFURL can't hold an empty URL, unlike NSURL.
589         // FIXME: This discards base URL, which seems incorrect.
590         result = reinterpret_cast<CFURLRef>([NSURL URLWithString:@""]);
591         return true;
592     }
593 #endif
594
595     result = createCFURLFromBuffer(reinterpret_cast<const char*>(urlBytes.data()), urlBytes.size(), baseURL.get());
596     return result;
597 }
598
599 void encode(ArgumentEncoder& encoder, SecCertificateRef certificate)
600 {
601     RetainPtr<CFDataRef> data = adoptCF(SecCertificateCopyData(certificate));
602     encode(encoder, data.get());
603 }
604
605 bool decode(ArgumentDecoder& decoder, RetainPtr<SecCertificateRef>& result)
606 {
607     RetainPtr<CFDataRef> data;
608     if (!decode(decoder, data))
609         return false;
610
611     result = adoptCF(SecCertificateCreateWithData(0, data.get()));
612     return true;
613 }
614
615 #if PLATFORM(IOS)
616 static bool secKeyRefDecodingAllowed;
617
618 void setAllowsDecodingSecKeyRef(bool allowsDecodingSecKeyRef)
619 {
620     secKeyRefDecodingAllowed = allowsDecodingSecKeyRef;
621 }
622
623 static CFDataRef copyPersistentRef(SecKeyRef key)
624 {
625     // This function differs from SecItemCopyPersistentRef in that it specifies an access group.
626     // This is necessary in case there are multiple copies of the key in the keychain, because we
627     // need a reference to the one that the Networking process will be able to access.
628     CFDataRef persistentRef = nullptr;
629     SecItemCopyMatching((CFDictionaryRef)@{
630         (id)kSecReturnPersistentRef: @YES,
631         (id)kSecValueRef: (id)key,
632         (id)kSecAttrSynchronizable: (id)kSecAttrSynchronizableAny,
633         (id)kSecAttrAccessGroup: @"com.apple.identities",
634     }, (CFTypeRef*)&persistentRef);
635
636     return persistentRef;
637 }
638 #endif
639
640 void encode(ArgumentEncoder& encoder, SecIdentityRef identity)
641 {
642     SecCertificateRef certificate = nullptr;
643     SecIdentityCopyCertificate(identity, &certificate);
644     encode(encoder, certificate);
645     CFRelease(certificate);
646
647     SecKeyRef key = nullptr;
648     SecIdentityCopyPrivateKey(identity, &key);
649
650     CFDataRef keyData = nullptr;
651 #if PLATFORM(IOS)
652     keyData = copyPersistentRef(key);
653 #endif
654 #if PLATFORM(MAC)
655     SecKeychainItemCreatePersistentReference((SecKeychainItemRef)key, &keyData);
656 #endif
657     CFRelease(key);
658
659     encoder << !!keyData;
660     if (keyData) {
661         encode(encoder, keyData);
662         CFRelease(keyData);
663     }
664 }
665
666 bool decode(ArgumentDecoder& decoder, RetainPtr<SecIdentityRef>& result)
667 {
668     RetainPtr<SecCertificateRef> certificate;
669     if (!decode(decoder, certificate))
670         return false;
671
672     bool hasKey;
673     if (!decoder.decode(hasKey))
674         return false;
675
676     if (!hasKey)
677         return true;
678
679     RetainPtr<CFDataRef> keyData;
680     if (!decode(decoder, keyData))
681         return false;
682
683     SecKeyRef key = nullptr;
684 #if PLATFORM(IOS)
685     if (secKeyRefDecodingAllowed)
686         SecKeyFindWithPersistentRef(keyData.get(), &key);
687 #endif
688 #if PLATFORM(MAC)
689     SecKeychainItemCopyFromPersistentReference(keyData.get(), (SecKeychainItemRef*)&key);
690 #endif
691     if (key) {
692         result = adoptCF(SecIdentityCreate(kCFAllocatorDefault, certificate.get(), key));
693         CFRelease(key);
694     }
695
696     return true;
697 }
698
699 #if HAVE(SEC_KEYCHAIN)
700 void encode(ArgumentEncoder& encoder, SecKeychainItemRef keychainItem)
701 {
702     CFDataRef data;
703     if (SecKeychainItemCreatePersistentReference(keychainItem, &data) == errSecSuccess) {
704         encode(encoder, data);
705         CFRelease(data);
706     }
707 }
708
709 bool decode(ArgumentDecoder& decoder, RetainPtr<SecKeychainItemRef>& result)
710 {
711     RetainPtr<CFDataRef> data;
712     if (!IPC::decode(decoder, data))
713         return false;
714
715     SecKeychainItemRef item;
716     if (SecKeychainItemCopyFromPersistentReference(data.get(), &item) != errSecSuccess || !item)
717         return false;
718     
719     result = adoptCF(item);
720     return true;
721 }
722 #endif
723
724 #if HAVE(SEC_ACCESS_CONTROL)
725 void encode(ArgumentEncoder& encoder, SecAccessControlRef accessControl)
726 {
727     RetainPtr<CFDataRef> data = adoptCF(SecAccessControlCopyData(accessControl));
728     if (data)
729         encode(encoder, data.get());
730 }
731
732 bool decode(ArgumentDecoder& decoder, RetainPtr<SecAccessControlRef>& result)
733 {
734     RetainPtr<CFDataRef> data;
735     if (!decode(decoder, data))
736         return false;
737
738     result = adoptCF(SecAccessControlCreateFromData(kCFAllocatorDefault, data.get(), nullptr));
739     if (!result)
740         return false;
741
742     return true;
743 }
744
745 #endif
746
747 } // namespace IPC