| 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_object.h" | |
| 6 | |
| 7 #include "base/logging.h" | |
| 8 #include "base/values.h" | |
| 9 #include "chromeos/dbus/ibus/ibus_text.h" | |
| 10 #include "dbus/message.h" | |
| 11 #include "dbus/values_util.h" | |
| 12 | |
| 13 namespace chromeos { | |
| 14 | |
| 15 /////////////////////////////////////////////////////////////////////////////// | |
| 16 // IBusObjectReader | |
| 17 IBusObjectReader::IBusObjectReader(const std::string& type_name, | |
| 18 dbus::MessageReader* reader) | |
| 19 : type_name_(type_name), | |
| 20 original_reader_(reader), | |
| 21 check_result_(IBUS_OBJECT_NOT_CHECKED) {} | |
| 22 | |
| 23 IBusObjectReader::~IBusObjectReader() { | |
| 24 for (std::map<std::string, base::Value*>::iterator ite = attachments_.begin(); | |
| 25 ite != attachments_.end(); ++ite) | |
| 26 delete ite->second; | |
| 27 } | |
| 28 | |
| 29 bool IBusObjectReader::Init() { | |
| 30 DCHECK(original_reader_); | |
| 31 DCHECK_EQ(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 32 | |
| 33 top_variant_reader_.reset(new dbus::MessageReader(NULL)); | |
| 34 contents_reader_.reset(new dbus::MessageReader(NULL)); | |
| 35 check_result_ = IBUS_OBJECT_INVALID; | |
| 36 | |
| 37 // IBus object has a variant on top-level. | |
| 38 if (!original_reader_->PopVariant(top_variant_reader_.get())) { | |
| 39 LOG(ERROR) << "Invalid object structure[" << type_name_ << "]: " | |
| 40 << "can not find top variant field."; | |
| 41 return false; | |
| 42 } | |
| 43 | |
| 44 // IBus object has struct on second level. | |
| 45 if (!top_variant_reader_->PopStruct(contents_reader_.get())) { | |
| 46 LOG(ERROR) << "Invalid object structure[" << type_name_ << "]: " | |
| 47 << "can not find top struct field."; | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 // IBus object has type key at the first element. | |
| 52 std::string type_name; | |
| 53 if (!contents_reader_->PopString(&type_name)) { | |
| 54 LOG(ERROR) << "Invalid object structure[" << type_name_ << "]: " | |
| 55 << "Can not get type name field."; | |
| 56 return false; | |
| 57 } | |
| 58 | |
| 59 if (type_name != type_name_) { | |
| 60 LOG(ERROR) << "Type check failed: Given variant is not " << type_name_ | |
| 61 << " and actual type is " << type_name << "."; | |
| 62 return false; | |
| 63 } | |
| 64 | |
| 65 dbus::MessageReader attachment_reader(NULL); | |
| 66 | |
| 67 // IBus object has array object at the second element, which is used in | |
| 68 // attaching additional information. | |
| 69 if (!contents_reader_->PopArray(&attachment_reader)) { | |
| 70 LOG(ERROR) << "Invalid object structure[" << type_name_ << "] " | |
| 71 << "can not find attachment array field."; | |
| 72 return false; | |
| 73 } | |
| 74 | |
| 75 while (attachment_reader.HasMoreData()) { | |
| 76 dbus::MessageReader dictionary_reader(NULL); | |
| 77 if (!attachment_reader.PopDictEntry(&dictionary_reader)) { | |
| 78 LOG(ERROR) << "Invalid attachment structure: " | |
| 79 << "The attachment field is array of dictionary entry."; | |
| 80 return false; | |
| 81 } | |
| 82 | |
| 83 std::string key; | |
| 84 if (!dictionary_reader.PopString(&key)) { | |
| 85 LOG(ERROR) << "Invalid attachment structure: " | |
| 86 << "The 1st dictionary entry should be string."; | |
| 87 return false; | |
| 88 } | |
| 89 | |
| 90 if (key.empty()) { | |
| 91 LOG(ERROR) << "Invalid attachment key: key is empty."; | |
| 92 return false; | |
| 93 } | |
| 94 | |
| 95 dbus::MessageReader variant_reader(NULL); | |
| 96 if (!dictionary_reader.PopVariant(&variant_reader)) { | |
| 97 LOG(ERROR) << "Invalid attachment structure: " | |
| 98 << "The 2nd dictionary entry should be variant."; | |
| 99 return false; | |
| 100 } | |
| 101 | |
| 102 dbus::MessageReader sub_variant_reader(NULL); | |
| 103 if (!variant_reader.PopVariant(&sub_variant_reader)) { | |
| 104 LOG(ERROR) << "Invalid attachment structure: " | |
| 105 << "The 2nd variant entry should contain variant."; | |
| 106 return false; | |
| 107 } | |
| 108 | |
| 109 attachments_[key] = dbus::PopDataAsValue(&sub_variant_reader); | |
| 110 } | |
| 111 check_result_ = IBUS_OBJECT_VALID; | |
| 112 return true; | |
| 113 } | |
| 114 | |
| 115 bool IBusObjectReader::InitWithParentReader(dbus::MessageReader* reader) { | |
| 116 original_reader_ = reader; | |
| 117 return Init(); | |
| 118 } | |
| 119 | |
| 120 bool IBusObjectReader::PopString(std::string* out) { | |
| 121 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 122 DCHECK(contents_reader_.get()); | |
| 123 return IsValid() && contents_reader_->PopString(out); | |
| 124 } | |
| 125 | |
| 126 bool IBusObjectReader::PopUint32(uint32* out) { | |
| 127 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 128 DCHECK(contents_reader_.get()); | |
| 129 return IsValid() && contents_reader_->PopUint32(out); | |
| 130 } | |
| 131 | |
| 132 bool IBusObjectReader::PopInt32(int32* out) { | |
| 133 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 134 DCHECK(contents_reader_.get()); | |
| 135 return IsValid() && contents_reader_->PopInt32(out); | |
| 136 } | |
| 137 | |
| 138 bool IBusObjectReader::PopBool(bool* out) { | |
| 139 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 140 DCHECK(contents_reader_.get()); | |
| 141 return IsValid() && contents_reader_->PopBool(out); | |
| 142 } | |
| 143 | |
| 144 bool IBusObjectReader::PopArray(dbus::MessageReader* reader) { | |
| 145 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 146 DCHECK(contents_reader_.get()); | |
| 147 return IsValid() && contents_reader_->PopArray(reader); | |
| 148 } | |
| 149 | |
| 150 bool IBusObjectReader::PopIBusText(IBusText* text) { | |
| 151 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 152 DCHECK(contents_reader_.get()); | |
| 153 return IsValid() && chromeos::PopIBusText(contents_reader_.get(), text); | |
| 154 } | |
| 155 | |
| 156 bool IBusObjectReader::PopStringFromIBusText(std::string* text) { | |
| 157 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 158 DCHECK(contents_reader_.get()); | |
| 159 return IsValid() && chromeos::PopStringFromIBusText( | |
| 160 contents_reader_.get(), text); | |
| 161 } | |
| 162 | |
| 163 const base::Value* IBusObjectReader::GetAttachment(const std::string& key) { | |
| 164 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 165 DCHECK(contents_reader_.get()); | |
| 166 if (!IsValid()) | |
| 167 return NULL; | |
| 168 std::map<std::string, base::Value*>::iterator it = attachments_.find(key); | |
| 169 if (it == attachments_.end()) | |
| 170 return NULL; | |
| 171 return it->second; | |
| 172 } | |
| 173 | |
| 174 bool IBusObjectReader::HasMoreData() { | |
| 175 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 176 DCHECK(contents_reader_.get()); | |
| 177 return IsValid() && contents_reader_->HasMoreData(); | |
| 178 } | |
| 179 | |
| 180 bool IBusObjectReader::PopIBusObject(IBusObjectReader* reader) { | |
| 181 DCHECK(contents_reader_.get()); | |
| 182 if (!IsValid()) | |
| 183 return false; | |
| 184 return reader->InitWithParentReader(contents_reader_.get()); | |
| 185 } | |
| 186 | |
| 187 bool IBusObjectReader::IsValid() const { | |
| 188 DCHECK_NE(IBUS_OBJECT_NOT_CHECKED, check_result_); | |
| 189 return check_result_ == IBUS_OBJECT_VALID; | |
| 190 } | |
| 191 | |
| 192 /////////////////////////////////////////////////////////////////////////////// | |
| 193 // IBusObjectWriter | |
| 194 IBusObjectWriter::IBusObjectWriter(const std::string& type_name, | |
| 195 const std::string& signature, | |
| 196 dbus::MessageWriter* writer) | |
| 197 : type_name_(type_name), | |
| 198 signature_(signature), | |
| 199 original_writer_(writer), | |
| 200 state_(NOT_INITIALZED) { | |
| 201 if (original_writer_) | |
| 202 Init(); | |
| 203 } | |
| 204 | |
| 205 IBusObjectWriter::~IBusObjectWriter() { | |
| 206 } | |
| 207 | |
| 208 void IBusObjectWriter::AppendString(const std::string& input) { | |
| 209 DCHECK_EQ(state_, INITIALIZED); | |
| 210 contents_writer_->AppendString(input); | |
| 211 } | |
| 212 | |
| 213 void IBusObjectWriter::AppendUint32(uint32 input) { | |
| 214 DCHECK_EQ(state_, INITIALIZED); | |
| 215 contents_writer_->AppendUint32(input); | |
| 216 } | |
| 217 | |
| 218 void IBusObjectWriter::AppendInt32(int32 input) { | |
| 219 DCHECK_EQ(state_, INITIALIZED); | |
| 220 contents_writer_->AppendInt32(input); | |
| 221 } | |
| 222 | |
| 223 void IBusObjectWriter::AppendBool(bool input) { | |
| 224 DCHECK_EQ(state_, INITIALIZED); | |
| 225 contents_writer_->AppendBool(input); | |
| 226 } | |
| 227 | |
| 228 void IBusObjectWriter::OpenArray(const std::string& signature, | |
| 229 dbus::MessageWriter* writer) { | |
| 230 DCHECK_EQ(state_, INITIALIZED); | |
| 231 contents_writer_->OpenArray(signature, writer); | |
| 232 } | |
| 233 | |
| 234 void IBusObjectWriter::AppendIBusText(const IBusText& text) { | |
| 235 DCHECK_EQ(state_, INITIALIZED); | |
| 236 chromeos::AppendIBusText(text, contents_writer_.get()); | |
| 237 } | |
| 238 | |
| 239 void IBusObjectWriter::AppendStringAsIBusText(const std::string& text) { | |
| 240 DCHECK_EQ(state_, INITIALIZED); | |
| 241 chromeos::AppendStringAsIBusText(text, contents_writer_.get()); | |
| 242 } | |
| 243 | |
| 244 void IBusObjectWriter::CloseContainer(dbus::MessageWriter* writer) { | |
| 245 DCHECK_EQ(state_, INITIALIZED); | |
| 246 contents_writer_->CloseContainer(writer); | |
| 247 } | |
| 248 | |
| 249 void IBusObjectWriter::AppendIBusObject(IBusObjectWriter* writer) { | |
| 250 DCHECK_EQ(state_, INITIALIZED); | |
| 251 writer->InitWithParentWriter(contents_writer_.get()); | |
| 252 } | |
| 253 | |
| 254 void IBusObjectWriter::Init() { | |
| 255 DCHECK(original_writer_); | |
| 256 DCHECK_EQ(state_, NOT_INITIALZED); | |
| 257 | |
| 258 top_variant_writer_.reset(new dbus::MessageWriter(NULL)); | |
| 259 contents_writer_.reset(new dbus::MessageWriter(NULL)); | |
| 260 attachment_writer_.reset(new dbus::MessageWriter(NULL)); | |
| 261 | |
| 262 const std::string ibus_signature = "(sa{sv}" + signature_ + ")"; | |
| 263 original_writer_->OpenVariant(ibus_signature, top_variant_writer_.get()); | |
| 264 top_variant_writer_->OpenStruct(contents_writer_.get()); | |
| 265 | |
| 266 contents_writer_->AppendString(type_name_); | |
| 267 | |
| 268 contents_writer_->OpenArray("{sv}", attachment_writer_.get()); | |
| 269 state_ = HEADER_OPEN; | |
| 270 } | |
| 271 | |
| 272 void IBusObjectWriter::InitWithParentWriter(dbus::MessageWriter* writer) { | |
| 273 DCHECK_EQ(state_, NOT_INITIALZED) << "Already initialized."; | |
| 274 original_writer_ = writer; | |
| 275 Init(); | |
| 276 } | |
| 277 | |
| 278 void IBusObjectWriter::CloseAll() { | |
| 279 DCHECK(original_writer_); | |
| 280 DCHECK_NE(state_, NOT_INITIALZED); | |
| 281 if (state_ == HEADER_OPEN) | |
| 282 CloseHeader(); | |
| 283 | |
| 284 top_variant_writer_->CloseContainer(contents_writer_.get()); | |
| 285 original_writer_->CloseContainer(top_variant_writer_.get()); | |
| 286 top_variant_writer_.reset(); | |
| 287 contents_writer_.reset(); | |
| 288 } | |
| 289 | |
| 290 void IBusObjectWriter::CloseHeader() { | |
| 291 DCHECK_EQ(state_, HEADER_OPEN) << "Header is already closed."; | |
| 292 contents_writer_->CloseContainer(attachment_writer_.get()); | |
| 293 state_ = INITIALIZED; | |
| 294 } | |
| 295 | |
| 296 bool IBusObjectWriter::AddAttachment(const std::string& key, | |
| 297 const base::Value& value) { | |
| 298 DCHECK_NE(state_, NOT_INITIALZED) << "Do not call before Init();"; | |
| 299 DCHECK_NE(state_, INITIALIZED) << "Do not call after CloseHeader()."; | |
| 300 DCHECK(attachment_writer_.get()); | |
| 301 DCHECK(!key.empty()); | |
| 302 DCHECK(!value.IsType(base::Value::TYPE_NULL)); | |
| 303 | |
| 304 dbus::MessageWriter dict_writer(NULL); | |
| 305 attachment_writer_->OpenDictEntry(&dict_writer); | |
| 306 dict_writer.AppendString(key); | |
| 307 dbus::MessageWriter variant_writer(NULL); | |
| 308 dict_writer.OpenVariant("v", &variant_writer); | |
| 309 | |
| 310 dbus::AppendBasicTypeValueDataAsVariant(&variant_writer, value); | |
| 311 dict_writer.CloseContainer(&variant_writer); | |
| 312 attachment_writer_->CloseContainer(&variant_writer); | |
| 313 return true; | |
| 314 } | |
| 315 | |
| 316 } // namespace chromeos | |
| OLD | NEW |