Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / common / mac / attributed_string_coder.mm
blobbcd8b118c5543ee773bab42063fc2d19a2416d61
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.
5 #include "content/common/mac/attributed_string_coder.h"
7 #include <AppKit/AppKit.h>
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"
17 namespace mac {
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;
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];
66 // Data Types //////////////////////////////////////////////////////////////////
68 AttributedStringCoder::EncodedString::EncodedString(base::string16 string)
69     : string_(string) {
72 AttributedStringCoder::EncodedString::EncodedString()
73     : string_() {
76 AttributedStringCoder::EncodedString::~EncodedString() {
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   }
89 AttributedStringCoder::FontAttribute::FontAttribute(FontDescriptor font,
90                                                     gfx::Range range)
91     : font_descriptor_(font),
92       effective_range_(range) {
95 AttributedStringCoder::FontAttribute::FontAttribute()
96     : font_descriptor_(),
97       effective_range_() {
100 AttributedStringCoder::FontAttribute::~FontAttribute() {
103 NSDictionary* AttributedStringCoder::FontAttribute::ToAttributesDictionary(
104     void) const {
105   DCHECK(ShouldEncode());
106   NSFont* font = font_descriptor_.ToNSFont();
107   return [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
110 bool AttributedStringCoder::FontAttribute::ShouldEncode() const {
111   return !font_descriptor_.font_name.empty();
114 }  // namespace mac
116 // IPC ParamTraits specialization //////////////////////////////////////////////
118 namespace IPC {
120 using mac::AttributedStringCoder;
122 void ParamTraits<AttributedStringCoder::EncodedString>::Write(
123     Message* m, const param_type& p) {
124   WriteParam(m, p.string());
125   WriteParam(m, p.attributes());
128 bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
129     const Message* m, PickleIterator* iter, param_type* p) {
130   bool success = true;
132   base::string16 result;
133   success &= ReadParam(m, iter, &result);
134   *p = AttributedStringCoder::EncodedString(result);
136   success &= ReadParam(m, iter, p->attributes());
137   return success;
140 void ParamTraits<AttributedStringCoder::EncodedString>::Log(
141     const param_type& p, std::string* l) {
142   l->append(base::UTF16ToUTF8(p.string()));
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());
151 bool ParamTraits<AttributedStringCoder::FontAttribute>::Read(
152     const Message* m, PickleIterator* iter, param_type* p) {
153   bool success = true;
155   FontDescriptor font;
156   success &= ReadParam(m, iter, &font);
158   gfx::Range range;
159   success &= ReadParam(m, iter, &range);
161   if (success) {
162     *p = AttributedStringCoder::FontAttribute(font, range);
163   }
164   return success;
167 void ParamTraits<AttributedStringCoder::FontAttribute>::Log(
168     const param_type& p, std::string* l) {
171 }  // namespace IPC