Home | History | Annotate | Download | only in mac
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/common/mac/attributed_string_coder.h"
      6 
      7 #include <AppKit/AppKit.h>
      8 
      9 #include "base/logging.h"
     10 #include "base/mac/scoped_nsobject.h"
     11 #include "base/strings/sys_string_conversions.h"
     12 #include "base/strings/utf_string_conversions.h"
     13 #include "content/common/view_messages.h"
     14 #include "content/public/common/common_param_traits.h"
     15 #include "ipc/ipc_message_utils.h"
     16 
     17 namespace mac {
     18 
     19 // static
     20 const AttributedStringCoder::EncodedString* AttributedStringCoder::Encode(
     21     NSAttributedString* str) {
     22   // Create the return value.
     23   EncodedString* encoded_string =
     24       new EncodedString(base::SysNSStringToUTF16([str string]));
     25   // Iterate over all the attributes in the string.
     26   NSUInteger length = [str length];
     27   for (NSUInteger i = 0; i < length; ) {
     28     NSRange effective_range;
     29     NSDictionary* ns_attributes = [str attributesAtIndex:i
     30                                           effectiveRange:&effective_range];
     31     // Convert the attributes to IPC-friendly types.
     32     FontAttribute attrs(ns_attributes, gfx::Range(effective_range));
     33     // Only encode the attributes if the filtered set contains font information.
     34     if (attrs.ShouldEncode()) {
     35       encoded_string->attributes()->push_back(attrs);
     36     }
     37     // Advance the iterator to the position outside of the effective range.
     38     i = NSMaxRange(effective_range);
     39   }
     40   return encoded_string;
     41 }
     42 
     43 // static
     44 NSAttributedString* AttributedStringCoder::Decode(
     45     const AttributedStringCoder::EncodedString* str) {
     46   // Create the return value.
     47   NSString* plain_text = base::SysUTF16ToNSString(str->string());
     48   base::scoped_nsobject<NSMutableAttributedString> decoded_string(
     49       [[NSMutableAttributedString alloc] initWithString:plain_text]);
     50   // Iterate over all the encoded attributes, attaching each to the string.
     51   const std::vector<FontAttribute> attributes = str->attributes();
     52   for (std::vector<FontAttribute>::const_iterator it = attributes.begin();
     53        it != attributes.end(); ++it) {
     54     // Protect against ranges that are outside the range of the string.
     55     const gfx::Range& range = it->effective_range();
     56     if (range.GetMin() > [plain_text length] ||
     57         range.GetMax() > [plain_text length]) {
     58       continue;
     59     }
     60     [decoded_string addAttributes:it->ToAttributesDictionary()
     61                             range:range.ToNSRange()];
     62   }
     63   return [decoded_string.release() autorelease];
     64 }
     65 
     66 // Data Types //////////////////////////////////////////////////////////////////
     67 
     68 AttributedStringCoder::EncodedString::EncodedString(base::string16 string)
     69     : string_(string) {
     70 }
     71 
     72 AttributedStringCoder::EncodedString::EncodedString()
     73     : string_() {
     74 }
     75 
     76 AttributedStringCoder::EncodedString::~EncodedString() {
     77 }
     78 
     79 AttributedStringCoder::FontAttribute::FontAttribute(NSDictionary* dict,
     80                                                     gfx::Range effective_range)
     81     : font_descriptor_(),
     82       effective_range_(effective_range) {
     83   NSFont* font = [dict objectForKey:NSFontAttributeName];
     84   if (font) {
     85     font_descriptor_ = FontDescriptor(font);
     86   }
     87 }
     88 
     89 AttributedStringCoder::FontAttribute::FontAttribute(FontDescriptor font,
     90                                                     gfx::Range range)
     91     : font_descriptor_(font),
     92       effective_range_(range) {
     93 }
     94 
     95 AttributedStringCoder::FontAttribute::FontAttribute()
     96     : font_descriptor_(),
     97       effective_range_() {
     98 }
     99 
    100 AttributedStringCoder::FontAttribute::~FontAttribute() {
    101 }
    102 
    103 NSDictionary* AttributedStringCoder::FontAttribute::ToAttributesDictionary(
    104     void) const {
    105   DCHECK(ShouldEncode());
    106   NSFont* font = font_descriptor_.ToNSFont();
    107   return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
    108 }
    109 
    110 bool AttributedStringCoder::FontAttribute::ShouldEncode() const {
    111   return !font_descriptor_.font_name.empty();
    112 }
    113 
    114 }  // namespace mac
    115 
    116 // IPC ParamTraits specialization //////////////////////////////////////////////
    117 
    118 namespace IPC {
    119 
    120 using mac::AttributedStringCoder;
    121 
    122 void ParamTraits<AttributedStringCoder::EncodedString>::Write(
    123     Message* m, const param_type& p) {
    124   WriteParam(m, p.string());
    125   WriteParam(m, p.attributes());
    126 }
    127 
    128 bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
    129     const Message* m, PickleIterator* iter, param_type* p) {
    130   bool success = true;
    131 
    132   base::string16 result;
    133   success &= ReadParam(m, iter, &result);
    134   *p = AttributedStringCoder::EncodedString(result);
    135 
    136   success &= ReadParam(m, iter, p->attributes());
    137   return success;
    138 }
    139 
    140 void ParamTraits<AttributedStringCoder::EncodedString>::Log(
    141     const param_type& p, std::string* l) {
    142   l->append(base::UTF16ToUTF8(p.string()));
    143 }
    144 
    145 void ParamTraits<AttributedStringCoder::FontAttribute>::Write(
    146     Message* m, const param_type& p) {
    147   WriteParam(m, p.font_descriptor());
    148   WriteParam(m, p.effective_range());
    149 }
    150 
    151 bool ParamTraits<AttributedStringCoder::FontAttribute>::Read(
    152     const Message* m, PickleIterator* iter, param_type* p) {
    153   bool success = true;
    154 
    155   FontDescriptor font;
    156   success &= ReadParam(m, iter, &font);
    157 
    158   gfx::Range range;
    159   success &= ReadParam(m, iter, &range);
    160 
    161   if (success) {
    162     *p = AttributedStringCoder::FontAttribute(font, range);
    163   }
    164   return success;
    165 }
    166 
    167 void ParamTraits<AttributedStringCoder::FontAttribute>::Log(
    168     const param_type& p, std::string* l) {
    169 }
    170 
    171 }  // namespace IPC
    172