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(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