OLD | NEW |
| (Empty) |
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 "chromeos/dbus/ibus/ibus_text.h" | |
6 | |
7 #include "base/logging.h" | |
8 #include "base/values.h" | |
9 #include "chromeos/dbus/ibus/ibus_object.h" | |
10 #include "dbus/message.h" | |
11 | |
12 namespace chromeos { | |
13 | |
14 namespace { | |
15 const uint32 kAttributeUnderline = 1; // Indicates underline attribute. | |
16 const uint32 kAttributeSelection = 2; // Indicates background attribute. | |
17 const char kAnnotationKey[] = "annotation"; | |
18 const char kDescriptionTitleKey[] = "description_title"; | |
19 const char kDescriptionBodyKey[] = "description_body"; | |
20 | |
21 struct IBusAttribute { | |
22 IBusAttribute() : type(0), value(0), start_index(0), end_index(0) {} | |
23 uint32 type; | |
24 uint32 value; | |
25 uint32 start_index; | |
26 uint32 end_index; | |
27 }; | |
28 | |
29 // Pops a IBusAttribute from |reader|. | |
30 // Returns false if an error occurs. | |
31 bool PopIBusAttribute(dbus::MessageReader* reader, IBusAttribute* attribute) { | |
32 IBusObjectReader ibus_object_reader("IBusAttribute", reader); | |
33 if (!ibus_object_reader.Init()) | |
34 return false; | |
35 | |
36 if (!ibus_object_reader.PopUint32(&attribute->type) || | |
37 !ibus_object_reader.PopUint32(&attribute->value) || | |
38 !ibus_object_reader.PopUint32(&attribute->start_index) || | |
39 !ibus_object_reader.PopUint32(&attribute->end_index)) { | |
40 LOG(ERROR) << "Invalid variant structure[IBusAttribute]: " | |
41 << "IBusAttribute should contain 4 unsigned integers."; | |
42 return false; | |
43 } | |
44 return true; | |
45 } | |
46 | |
47 // Appends a IBusAttribute into |writer|. | |
48 void AppendIBusAttribute(dbus::MessageWriter* writer, | |
49 const IBusAttribute& attribute) { | |
50 IBusObjectWriter ibus_attribute_writer("IBusAttribute", "uuuu", writer); | |
51 ibus_attribute_writer.CloseHeader(); | |
52 ibus_attribute_writer.AppendUint32(attribute.type); | |
53 ibus_attribute_writer.AppendUint32(attribute.value); | |
54 ibus_attribute_writer.AppendUint32(attribute.start_index); | |
55 ibus_attribute_writer.AppendUint32(attribute.end_index); | |
56 ibus_attribute_writer.CloseAll(); | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 void AppendIBusText(const IBusText& ibus_text, dbus::MessageWriter* writer) { | |
62 IBusObjectWriter ibus_text_writer("IBusText", "sv", writer); | |
63 | |
64 if (!ibus_text.annotation().empty()) { | |
65 scoped_ptr<base::Value> annotation( | |
66 base::Value::CreateStringValue(ibus_text.annotation())); | |
67 ibus_text_writer.AddAttachment(kAnnotationKey, *annotation.get()); | |
68 } | |
69 if (!ibus_text.description_title().empty()) { | |
70 scoped_ptr<base::Value> description_title( | |
71 base::Value::CreateStringValue(ibus_text.description_title())); | |
72 ibus_text_writer.AddAttachment(kDescriptionTitleKey, | |
73 *description_title.get()); | |
74 } | |
75 if (!ibus_text.description_body().empty()) { | |
76 scoped_ptr<base::Value> description_body( | |
77 base::Value::CreateStringValue(ibus_text.description_body())); | |
78 ibus_text_writer.AddAttachment(kDescriptionBodyKey, | |
79 *description_body.get()); | |
80 } | |
81 ibus_text_writer.CloseHeader(); | |
82 | |
83 ibus_text_writer.AppendString(ibus_text.text()); | |
84 | |
85 // Start appending IBusAttrList into IBusText | |
86 IBusObjectWriter ibus_attr_list_writer("IBusAttrList", "av", NULL); | |
87 ibus_text_writer.AppendIBusObject(&ibus_attr_list_writer); | |
88 ibus_attr_list_writer.CloseHeader(); | |
89 dbus::MessageWriter attribute_array_writer(NULL); | |
90 ibus_attr_list_writer.OpenArray("v", &attribute_array_writer); | |
91 | |
92 const std::vector<IBusText::UnderlineAttribute>& underline_attributes = | |
93 ibus_text.underline_attributes(); | |
94 for (size_t i = 0; i < underline_attributes.size(); ++i) { | |
95 IBusAttribute attribute; | |
96 attribute.type = kAttributeUnderline; | |
97 attribute.value = static_cast<uint32>(underline_attributes[i].type); | |
98 attribute.start_index = underline_attributes[i].start_index; | |
99 attribute.end_index = underline_attributes[i].end_index; | |
100 AppendIBusAttribute(&attribute_array_writer, attribute); | |
101 } | |
102 | |
103 const std::vector<IBusText::SelectionAttribute>& selection_attributes = | |
104 ibus_text.selection_attributes(); | |
105 for (size_t i = 0; i < selection_attributes.size(); ++i) { | |
106 IBusAttribute attribute; | |
107 attribute.type = kAttributeSelection; | |
108 attribute.value = 0; | |
109 attribute.start_index = selection_attributes[i].start_index; | |
110 attribute.end_index = selection_attributes[i].end_index; | |
111 AppendIBusAttribute(&attribute_array_writer, attribute); | |
112 } | |
113 | |
114 // Close all writers. | |
115 ibus_attr_list_writer.CloseContainer(&attribute_array_writer); | |
116 ibus_attr_list_writer.CloseAll(); | |
117 ibus_text_writer.CloseAll(); | |
118 } | |
119 | |
120 void CHROMEOS_EXPORT AppendStringAsIBusText(const std::string& text, | |
121 dbus::MessageWriter* writer) { | |
122 IBusText ibus_text; | |
123 ibus_text.set_text(text); | |
124 AppendIBusText(ibus_text, writer); | |
125 } | |
126 | |
127 bool PopIBusText(dbus::MessageReader* reader, IBusText* ibus_text) { | |
128 IBusObjectReader ibus_text_reader("IBusText", reader); | |
129 | |
130 if (!ibus_text_reader.Init()) | |
131 return false; | |
132 | |
133 const base::Value* annotation_value = | |
134 ibus_text_reader.GetAttachment(kAnnotationKey); | |
135 if (annotation_value) { | |
136 std::string annotation; | |
137 if (annotation_value->GetAsString(&annotation)) | |
138 ibus_text->set_annotation(annotation); | |
139 } | |
140 | |
141 const base::Value* description_title_value = | |
142 ibus_text_reader.GetAttachment(kDescriptionTitleKey); | |
143 if (description_title_value) { | |
144 std::string description_title; | |
145 if (description_title_value->GetAsString(&description_title)) | |
146 ibus_text->set_description_title(description_title); | |
147 } | |
148 | |
149 const base::Value* description_body_value = | |
150 ibus_text_reader.GetAttachment(kDescriptionBodyKey); | |
151 if (description_body_value) { | |
152 std::string description_body; | |
153 if (description_body_value->GetAsString(&description_body)) | |
154 ibus_text->set_description_body(description_body); | |
155 } | |
156 | |
157 std::string text; | |
158 if (!ibus_text_reader.PopString(&text)) { | |
159 LOG(ERROR) << "Invalid variant structure[IBusText]: " | |
160 << "1st argument should be string."; | |
161 return false; | |
162 } | |
163 | |
164 ibus_text->set_text(text); | |
165 | |
166 // Start reading IBusAttrList object | |
167 IBusObjectReader ibus_attr_list_reader("IBusAttrList", NULL); | |
168 if (!ibus_text_reader.PopIBusObject(&ibus_attr_list_reader)) { | |
169 LOG(ERROR) << "Invalid variant structure[IBusText]: " | |
170 << "2nd argument should be IBusAttrList."; | |
171 return false; | |
172 } | |
173 | |
174 dbus::MessageReader attribute_array_reader(NULL); | |
175 if (!ibus_attr_list_reader.PopArray(&attribute_array_reader)) { | |
176 LOG(ERROR) << "Invalid variant structure[IBusAttrList]: " | |
177 << "1st argument should be array of IBusAttribute."; | |
178 return false; | |
179 } | |
180 | |
181 std::vector<IBusText::UnderlineAttribute>* underline_attributes = | |
182 ibus_text->mutable_underline_attributes(); | |
183 | |
184 std::vector<IBusText::SelectionAttribute>* selection_attributes = | |
185 ibus_text->mutable_selection_attributes(); | |
186 | |
187 while (attribute_array_reader.HasMoreData()) { | |
188 IBusAttribute attribute; | |
189 if (!PopIBusAttribute(&attribute_array_reader, &attribute)) | |
190 return false; | |
191 | |
192 if (attribute.type == kAttributeUnderline) { | |
193 IBusText::UnderlineAttribute underline_attribute; | |
194 underline_attribute.type = | |
195 static_cast<IBusText::IBusTextUnderlineType>(attribute.value); | |
196 underline_attribute.start_index = attribute.start_index; | |
197 underline_attribute.end_index = attribute.end_index; | |
198 underline_attributes->push_back(underline_attribute); | |
199 } else if (attribute.type == kAttributeSelection) { | |
200 IBusText::SelectionAttribute selection_attribute; | |
201 selection_attribute.start_index = attribute.start_index; | |
202 selection_attribute.end_index = attribute.end_index; | |
203 selection_attributes->push_back(selection_attribute); | |
204 } else { | |
205 DVLOG(1) << "Chrome does not support background attribute."; | |
206 } | |
207 } | |
208 | |
209 return true; | |
210 } | |
211 | |
212 bool CHROMEOS_EXPORT PopStringFromIBusText(dbus::MessageReader* reader, | |
213 std::string* text) { | |
214 IBusText ibus_text; | |
215 if (!PopIBusText(reader, &ibus_text)) | |
216 return false; | |
217 *text = ibus_text.text(); | |
218 return true; | |
219 } | |
220 | |
221 /////////////////////////////////////////////////////////////////////////////// | |
222 // IBusText | |
223 IBusText::IBusText() | |
224 : text_("") { | |
225 } | |
226 | |
227 IBusText::~IBusText() { | |
228 } | |
229 | |
230 void IBusText::CopyFrom(const IBusText& obj) { | |
231 text_ = obj.text(); | |
232 annotation_ = obj.annotation(); | |
233 description_title_ = obj.description_title(); | |
234 description_body_ = obj.description_body(); | |
235 underline_attributes_ = obj.underline_attributes(); | |
236 selection_attributes_ = obj.selection_attributes(); | |
237 } | |
238 | |
239 } // namespace chromeos | |
OLD | NEW |