| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ppapi/shared_impl/var_value_conversions.h" | 5 #include "ppapi/shared_impl/var_value_conversions.h" |
| 6 | 6 |
| 7 #include <limits> | 7 #include <limits> |
| 8 #include <set> | 8 #include <set> |
| 9 #include <stack> | 9 #include <stack> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
| 13 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/values.h" | 14 #include "base/values.h" |
| 15 #include "ppapi/c/pp_bool.h" | 15 #include "ppapi/c/pp_bool.h" |
| 16 #include "ppapi/c/pp_stdint.h" | 16 #include "ppapi/c/pp_stdint.h" |
| 17 #include "ppapi/shared_impl/array_var.h" |
| 17 #include "ppapi/shared_impl/dictionary_var.h" | 18 #include "ppapi/shared_impl/dictionary_var.h" |
| 18 #include "ppapi/shared_impl/ppapi_globals.h" | 19 #include "ppapi/shared_impl/ppapi_globals.h" |
| 19 #include "ppapi/shared_impl/scoped_pp_var.h" | 20 #include "ppapi/shared_impl/scoped_pp_var.h" |
| 20 #include "ppapi/shared_impl/var.h" | 21 #include "ppapi/shared_impl/var.h" |
| 21 #include "ppapi/shared_impl/var_tracker.h" | 22 #include "ppapi/shared_impl/var_tracker.h" |
| 22 | 23 |
| 23 namespace ppapi { | 24 namespace ppapi { |
| 24 | 25 |
| 25 namespace { | 26 namespace { |
| 26 | 27 |
| 27 // In CreateValueFromVar(), a stack is used to keep track of conversion progress | 28 // In CreateValueFromVar(), a stack is used to keep track of conversion progress |
| 28 // of array and dictionary vars. VarNodeBase is the base class of stack | 29 // of array and dictionary vars. VarNodeBase is the base class of stack |
| 29 // elements. | 30 // elements. |
| 30 class VarNodeBase : public base::RefCounted<VarNodeBase> { | 31 class VarNodeBase : public base::RefCounted<VarNodeBase> { |
| 31 public: | 32 public: |
| 32 virtual bool IsArrayVar() const { return false; } | 33 virtual bool IsArrayVar() const { return false; } |
| 33 virtual bool IsDictionaryVar() const { return false; } | 34 virtual bool IsDictionaryVar() const { return false; } |
| 34 | 35 |
| 35 protected: | 36 protected: |
| 36 friend class base::RefCounted<VarNodeBase>; | 37 friend class base::RefCounted<VarNodeBase>; |
| 37 | 38 |
| 38 VarNodeBase() {} | 39 VarNodeBase() {} |
| 39 virtual ~VarNodeBase() {} | 40 virtual ~VarNodeBase() {} |
| 40 }; | 41 }; |
| 41 | 42 |
| 43 class ArrayVarNode : public VarNodeBase { |
| 44 public: |
| 45 ArrayVarNode(int64_t in_var_id, const ArrayVar* array_var) |
| 46 : var_id(in_var_id), |
| 47 next(array_var->elements().begin()), |
| 48 end(array_var->elements().end()), |
| 49 list_value(new base::ListValue()) { |
| 50 } |
| 51 |
| 52 virtual bool IsArrayVar() const OVERRIDE { |
| 53 return true; |
| 54 } |
| 55 |
| 56 int64_t var_id; |
| 57 ArrayVar::ElementVector::const_iterator next; |
| 58 ArrayVar::ElementVector::const_iterator end; |
| 59 scoped_ptr<base::ListValue> list_value; |
| 60 |
| 61 private: |
| 62 virtual ~ArrayVarNode() {} |
| 63 }; |
| 64 |
| 42 class DictionaryVarNode : public VarNodeBase { | 65 class DictionaryVarNode : public VarNodeBase { |
| 43 public: | 66 public: |
| 44 DictionaryVarNode(int64_t in_var_id, const DictionaryVar* dict_var) | 67 DictionaryVarNode(int64_t in_var_id, const DictionaryVar* dict_var) |
| 45 : var_id(in_var_id), | 68 : var_id(in_var_id), |
| 46 next(dict_var->key_value_map().begin()), | 69 next(dict_var->key_value_map().begin()), |
| 47 end(dict_var->key_value_map().end()), | 70 end(dict_var->key_value_map().end()), |
| 48 dict_value(new base::DictionaryValue()) { | 71 dict_value(new base::DictionaryValue()) { |
| 49 } | 72 } |
| 50 | 73 |
| 51 virtual bool IsDictionaryVar() const OVERRIDE { | 74 virtual bool IsDictionaryVar() const OVERRIDE { |
| (...skipping 18 matching lines...) Expand all Loading... |
| 70 virtual bool IsListValue() const { return false; } | 93 virtual bool IsListValue() const { return false; } |
| 71 virtual bool IsDictionaryValue() const { return false; } | 94 virtual bool IsDictionaryValue() const { return false; } |
| 72 | 95 |
| 73 protected: | 96 protected: |
| 74 friend class base::RefCounted<ValueNodeBase>; | 97 friend class base::RefCounted<ValueNodeBase>; |
| 75 | 98 |
| 76 ValueNodeBase() {} | 99 ValueNodeBase() {} |
| 77 virtual ~ValueNodeBase() {} | 100 virtual ~ValueNodeBase() {} |
| 78 }; | 101 }; |
| 79 | 102 |
| 103 class ListValueNode : public ValueNodeBase { |
| 104 public: |
| 105 explicit ListValueNode(const base::ListValue& list_value) |
| 106 : next(list_value.begin()), |
| 107 end(list_value.end()), |
| 108 array_var(new ArrayVar()) { |
| 109 array_var->elements().reserve(list_value.GetSize()); |
| 110 } |
| 111 |
| 112 virtual bool IsListValue() const OVERRIDE { |
| 113 return true; |
| 114 } |
| 115 |
| 116 base::ListValue::const_iterator next; |
| 117 base::ListValue::const_iterator end; |
| 118 scoped_refptr<ArrayVar> array_var; |
| 119 |
| 120 private: |
| 121 virtual ~ListValueNode() {} |
| 122 }; |
| 123 |
| 80 class DictionaryValueNode : public ValueNodeBase { | 124 class DictionaryValueNode : public ValueNodeBase { |
| 81 public: | 125 public: |
| 82 explicit DictionaryValueNode(const base::DictionaryValue& dict_value) | 126 explicit DictionaryValueNode(const base::DictionaryValue& dict_value) |
| 83 : iter(dict_value), | 127 : iter(dict_value), |
| 84 dict_var(new DictionaryVar()) { | 128 dict_var(new DictionaryVar()) { |
| 85 } | 129 } |
| 86 | 130 |
| 87 virtual bool IsDictionaryValue() const OVERRIDE { | 131 virtual bool IsDictionaryValue() const OVERRIDE { |
| 88 return true; | 132 return true; |
| 89 } | 133 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 128 if (!string_var) | 172 if (!string_var) |
| 129 return false; | 173 return false; |
| 130 | 174 |
| 131 value->reset(new base::StringValue(string_var->value())); | 175 value->reset(new base::StringValue(string_var->value())); |
| 132 return true; | 176 return true; |
| 133 } | 177 } |
| 134 case PP_VARTYPE_OBJECT: { | 178 case PP_VARTYPE_OBJECT: { |
| 135 return false; | 179 return false; |
| 136 } | 180 } |
| 137 case PP_VARTYPE_ARRAY: { | 181 case PP_VARTYPE_ARRAY: { |
| 138 // TODO(yzshen): Implement it once array var is supported. | 182 if (parent_ids->find(var.value.as_id) != parent_ids->end()) { |
| 139 return false; | 183 // A circular reference is found. |
| 184 return false; |
| 185 } |
| 186 |
| 187 ArrayVar* array_var = ArrayVar::FromPPVar(var); |
| 188 if (!array_var) |
| 189 return false; |
| 190 |
| 191 |
| 192 parent_ids->insert(var.value.as_id); |
| 193 state->push(new ArrayVarNode(var.value.as_id, array_var)); |
| 194 return true; |
| 140 } | 195 } |
| 141 case PP_VARTYPE_DICTIONARY: { | 196 case PP_VARTYPE_DICTIONARY: { |
| 142 if (parent_ids->find(var.value.as_id) != parent_ids->end()) { | 197 if (parent_ids->find(var.value.as_id) != parent_ids->end()) { |
| 143 // A circular reference is found. | 198 // A circular reference is found. |
| 144 return false; | 199 return false; |
| 145 } | 200 } |
| 146 | 201 |
| 147 DictionaryVar* dict_var = DictionaryVar::FromPPVar(var); | 202 DictionaryVar* dict_var = DictionaryVar::FromPPVar(var); |
| 148 if (!dict_var) | 203 if (!dict_var) |
| 149 return false; | 204 return false; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 return true; | 289 return true; |
| 235 } | 290 } |
| 236 return false; | 291 return false; |
| 237 } | 292 } |
| 238 case base::Value::TYPE_DICTIONARY: { | 293 case base::Value::TYPE_DICTIONARY: { |
| 239 state->push(new DictionaryValueNode( | 294 state->push(new DictionaryValueNode( |
| 240 static_cast<const base::DictionaryValue&>(value))); | 295 static_cast<const base::DictionaryValue&>(value))); |
| 241 return true; | 296 return true; |
| 242 } | 297 } |
| 243 case base::Value::TYPE_LIST: { | 298 case base::Value::TYPE_LIST: { |
| 244 // TODO(yzshen): Add support once array var is supported. | 299 state->push(new ListValueNode( |
| 245 return false; | 300 static_cast<const base::ListValue&>(value))); |
| 301 return true; |
| 246 } | 302 } |
| 247 } | 303 } |
| 248 NOTREACHED(); | 304 NOTREACHED(); |
| 249 return false; | 305 return false; |
| 250 } | 306 } |
| 251 | 307 |
| 252 } // namespace | 308 } // namespace |
| 253 | 309 |
| 254 base::Value* CreateValueFromVar(const PP_Var& var) { | 310 base::Value* CreateValueFromVar(const PP_Var& var) { |
| 255 // Used to detect circular references. | 311 // Used to detect circular references. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 280 top->current_key = top->next->first; | 336 top->current_key = top->next->first; |
| 281 current_var = top->next->second.get(); | 337 current_var = top->next->second.get(); |
| 282 ++top->next; | 338 ++top->next; |
| 283 | 339 |
| 284 // Ignore the key-value pair if the value is undefined. | 340 // Ignore the key-value pair if the value is undefined. |
| 285 if (current_var.type == PP_VARTYPE_UNDEFINED) { | 341 if (current_var.type == PP_VARTYPE_UNDEFINED) { |
| 286 top->current_key.clear(); | 342 top->current_key.clear(); |
| 287 continue; | 343 continue; |
| 288 } | 344 } |
| 289 } | 345 } |
| 346 } else if (state.top()->IsArrayVar()) { |
| 347 scoped_refptr<ArrayVarNode> top( |
| 348 static_cast<ArrayVarNode*>(state.top().get())); |
| 349 |
| 350 if (current_value.get()) |
| 351 top->list_value->Append(current_value.release()); |
| 352 |
| 353 if (top->next == top->end) { |
| 354 current_value.reset(top->list_value.release()); |
| 355 parent_ids.erase(top->var_id); |
| 356 state.pop(); |
| 357 continue; |
| 358 } else { |
| 359 current_var = top->next->get(); |
| 360 ++top->next; |
| 361 } |
| 290 } else { | 362 } else { |
| 291 NOTREACHED(); | 363 NOTREACHED(); |
| 292 return NULL; | 364 return NULL; |
| 293 } | 365 } |
| 294 | 366 |
| 295 DCHECK(!current_value.get()); | 367 DCHECK(!current_value.get()); |
| 296 if (!CreateValueFromVarHelper(current_var, ¤t_value, &parent_ids, | 368 if (!CreateValueFromVarHelper(current_var, ¤t_value, &parent_ids, |
| 297 &state)) { | 369 &state)) { |
| 298 return NULL; | 370 return NULL; |
| 299 } | 371 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 326 if (top->iter.IsAtEnd()) { | 398 if (top->iter.IsAtEnd()) { |
| 327 current_var = ScopedPPVar(ScopedPPVar::PassRef(), | 399 current_var = ScopedPPVar(ScopedPPVar::PassRef(), |
| 328 top->dict_var->GetPPVar()); | 400 top->dict_var->GetPPVar()); |
| 329 state.pop(); | 401 state.pop(); |
| 330 continue; | 402 continue; |
| 331 } else { | 403 } else { |
| 332 top->current_key = top->iter.key(); | 404 top->current_key = top->iter.key(); |
| 333 current_value = &top->iter.value(); | 405 current_value = &top->iter.value(); |
| 334 top->iter.Advance(); | 406 top->iter.Advance(); |
| 335 } | 407 } |
| 408 } else if (state.top()->IsListValue()) { |
| 409 scoped_refptr<ListValueNode> top( |
| 410 static_cast<ListValueNode*>(state.top().get())); |
| 411 |
| 412 if (current_var.get().type != PP_VARTYPE_UNDEFINED) |
| 413 top->array_var->elements().push_back(current_var); |
| 414 current_var = PP_MakeUndefined(); |
| 415 if (top->next == top->end) { |
| 416 current_var = ScopedPPVar(ScopedPPVar::PassRef(), |
| 417 top->array_var->GetPPVar()); |
| 418 state.pop(); |
| 419 continue; |
| 420 } else { |
| 421 current_value = *top->next; |
| 422 ++top->next; |
| 423 } |
| 336 } else { | 424 } else { |
| 337 NOTREACHED(); | 425 NOTREACHED(); |
| 338 return PP_MakeUndefined(); | 426 return PP_MakeUndefined(); |
| 339 } | 427 } |
| 340 | 428 |
| 341 DCHECK(current_var.get().type == PP_VARTYPE_UNDEFINED); | 429 DCHECK(current_var.get().type == PP_VARTYPE_UNDEFINED); |
| 342 if (!CreateVarFromValueHelper(*current_value, ¤t_var, &state)) | 430 if (!CreateVarFromValueHelper(*current_value, ¤t_var, &state)) |
| 343 return PP_MakeUndefined(); | 431 return PP_MakeUndefined(); |
| 344 }; | 432 }; |
| 345 | 433 |
| 346 return current_var.Release(); | 434 return current_var.Release(); |
| 347 } | 435 } |
| 348 } // namespace ppapi | 436 } // namespace ppapi |
| 349 | 437 |
| OLD | NEW |