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 |