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