Home | History | Annotate | Download | only in mac
      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 
     35 using namespace WebCore;
     36 using namespace std;
     37 
     38 namespace CoreIPC {
     39 
     40 enum NSType {
     41     NSAttributedStringType,
     42     NSColorType,
     43     NSDictionaryType,
     44     NSFontType,
     45     NSNumberType,
     46     NSStringType,
     47     Unknown,
     48 };
     49 
     50 static 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 
     71 static 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 
    102 static 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 
    159 void 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 
    192 bool 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 
    229 void encode(ArgumentEncoder* encoder, NSColor *color)
    230 {
    231     encoder->encode(colorFromNSColor(color));
    232 }
    233 
    234 bool 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 
    244 void 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 
    270 bool 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 
    295 void 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 
    301 bool 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 
    313 void encode(ArgumentEncoder* encoder, NSNumber *number)
    314 {
    315     encode(encoder, (CFNumberRef)number);
    316 }
    317 
    318 bool 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 
    328 void encode(ArgumentEncoder* encoder, NSString *string)
    329 {
    330     encode(encoder, (CFStringRef)string);
    331 }
    332 
    333 bool 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