1/* 2 * Copyright (C) 2011 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#import "config.h" 27#import "ArgumentCodersMac.h" 28 29#import "ArgumentCodersCF.h" 30#import "ArgumentDecoder.h" 31#import "ArgumentEncoder.h" 32#import "WebCoreArgumentCoders.h" 33#import <WebCore/ColorMac.h> 34 35using namespace WebCore; 36using namespace std; 37 38namespace CoreIPC { 39 40enum NSType { 41 NSAttributedStringType, 42 NSColorType, 43 NSDictionaryType, 44 NSFontType, 45 NSNumberType, 46 NSStringType, 47 Unknown, 48}; 49 50static NSType typeFromObject(id object) 51{ 52 ASSERT(object); 53 54 if ([object isKindOfClass:[NSAttributedString class]]) 55 return NSAttributedStringType; 56 if ([object isKindOfClass:[NSColor class]]) 57 return NSColorType; 58 if ([object isKindOfClass:[NSDictionary class]]) 59 return NSDictionaryType; 60 if ([object isKindOfClass:[NSFont class]]) 61 return NSFontType; 62 if ([object isKindOfClass:[NSNumber class]]) 63 return NSNumberType; 64 if ([object isKindOfClass:[NSString class]]) 65 return NSStringType; 66 67 ASSERT_NOT_REACHED(); 68 return Unknown; 69} 70 71static void encode(ArgumentEncoder* encoder, id object) 72{ 73 NSType type = typeFromObject(object); 74 encoder->encodeEnum(type); 75 76 switch (type) { 77 case NSAttributedStringType: 78 encode(encoder, static_cast<NSAttributedString *>(object)); 79 return; 80 case NSColorType: 81 encode(encoder, static_cast<NSColor *>(object)); 82 return; 83 case NSDictionaryType: 84 encode(encoder, static_cast<NSDictionary *>(object)); 85 return; 86 case NSFontType: 87 encode(encoder, static_cast<NSFont *>(object)); 88 return; 89 case NSNumberType: 90 encode(encoder, static_cast<NSNumber *>(object)); 91 return; 92 case NSStringType: 93 encode(encoder, static_cast<NSString *>(object)); 94 return; 95 case Unknown: 96 break; 97 } 98 99 ASSERT_NOT_REACHED(); 100} 101 102static bool decode(ArgumentDecoder* decoder, RetainPtr<id>& result) 103{ 104 NSType type; 105 if (!decoder->decodeEnum(type)) 106 return false; 107 108 switch (type) { 109 case NSAttributedStringType: { 110 RetainPtr<NSAttributedString> string; 111 if (!decode(decoder, string)) 112 return false; 113 result = string; 114 return true; 115 } 116 case NSColorType: { 117 RetainPtr<NSColor> color; 118 if (!decode(decoder, color)) 119 return false; 120 result = color; 121 return true; 122 } 123 case NSDictionaryType: { 124 RetainPtr<NSDictionary> dictionary; 125 if (!decode(decoder, dictionary)) 126 return false; 127 result = dictionary; 128 return true; 129 } 130 case NSFontType: { 131 RetainPtr<NSFont> font; 132 if (!decode(decoder, font)) 133 return false; 134 result = font; 135 return true; 136 } 137 case NSNumberType: { 138 RetainPtr<NSNumber> number; 139 if (!decode(decoder, number)) 140 return false; 141 result = number; 142 return true; 143 } 144 case NSStringType: { 145 RetainPtr<NSString> string; 146 if (!decode(decoder, string)) 147 return false; 148 result = string; 149 return true; 150 } 151 case Unknown: 152 ASSERT_NOT_REACHED(); 153 return false; 154 } 155 156 return false; 157} 158 159void encode(ArgumentEncoder* encoder, NSAttributedString *string) 160{ 161 // Even though NSAttributedString is toll free bridged with CFAttributedStringRef, attributes' values may be not, so we should stay within this file's code. 162 163 NSString *plainString = [string string]; 164 NSUInteger length = [plainString length]; 165 CoreIPC::encode(encoder, plainString); 166 167 Vector<pair<NSRange, RetainPtr<NSDictionary> > > ranges; 168 169 NSUInteger position = 0; 170 while (position < length) { 171 // Collect ranges in a vector, becasue the total count should be encoded first. 172 NSRange effectiveRange; 173 RetainPtr<NSDictionary> attributesAtIndex = [string attributesAtIndex:position effectiveRange:&effectiveRange]; 174 ASSERT(effectiveRange.location == position); 175 ASSERT(effectiveRange.length); 176 ASSERT(NSMaxRange(effectiveRange) <= length); 177 178 ranges.append(make_pair(effectiveRange, attributesAtIndex)); 179 180 position = NSMaxRange(effectiveRange); 181 } 182 183 encoder->encodeUInt64(ranges.size()); 184 185 for (size_t i = 0; i < ranges.size(); ++i) { 186 encoder->encodeUInt64(ranges[i].first.location); 187 encoder->encodeUInt64(ranges[i].first.length); 188 CoreIPC::encode(encoder, ranges[i].second.get()); 189 } 190} 191 192bool decode(ArgumentDecoder* decoder, RetainPtr<NSAttributedString>& result) 193{ 194 RetainPtr<NSString> plainString; 195 if (!CoreIPC::decode(decoder, plainString)) 196 return false; 197 198 NSUInteger stringLength = [plainString.get() length]; 199 200 RetainPtr<NSMutableAttributedString> resultString(AdoptNS, [[NSMutableAttributedString alloc] initWithString:plainString.get()]); 201 202 uint64_t rangeCount; 203 if (!decoder->decode(rangeCount)) 204 return false; 205 206 while (rangeCount--) { 207 uint64_t rangeLocation; 208 uint64_t rangeLength; 209 RetainPtr<NSDictionary> attributes; 210 if (!decoder->decode(rangeLocation)) 211 return false; 212 if (!decoder->decode(rangeLength)) 213 return false; 214 215 ASSERT(rangeLocation + rangeLength > rangeLocation); 216 ASSERT(rangeLocation + rangeLength <= stringLength); 217 if (rangeLocation + rangeLength <= rangeLocation || rangeLocation + rangeLength > stringLength) 218 return false; 219 220 if (!CoreIPC::decode(decoder, attributes)) 221 return false; 222 [resultString.get() addAttributes:attributes.get() range:NSMakeRange(rangeLocation, rangeLength)]; 223 } 224 225 result.adoptCF(resultString.leakRef()); 226 return true; 227} 228 229void encode(ArgumentEncoder* encoder, NSColor *color) 230{ 231 encoder->encode(colorFromNSColor(color)); 232} 233 234bool decode(ArgumentDecoder* decoder, RetainPtr<NSColor>& result) 235{ 236 Color color; 237 if (!decoder->decode(color)) 238 return false; 239 240 result = nsColor(color); 241 return true; 242} 243 244void encode(ArgumentEncoder* encoder, NSDictionary *dictionary) 245{ 246 // Even though NSDictionary is toll free bridged with CFDictionaryRef, values may be not, so we should stay within this file's code. 247 248 NSUInteger size = [dictionary count]; 249 NSArray *keys = [dictionary allKeys]; 250 NSArray *values = [dictionary allValues]; 251 252 encoder->encodeUInt64(size); 253 254 for (NSUInteger i = 0; i < size; ++i) { 255 id key = [keys objectAtIndex:i]; 256 id value = [values objectAtIndex:i]; 257 ASSERT(key); 258 ASSERT([key isKindOfClass:[NSString class]]); 259 ASSERT(value); 260 261 // Ignore values we don't recognize. 262 if (typeFromObject(value) == Unknown) 263 continue; 264 265 encode(encoder, (NSString *)key); 266 encode(encoder, value); 267 } 268} 269 270bool decode(ArgumentDecoder* decoder, RetainPtr<NSDictionary>& result) 271{ 272 uint64_t size; 273 if (!decoder->decodeUInt64(size)) 274 return false; 275 276 RetainPtr<NSMutableDictionary> dictionary(AdoptNS, [[NSMutableDictionary alloc] initWithCapacity:size]); 277 for (uint64_t i = 0; i < size; ++i) { 278 // Try to decode the key name. 279 RetainPtr<NSString> key; 280 if (!decode(decoder, key)) 281 return false; 282 283 RetainPtr<id> value; 284 if (!decode(decoder, value)) 285 return false; 286 287 [dictionary.get() setObject:value.get() forKey:key.get()]; 288 } 289 290 result.adoptCF(dictionary.leakRef()); 291 return true; 292} 293 294 295void encode(ArgumentEncoder* encoder, NSFont *font) 296{ 297 // NSFont could use CTFontRef code if we had it in ArgumentCodersCF. 298 encode(encoder, [[font fontDescriptor] fontAttributes]); 299} 300 301bool decode(ArgumentDecoder* decoder, RetainPtr<NSFont>& result) 302{ 303 RetainPtr<NSDictionary> fontAttributes; 304 if (!decode(decoder, fontAttributes)) 305 return false; 306 307 NSFontDescriptor *fontDescriptor = [NSFontDescriptor fontDescriptorWithFontAttributes:fontAttributes.get()]; 308 result = [NSFont fontWithDescriptor:fontDescriptor size:0]; 309 310 return true; 311} 312 313void encode(ArgumentEncoder* encoder, NSNumber *number) 314{ 315 encode(encoder, (CFNumberRef)number); 316} 317 318bool decode(ArgumentDecoder* decoder, RetainPtr<NSNumber>& result) 319{ 320 RetainPtr<CFNumberRef> number; 321 if (!decode(decoder, number)) 322 return false; 323 324 result.adoptCF((NSNumber *)number.leakRef()); 325 return true; 326} 327 328void encode(ArgumentEncoder* encoder, NSString *string) 329{ 330 encode(encoder, (CFStringRef)string); 331} 332 333bool decode(ArgumentDecoder* decoder, RetainPtr<NSString>& result) 334{ 335 RetainPtr<CFStringRef> string; 336 if (!decode(decoder, string)) 337 return false; 338 339 result.adoptCF((NSString *)string.leakRef()); 340 return true; 341} 342 343} 344