ArgumentCodersCF.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  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. #include "config.h"
  26. #include "ArgumentCodersCF.h"
  27. #include "ArgumentDecoder.h"
  28. #include "ArgumentEncoder.h"
  29. #include "DataReference.h"
  30. #include <WebCore/CFURLExtras.h>
  31. #include <wtf/Vector.h>
  32. #if PLATFORM(MAC)
  33. #import <Foundation/Foundation.h>
  34. #endif
  35. using namespace WebCore;
  36. namespace CoreIPC {
  37. CFTypeRef tokenNullTypeRef()
  38. {
  39. static CFStringRef tokenNullType = CFSTR("WKNull");
  40. return tokenNullType;
  41. }
  42. enum CFType {
  43. CFArray,
  44. CFBoolean,
  45. CFData,
  46. CFDate,
  47. CFDictionary,
  48. CFNull,
  49. CFNumber,
  50. CFString,
  51. CFURL,
  52. #if USE(SECURITY_FRAMEWORK)
  53. SecCertificate,
  54. SecKeychainItem,
  55. #endif
  56. Null,
  57. Unknown,
  58. };
  59. static CFType typeFromCFTypeRef(CFTypeRef type)
  60. {
  61. ASSERT(type);
  62. if (type == tokenNullTypeRef())
  63. return Null;
  64. CFTypeID typeID = CFGetTypeID(type);
  65. if (typeID == CFArrayGetTypeID())
  66. return CFArray;
  67. if (typeID == CFBooleanGetTypeID())
  68. return CFBoolean;
  69. if (typeID == CFDataGetTypeID())
  70. return CFData;
  71. if (typeID == CFDateGetTypeID())
  72. return CFDate;
  73. if (typeID == CFDictionaryGetTypeID())
  74. return CFDictionary;
  75. if (typeID == CFNullGetTypeID())
  76. return CFNull;
  77. if (typeID == CFNumberGetTypeID())
  78. return CFNumber;
  79. if (typeID == CFStringGetTypeID())
  80. return CFString;
  81. if (typeID == CFURLGetTypeID())
  82. return CFURL;
  83. #if USE(SECURITY_FRAMEWORK)
  84. if (typeID == SecCertificateGetTypeID())
  85. return SecCertificate;
  86. if (typeID == SecKeychainItemGetTypeID())
  87. return SecKeychainItem;
  88. #endif
  89. ASSERT_NOT_REACHED();
  90. return Unknown;
  91. }
  92. void encode(ArgumentEncoder& encoder, CFTypeRef typeRef)
  93. {
  94. CFType type = typeFromCFTypeRef(typeRef);
  95. encoder.encodeEnum(type);
  96. switch (type) {
  97. case CFArray:
  98. encode(encoder, static_cast<CFArrayRef>(typeRef));
  99. return;
  100. case CFBoolean:
  101. encode(encoder, static_cast<CFBooleanRef>(typeRef));
  102. return;
  103. case CFData:
  104. encode(encoder, static_cast<CFDataRef>(typeRef));
  105. return;
  106. case CFDate:
  107. encode(encoder, static_cast<CFDateRef>(typeRef));
  108. return;
  109. case CFDictionary:
  110. encode(encoder, static_cast<CFDictionaryRef>(typeRef));
  111. return;
  112. case CFNull:
  113. return;
  114. case CFNumber:
  115. encode(encoder, static_cast<CFNumberRef>(typeRef));
  116. return;
  117. case CFString:
  118. encode(encoder, static_cast<CFStringRef>(typeRef));
  119. return;
  120. case CFURL:
  121. encode(encoder, static_cast<CFURLRef>(typeRef));
  122. return;
  123. #if USE(SECURITY_FRAMEWORK)
  124. case SecCertificate:
  125. encode(encoder, (SecCertificateRef)typeRef);
  126. return;
  127. case SecKeychainItem:
  128. encode(encoder, (SecKeychainItemRef)typeRef);
  129. return;
  130. #endif
  131. case Null:
  132. return;
  133. case Unknown:
  134. break;
  135. }
  136. ASSERT_NOT_REACHED();
  137. }
  138. bool decode(ArgumentDecoder& decoder, RetainPtr<CFTypeRef>& result)
  139. {
  140. CFType type;
  141. if (!decoder.decodeEnum(type))
  142. return false;
  143. switch (type) {
  144. case CFArray: {
  145. RetainPtr<CFArrayRef> array;
  146. if (!decode(decoder, array))
  147. return false;
  148. result = adoptCF(array.leakRef());
  149. return true;
  150. }
  151. case CFBoolean: {
  152. RetainPtr<CFBooleanRef> boolean;
  153. if (!decode(decoder, boolean))
  154. return false;
  155. result = adoptCF(boolean.leakRef());
  156. return true;
  157. }
  158. case CFData: {
  159. RetainPtr<CFDataRef> data;
  160. if (!decode(decoder, data))
  161. return false;
  162. result = adoptCF(data.leakRef());
  163. return true;
  164. }
  165. case CFDate: {
  166. RetainPtr<CFDateRef> date;
  167. if (!decode(decoder, date))
  168. return false;
  169. result = adoptCF(date.leakRef());
  170. return true;
  171. }
  172. case CFDictionary: {
  173. RetainPtr<CFDictionaryRef> dictionary;
  174. if (!decode(decoder, dictionary))
  175. return false;
  176. result = adoptCF(dictionary.leakRef());
  177. return true;
  178. }
  179. case CFNull:
  180. result = adoptCF(kCFNull);
  181. return true;
  182. case CFNumber: {
  183. RetainPtr<CFNumberRef> number;
  184. if (!decode(decoder, number))
  185. return false;
  186. result = adoptCF(number.leakRef());
  187. return true;
  188. }
  189. case CFString: {
  190. RetainPtr<CFStringRef> string;
  191. if (!decode(decoder, string))
  192. return false;
  193. result = adoptCF(string.leakRef());
  194. return true;
  195. }
  196. case CFURL: {
  197. RetainPtr<CFURLRef> url;
  198. if (!decode(decoder, url))
  199. return false;
  200. result = adoptCF(url.leakRef());
  201. return true;
  202. }
  203. #if USE(SECURITY_FRAMEWORK)
  204. case SecCertificate: {
  205. RetainPtr<SecCertificateRef> certificate;
  206. if (!decode(decoder, certificate))
  207. return false;
  208. result = adoptCF(certificate.leakRef());
  209. return true;
  210. }
  211. case SecKeychainItem: {
  212. RetainPtr<SecKeychainItemRef> keychainItem;
  213. if (!decode(decoder, keychainItem))
  214. return false;
  215. result = adoptCF(keychainItem.leakRef());
  216. return true;
  217. }
  218. #endif
  219. case Null:
  220. result = tokenNullTypeRef();
  221. return true;
  222. case Unknown:
  223. ASSERT_NOT_REACHED();
  224. return false;
  225. }
  226. return false;
  227. }
  228. void encode(ArgumentEncoder& encoder, CFArrayRef array)
  229. {
  230. CFIndex size = CFArrayGetCount(array);
  231. Vector<CFTypeRef, 32> values(size);
  232. CFArrayGetValues(array, CFRangeMake(0, size), values.data());
  233. encoder << static_cast<uint64_t>(size);
  234. for (CFIndex i = 0; i < size; ++i) {
  235. ASSERT(values[i]);
  236. encode(encoder, values[i]);
  237. }
  238. }
  239. bool decode(ArgumentDecoder& decoder, RetainPtr<CFArrayRef>& result)
  240. {
  241. uint64_t size;
  242. if (!decoder.decode(size))
  243. return false;
  244. RetainPtr<CFMutableArrayRef> array = adoptCF(CFArrayCreateMutable(0, 0, &kCFTypeArrayCallBacks));
  245. for (size_t i = 0; i < size; ++i) {
  246. RetainPtr<CFTypeRef> element;
  247. if (!decode(decoder, element))
  248. return false;
  249. CFArrayAppendValue(array.get(), element.get());
  250. }
  251. result = adoptCF(array.leakRef());
  252. return true;
  253. }
  254. void encode(ArgumentEncoder& encoder, CFBooleanRef boolean)
  255. {
  256. encoder << static_cast<bool>(CFBooleanGetValue(boolean));
  257. }
  258. bool decode(ArgumentDecoder& decoder, RetainPtr<CFBooleanRef>& result)
  259. {
  260. bool boolean;
  261. if (!decoder.decode(boolean))
  262. return false;
  263. result = adoptCF(boolean ? kCFBooleanTrue : kCFBooleanFalse);
  264. return true;
  265. }
  266. void encode(ArgumentEncoder& encoder, CFDataRef data)
  267. {
  268. CFIndex length = CFDataGetLength(data);
  269. const UInt8* bytePtr = CFDataGetBytePtr(data);
  270. encoder << CoreIPC::DataReference(bytePtr, length);
  271. }
  272. bool decode(ArgumentDecoder& decoder, RetainPtr<CFDataRef>& result)
  273. {
  274. CoreIPC::DataReference dataReference;
  275. if (!decoder.decode(dataReference))
  276. return false;
  277. result = adoptCF(CFDataCreate(0, dataReference.data(), dataReference.size()));
  278. return true;
  279. }
  280. void encode(ArgumentEncoder& encoder, CFDateRef date)
  281. {
  282. encoder << static_cast<double>(CFDateGetAbsoluteTime(date));
  283. }
  284. bool decode(ArgumentDecoder& decoder, RetainPtr<CFDateRef>& result)
  285. {
  286. double absoluteTime;
  287. if (!decoder.decode(absoluteTime))
  288. return false;
  289. result = adoptCF(CFDateCreate(0, absoluteTime));
  290. return true;
  291. }
  292. void encode(ArgumentEncoder& encoder, CFDictionaryRef dictionary)
  293. {
  294. CFIndex size = CFDictionaryGetCount(dictionary);
  295. Vector<CFTypeRef, 32> keys(size);
  296. Vector<CFTypeRef, 32> values(size);
  297. CFDictionaryGetKeysAndValues(dictionary, keys.data(), values.data());
  298. encoder << static_cast<uint64_t>(size);
  299. for (CFIndex i = 0; i < size; ++i) {
  300. ASSERT(keys[i]);
  301. ASSERT(CFGetTypeID(keys[i]) == CFStringGetTypeID());
  302. ASSERT(values[i]);
  303. // Ignore values we don't recognize.
  304. if (typeFromCFTypeRef(values[i]) == Unknown)
  305. continue;
  306. encode(encoder, static_cast<CFStringRef>(keys[i]));
  307. encode(encoder, values[i]);
  308. }
  309. }
  310. bool decode(ArgumentDecoder& decoder, RetainPtr<CFDictionaryRef>& result)
  311. {
  312. uint64_t size;
  313. if (!decoder.decode(size))
  314. return false;
  315. RetainPtr<CFMutableDictionaryRef> dictionary = adoptCF(CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks));
  316. for (uint64_t i = 0; i < size; ++i) {
  317. // Try to decode the key name.
  318. RetainPtr<CFStringRef> key;
  319. if (!decode(decoder, key))
  320. return false;
  321. RetainPtr<CFTypeRef> value;
  322. if (!decode(decoder, value))
  323. return false;
  324. CFDictionarySetValue(dictionary.get(), key.get(), value.get());
  325. }
  326. result = adoptCF(dictionary.leakRef());
  327. return true;
  328. }
  329. void encode(ArgumentEncoder& encoder, CFNumberRef number)
  330. {
  331. CFNumberType numberType = CFNumberGetType(number);
  332. Vector<uint8_t> buffer(CFNumberGetByteSize(number));
  333. bool result = CFNumberGetValue(number, numberType, buffer.data());
  334. ASSERT_UNUSED(result, result);
  335. encoder.encodeEnum(numberType);
  336. encoder << CoreIPC::DataReference(buffer);
  337. }
  338. static size_t sizeForNumberType(CFNumberType numberType)
  339. {
  340. switch (numberType) {
  341. case kCFNumberSInt8Type:
  342. return sizeof(SInt8);
  343. case kCFNumberSInt16Type:
  344. return sizeof(SInt16);
  345. case kCFNumberSInt32Type:
  346. return sizeof(SInt32);
  347. case kCFNumberSInt64Type:
  348. return sizeof(SInt64);
  349. case kCFNumberFloat32Type:
  350. return sizeof(Float32);
  351. case kCFNumberFloat64Type:
  352. return sizeof(Float64);
  353. case kCFNumberCharType:
  354. return sizeof(char);
  355. case kCFNumberShortType:
  356. return sizeof(short);
  357. case kCFNumberIntType:
  358. return sizeof(int);
  359. case kCFNumberLongType:
  360. return sizeof(long);
  361. case kCFNumberLongLongType:
  362. return sizeof(long long);
  363. case kCFNumberFloatType:
  364. return sizeof(float);
  365. case kCFNumberDoubleType:
  366. return sizeof(double);
  367. case kCFNumberCFIndexType:
  368. return sizeof(CFIndex);
  369. case kCFNumberNSIntegerType:
  370. #ifdef __LP64__
  371. return sizeof(long);
  372. #else
  373. return sizeof(int);
  374. #endif
  375. case kCFNumberCGFloatType:
  376. #ifdef __LP64__
  377. return sizeof(double);
  378. #else
  379. return sizeof(float);
  380. #endif
  381. }
  382. return 0;
  383. }
  384. bool decode(ArgumentDecoder& decoder, RetainPtr<CFNumberRef>& result)
  385. {
  386. CFNumberType numberType;
  387. if (!decoder.decodeEnum(numberType))
  388. return false;
  389. CoreIPC::DataReference dataReference;
  390. if (!decoder.decode(dataReference))
  391. return false;
  392. size_t neededBufferSize = sizeForNumberType(numberType);
  393. if (!neededBufferSize || dataReference.size() != neededBufferSize)
  394. return false;
  395. ASSERT(dataReference.data());
  396. CFNumberRef number = CFNumberCreate(0, numberType, dataReference.data());
  397. result = adoptCF(number);
  398. return true;
  399. }
  400. void encode(ArgumentEncoder& encoder, CFStringRef string)
  401. {
  402. CFIndex length = CFStringGetLength(string);
  403. CFStringEncoding encoding = CFStringGetFastestEncoding(string);
  404. CFRange range = CFRangeMake(0, length);
  405. CFIndex bufferLength = 0;
  406. CFIndex numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, 0, 0, &bufferLength);
  407. ASSERT(numConvertedBytes == length);
  408. Vector<UInt8, 128> buffer(bufferLength);
  409. numConvertedBytes = CFStringGetBytes(string, range, encoding, 0, false, buffer.data(), buffer.size(), &bufferLength);
  410. ASSERT(numConvertedBytes == length);
  411. encoder.encodeEnum(encoding);
  412. encoder << CoreIPC::DataReference(buffer);
  413. }
  414. bool decode(ArgumentDecoder& decoder, RetainPtr<CFStringRef>& result)
  415. {
  416. CFStringEncoding encoding;
  417. if (!decoder.decodeEnum(encoding))
  418. return false;
  419. if (!CFStringIsEncodingAvailable(encoding))
  420. return false;
  421. CoreIPC::DataReference dataReference;
  422. if (!decoder.decode(dataReference))
  423. return false;
  424. CFStringRef string = CFStringCreateWithBytes(0, dataReference.data(), dataReference.size(), encoding, false);
  425. if (!string)
  426. return false;
  427. result = adoptCF(string);
  428. return true;
  429. }
  430. void encode(ArgumentEncoder& encoder, CFURLRef url)
  431. {
  432. CFURLRef baseURL = CFURLGetBaseURL(url);
  433. encoder << static_cast<bool>(baseURL);
  434. if (baseURL)
  435. encode(encoder, baseURL);
  436. URLCharBuffer urlBytes;
  437. getURLBytes(url, urlBytes);
  438. CoreIPC::DataReference dataReference(reinterpret_cast<const uint8_t*>(urlBytes.data()), urlBytes.size());
  439. encoder << dataReference;
  440. }
  441. bool decode(ArgumentDecoder& decoder, RetainPtr<CFURLRef>& result)
  442. {
  443. RetainPtr<CFURLRef> baseURL;
  444. bool hasBaseURL;
  445. if (!decoder.decode(hasBaseURL))
  446. return false;
  447. if (hasBaseURL) {
  448. if (!decode(decoder, baseURL))
  449. return false;
  450. }
  451. CoreIPC::DataReference urlBytes;
  452. if (!decoder.decode(urlBytes))
  453. return false;
  454. #if PLATFORM(MAC)
  455. // FIXME: Move this to ArgumentCodersCFMac.mm and change this file back to be C++
  456. // instead of Objective-C++.
  457. if (urlBytes.isEmpty()) {
  458. // CFURL can't hold an empty URL, unlike NSURL.
  459. // FIXME: This discards base URL, which seems incorrect.
  460. result = reinterpret_cast<CFURLRef>([NSURL URLWithString:@""]);
  461. return true;
  462. }
  463. #endif
  464. result = createCFURLFromBuffer(reinterpret_cast<const char*>(urlBytes.data()), urlBytes.size(), baseURL.get());
  465. return result;
  466. }
  467. #if USE(SECURITY_FRAMEWORK)
  468. void encode(ArgumentEncoder& encoder, SecCertificateRef certificate)
  469. {
  470. RetainPtr<CFDataRef> data = adoptCF(SecCertificateCopyData(certificate));
  471. encode(encoder, data.get());
  472. }
  473. bool decode(ArgumentDecoder& decoder, RetainPtr<SecCertificateRef>& result)
  474. {
  475. RetainPtr<CFDataRef> data;
  476. if (!decode(decoder, data))
  477. return false;
  478. result = adoptCF(SecCertificateCreateWithData(0, data.get()));
  479. return true;
  480. }
  481. void encode(ArgumentEncoder& encoder, SecKeychainItemRef keychainItem)
  482. {
  483. CFDataRef data;
  484. if (SecKeychainItemCreatePersistentReference(keychainItem, &data) == errSecSuccess) {
  485. encode(encoder, data);
  486. CFRelease(data);
  487. }
  488. }
  489. bool decode(ArgumentDecoder& decoder, RetainPtr<SecKeychainItemRef>& result)
  490. {
  491. RetainPtr<CFDataRef> data;
  492. if (!CoreIPC::decode(decoder, data))
  493. return false;
  494. SecKeychainItemRef item;
  495. if (SecKeychainItemCopyFromPersistentReference(data.get(), &item) != errSecSuccess || !item)
  496. return false;
  497. result = adoptCF(item);
  498. return true;
  499. }
  500. #endif
  501. } // namespace CoreIPC