| 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 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 #include "ppapi/shared_impl/var_tracker.h" | 23 #include "ppapi/shared_impl/var_tracker.h" |
| 24 | 24 |
| 25 namespace ppapi { | 25 namespace ppapi { |
| 26 | 26 |
| 27 namespace { | 27 namespace { |
| 28 | 28 |
| 29 // In CreateValueFromVar(), a stack is used to keep track of conversion progress | 29 // In CreateValueFromVar(), a stack is used to keep track of conversion progress |
| 30 // of array and dictionary vars. VarNode represents elements of that stack. | 30 // of array and dictionary vars. VarNode represents elements of that stack. |
| 31 struct VarNode { | 31 struct VarNode { |
| 32 VarNode(const PP_Var& in_var, base::Value* in_value) | 32 VarNode(const PP_Var& in_var, base::Value* in_value) |
| 33 : var(in_var), | 33 : var(in_var), value(in_value), sentinel(false) {} |
| 34 value(in_value), | |
| 35 sentinel(false) { | |
| 36 } | |
| 37 | 34 |
| 38 // This object doesn't hold a reference to it. | 35 // This object doesn't hold a reference to it. |
| 39 PP_Var var; | 36 PP_Var var; |
| 40 // It is not owned by this object. | 37 // It is not owned by this object. |
| 41 base::Value* value; | 38 base::Value* value; |
| 42 // When this is set to true for a node in the stack, it means that we have | 39 // When this is set to true for a node in the stack, it means that we have |
| 43 // finished processing the node itself. However, we keep it in the stack as | 40 // finished processing the node itself. However, we keep it in the stack as |
| 44 // a sentinel. When it becomes the top element of the stack again, we know | 41 // a sentinel. When it becomes the top element of the stack again, we know |
| 45 // that we have processed all the descendants of this node. | 42 // that we have processed all the descendants of this node. |
| 46 bool sentinel; | 43 bool sentinel; |
| 47 }; | 44 }; |
| 48 | 45 |
| 49 // In CreateVarFromValue(), a stack is used to keep track of conversion progress | 46 // In CreateVarFromValue(), a stack is used to keep track of conversion progress |
| 50 // of list and dictionary values. ValueNode represents elements of that stack. | 47 // of list and dictionary values. ValueNode represents elements of that stack. |
| 51 struct ValueNode { | 48 struct ValueNode { |
| 52 ValueNode(const PP_Var& in_var, const base::Value* in_value) | 49 ValueNode(const PP_Var& in_var, const base::Value* in_value) |
| 53 : var(in_var), | 50 : var(in_var), value(in_value) {} |
| 54 value(in_value) { | |
| 55 } | |
| 56 | 51 |
| 57 // This object doesn't hold a reference to it. | 52 // This object doesn't hold a reference to it. |
| 58 PP_Var var; | 53 PP_Var var; |
| 59 // It is not owned by this object. | 54 // It is not owned by this object. |
| 60 const base::Value* value; | 55 const base::Value* value; |
| 61 }; | 56 }; |
| 62 | 57 |
| 63 // Helper function for CreateValueFromVar(). It only looks at |var| but not its | 58 // Helper function for CreateValueFromVar(). It only looks at |var| but not its |
| 64 // descendants. The conversion result is stored in |value|. If |var| is array or | 59 // descendants. The conversion result is stored in |value|. If |var| is array or |
| 65 // dictionary, a new node is pushed onto |state|. | 60 // dictionary, a new node is pushed onto |state|. |
| (...skipping 22 matching lines...) Expand all Loading... |
| 88 return true; | 83 return true; |
| 89 } | 84 } |
| 90 case PP_VARTYPE_STRING: { | 85 case PP_VARTYPE_STRING: { |
| 91 StringVar* string_var = StringVar::FromPPVar(var); | 86 StringVar* string_var = StringVar::FromPPVar(var); |
| 92 if (!string_var) | 87 if (!string_var) |
| 93 return false; | 88 return false; |
| 94 | 89 |
| 95 value->reset(new base::StringValue(string_var->value())); | 90 value->reset(new base::StringValue(string_var->value())); |
| 96 return true; | 91 return true; |
| 97 } | 92 } |
| 98 case PP_VARTYPE_OBJECT: { | 93 case PP_VARTYPE_OBJECT: { return false; } |
| 99 return false; | |
| 100 } | |
| 101 case PP_VARTYPE_ARRAY: { | 94 case PP_VARTYPE_ARRAY: { |
| 102 if (ContainsKey(parent_ids, var.value.as_id)) { | 95 if (ContainsKey(parent_ids, var.value.as_id)) { |
| 103 // A circular reference is found. | 96 // A circular reference is found. |
| 104 return false; | 97 return false; |
| 105 } | 98 } |
| 106 | 99 |
| 107 value->reset(new base::ListValue()); | 100 value->reset(new base::ListValue()); |
| 108 state->push(VarNode(var, value->get())); | 101 state->push(VarNode(var, value->get())); |
| 109 return true; | 102 return true; |
| 110 } | 103 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 124 return false; | 117 return false; |
| 125 | 118 |
| 126 base::BinaryValue* binary_value = | 119 base::BinaryValue* binary_value = |
| 127 base::BinaryValue::CreateWithCopiedBuffer( | 120 base::BinaryValue::CreateWithCopiedBuffer( |
| 128 static_cast<const char*>(array_buffer->Map()), | 121 static_cast<const char*>(array_buffer->Map()), |
| 129 array_buffer->ByteLength()); | 122 array_buffer->ByteLength()); |
| 130 array_buffer->Unmap(); | 123 array_buffer->Unmap(); |
| 131 value->reset(binary_value); | 124 value->reset(binary_value); |
| 132 return true; | 125 return true; |
| 133 } | 126 } |
| 134 case PP_VARTYPE_RESOURCE: { | 127 case PP_VARTYPE_RESOURCE: { return false; } |
| 135 return false; | |
| 136 } | |
| 137 } | 128 } |
| 138 NOTREACHED(); | 129 NOTREACHED(); |
| 139 return false; | 130 return false; |
| 140 } | 131 } |
| 141 | 132 |
| 142 // Helper function for CreateVarFromValue(). It only looks at |value| but not | 133 // Helper function for CreateVarFromValue(). It only looks at |value| but not |
| 143 // its descendants. The conversion result is stored in |var|. If |value| is list | 134 // its descendants. The conversion result is stored in |var|. If |value| is list |
| 144 // or dictionary, a new node is pushed onto |state|. | 135 // or dictionary, a new node is pushed onto |state|. |
| 145 // | 136 // |
| 146 // Returns false on failure. | 137 // Returns false on failure. |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 dict_var->key_value_map().begin(); | 243 dict_var->key_value_map().begin(); |
| 253 iter != dict_var->key_value_map().end(); | 244 iter != dict_var->key_value_map().end(); |
| 254 ++iter) { | 245 ++iter) { |
| 255 // Skip the key-value pair if the value is undefined or null. | 246 // Skip the key-value pair if the value is undefined or null. |
| 256 if (iter->second.get().type == PP_VARTYPE_UNDEFINED || | 247 if (iter->second.get().type == PP_VARTYPE_UNDEFINED || |
| 257 iter->second.get().type == PP_VARTYPE_NULL) { | 248 iter->second.get().type == PP_VARTYPE_NULL) { |
| 258 continue; | 249 continue; |
| 259 } | 250 } |
| 260 | 251 |
| 261 scoped_ptr<base::Value> child_value; | 252 scoped_ptr<base::Value> child_value; |
| 262 if (!CreateValueFromVarHelper(parent_ids, iter->second.get(), | 253 if (!CreateValueFromVarHelper( |
| 263 &child_value, &state)) { | 254 parent_ids, iter->second.get(), &child_value, &state)) { |
| 264 return NULL; | 255 return NULL; |
| 265 } | 256 } |
| 266 | 257 |
| 267 dict_value->SetWithoutPathExpansion(iter->first, child_value.release()); | 258 dict_value->SetWithoutPathExpansion(iter->first, child_value.release()); |
| 268 } | 259 } |
| 269 } else if (top.var.type == PP_VARTYPE_ARRAY) { | 260 } else if (top.var.type == PP_VARTYPE_ARRAY) { |
| 270 parent_ids.insert(top.var.value.as_id); | 261 parent_ids.insert(top.var.value.as_id); |
| 271 top.sentinel = true; | 262 top.sentinel = true; |
| 272 | 263 |
| 273 ArrayVar* array_var = ArrayVar::FromPPVar(top.var); | 264 ArrayVar* array_var = ArrayVar::FromPPVar(top.var); |
| 274 if (!array_var) | 265 if (!array_var) |
| 275 return NULL; | 266 return NULL; |
| 276 | 267 |
| 277 DCHECK(top.value->GetType() == base::Value::TYPE_LIST); | 268 DCHECK(top.value->GetType() == base::Value::TYPE_LIST); |
| 278 base::ListValue* list_value = static_cast<base::ListValue*>(top.value); | 269 base::ListValue* list_value = static_cast<base::ListValue*>(top.value); |
| 279 | 270 |
| 280 for (ArrayVar::ElementVector::const_iterator iter = | 271 for (ArrayVar::ElementVector::const_iterator iter = |
| 281 array_var->elements().begin(); | 272 array_var->elements().begin(); |
| 282 iter != array_var->elements().end(); | 273 iter != array_var->elements().end(); |
| 283 ++iter) { | 274 ++iter) { |
| 284 scoped_ptr<base::Value> child_value; | 275 scoped_ptr<base::Value> child_value; |
| 285 if (!CreateValueFromVarHelper(parent_ids, iter->get(), &child_value, | 276 if (!CreateValueFromVarHelper( |
| 286 &state)) { | 277 parent_ids, iter->get(), &child_value, &state)) { |
| 287 return NULL; | 278 return NULL; |
| 288 } | 279 } |
| 289 | 280 |
| 290 list_value->Append(child_value.release()); | 281 list_value->Append(child_value.release()); |
| 291 } | 282 } |
| 292 } else { | 283 } else { |
| 293 NOTREACHED(); | 284 NOTREACHED(); |
| 294 return NULL; | 285 return NULL; |
| 295 } | 286 } |
| 296 } | 287 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 307 | 298 |
| 308 while (!state.empty()) { | 299 while (!state.empty()) { |
| 309 ValueNode top = state.top(); | 300 ValueNode top = state.top(); |
| 310 state.pop(); | 301 state.pop(); |
| 311 | 302 |
| 312 if (top.value->GetType() == base::Value::TYPE_DICTIONARY) { | 303 if (top.value->GetType() == base::Value::TYPE_DICTIONARY) { |
| 313 const base::DictionaryValue* dict_value = | 304 const base::DictionaryValue* dict_value = |
| 314 static_cast<const base::DictionaryValue*>(top.value); | 305 static_cast<const base::DictionaryValue*>(top.value); |
| 315 DictionaryVar* dict_var = DictionaryVar::FromPPVar(top.var); | 306 DictionaryVar* dict_var = DictionaryVar::FromPPVar(top.var); |
| 316 DCHECK(dict_var); | 307 DCHECK(dict_var); |
| 317 for (base::DictionaryValue::Iterator iter(*dict_value); | 308 for (base::DictionaryValue::Iterator iter(*dict_value); !iter.IsAtEnd(); |
| 318 !iter.IsAtEnd(); | |
| 319 iter.Advance()) { | 309 iter.Advance()) { |
| 320 ScopedPPVar child_var; | 310 ScopedPPVar child_var; |
| 321 if (!CreateVarFromValueHelper(iter.value(), &child_var, &state) || | 311 if (!CreateVarFromValueHelper(iter.value(), &child_var, &state) || |
| 322 !dict_var->SetWithStringKey(iter.key(), child_var.get())) { | 312 !dict_var->SetWithStringKey(iter.key(), child_var.get())) { |
| 323 return PP_MakeUndefined(); | 313 return PP_MakeUndefined(); |
| 324 } | 314 } |
| 325 } | 315 } |
| 326 } else if (top.value->GetType() == base::Value::TYPE_LIST) { | 316 } else if (top.value->GetType() == base::Value::TYPE_LIST) { |
| 327 const base::ListValue* list_value = | 317 const base::ListValue* list_value = |
| 328 static_cast<const base::ListValue*>(top.value); | 318 static_cast<const base::ListValue*>(top.value); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 339 } | 329 } |
| 340 } else { | 330 } else { |
| 341 NOTREACHED(); | 331 NOTREACHED(); |
| 342 return PP_MakeUndefined(); | 332 return PP_MakeUndefined(); |
| 343 } | 333 } |
| 344 } | 334 } |
| 345 | 335 |
| 346 return root_var.Release(); | 336 return root_var.Release(); |
| 347 } | 337 } |
| 348 | 338 |
| 349 base::ListValue* CreateListValueFromVarVector( | 339 base::ListValue* CreateListValueFromVarVector(const std::vector<PP_Var>& vars) { |
| 350 const std::vector<PP_Var>& vars) { | |
| 351 scoped_ptr<base::ListValue> list_value(new base::ListValue()); | 340 scoped_ptr<base::ListValue> list_value(new base::ListValue()); |
| 352 | 341 |
| 353 for (std::vector<PP_Var>::const_iterator iter = vars.begin(); | 342 for (std::vector<PP_Var>::const_iterator iter = vars.begin(); |
| 354 iter != vars.end(); | 343 iter != vars.end(); |
| 355 ++iter) { | 344 ++iter) { |
| 356 base::Value* value = CreateValueFromVar(*iter); | 345 base::Value* value = CreateValueFromVar(*iter); |
| 357 if (!value) | 346 if (!value) |
| 358 return NULL; | 347 return NULL; |
| 359 list_value->Append(value); | 348 list_value->Append(value); |
| 360 } | 349 } |
| 361 return list_value.release(); | 350 return list_value.release(); |
| 362 } | 351 } |
| 363 | 352 |
| 364 bool CreateVarVectorFromListValue(const base::ListValue& list_value, | 353 bool CreateVarVectorFromListValue(const base::ListValue& list_value, |
| 365 std::vector<PP_Var>* vars) { | 354 std::vector<PP_Var>* vars) { |
| 366 if (!vars) | 355 if (!vars) |
| 367 return false; | 356 return false; |
| 368 | 357 |
| 369 std::vector<ScopedPPVar> result; | 358 std::vector<ScopedPPVar> result; |
| 370 result.reserve(list_value.GetSize()); | 359 result.reserve(list_value.GetSize()); |
| 371 for (base::ListValue::const_iterator iter = list_value.begin(); | 360 for (base::ListValue::const_iterator iter = list_value.begin(); |
| 372 iter != list_value.end(); | 361 iter != list_value.end(); |
| 373 ++iter) { | 362 ++iter) { |
| 374 ScopedPPVar child_var(ScopedPPVar::PassRef(), | 363 ScopedPPVar child_var(ScopedPPVar::PassRef(), CreateVarFromValue(**iter)); |
| 375 CreateVarFromValue(**iter)); | |
| 376 if (child_var.get().type == PP_VARTYPE_UNDEFINED) | 364 if (child_var.get().type == PP_VARTYPE_UNDEFINED) |
| 377 return false; | 365 return false; |
| 378 | 366 |
| 379 result.push_back(child_var); | 367 result.push_back(child_var); |
| 380 } | 368 } |
| 381 | 369 |
| 382 vars->clear(); | 370 vars->clear(); |
| 383 vars->reserve(result.size()); | 371 vars->reserve(result.size()); |
| 384 for (std::vector<ScopedPPVar>::iterator iter = result.begin(); | 372 for (std::vector<ScopedPPVar>::iterator iter = result.begin(); |
| 385 iter != result.end(); | 373 iter != result.end(); |
| 386 ++iter) { | 374 ++iter) { |
| 387 vars->push_back(iter->Release()); | 375 vars->push_back(iter->Release()); |
| 388 } | 376 } |
| 389 | 377 |
| 390 return true; | 378 return true; |
| 391 } | 379 } |
| 392 | 380 |
| 393 } // namespace ppapi | 381 } // namespace ppapi |
| 394 | |
| OLD | NEW |