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