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 "content/renderer/pepper/v8_var_converter.h" | 5 #include "content/renderer/pepper/v8_var_converter.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <stack> | 8 #include <stack> |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 26 matching lines...) Expand all Loading... |
37 | 37 |
38 template <class T> | 38 template <class T> |
39 struct StackEntry { | 39 struct StackEntry { |
40 StackEntry(T v) : val(v), sentinel(false) {} | 40 StackEntry(T v) : val(v), sentinel(false) {} |
41 T val; | 41 T val; |
42 // Used to track parent nodes on the stack while traversing the graph. | 42 // Used to track parent nodes on the stack while traversing the graph. |
43 bool sentinel; | 43 bool sentinel; |
44 }; | 44 }; |
45 | 45 |
46 struct HashedHandle { | 46 struct HashedHandle { |
47 HashedHandle(v8::Handle<v8::Object> h) : handle(h) {} | 47 HashedHandle(v8::Local<v8::Object> h) : handle(h) {} |
48 size_t hash() const { return handle->GetIdentityHash(); } | 48 size_t hash() const { return handle->GetIdentityHash(); } |
49 bool operator==(const HashedHandle& h) const { return handle == h.handle; } | 49 bool operator==(const HashedHandle& h) const { return handle == h.handle; } |
50 v8::Handle<v8::Object> handle; | 50 v8::Local<v8::Object> handle; |
51 }; | 51 }; |
52 | 52 |
53 } // namespace | 53 } // namespace |
54 | 54 |
55 namespace BASE_HASH_NAMESPACE { | 55 namespace BASE_HASH_NAMESPACE { |
56 template <> | 56 template <> |
57 struct hash<HashedHandle> { | 57 struct hash<HashedHandle> { |
58 size_t operator()(const HashedHandle& handle) const { return handle.hash(); } | 58 size_t operator()(const HashedHandle& handle) const { return handle.hash(); } |
59 }; | 59 }; |
60 } // namespace BASE_HASH_NAMESPACE | 60 } // namespace BASE_HASH_NAMESPACE |
61 | 61 |
62 namespace content { | 62 namespace content { |
63 | 63 |
64 namespace { | 64 namespace { |
65 | 65 |
66 // Maps PP_Var IDs to the V8 value handle they correspond to. | 66 // Maps PP_Var IDs to the V8 value handle they correspond to. |
67 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; | 67 typedef base::hash_map<int64_t, v8::Local<v8::Value> > VarHandleMap; |
68 typedef base::hash_set<int64_t> ParentVarSet; | 68 typedef base::hash_set<int64_t> ParentVarSet; |
69 | 69 |
70 // Maps V8 value handles to the PP_Var they correspond to. | 70 // Maps V8 value handles to the PP_Var they correspond to. |
71 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap; | 71 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap; |
72 typedef base::hash_set<HashedHandle> ParentHandleSet; | 72 typedef base::hash_set<HashedHandle> ParentHandleSet; |
73 | 73 |
74 // Returns a V8 value which corresponds to a given PP_Var. If |var| is a | 74 // Returns a V8 value which corresponds to a given PP_Var. If |var| is a |
75 // reference counted PP_Var type, and it exists in |visited_ids|, the V8 value | 75 // reference counted PP_Var type, and it exists in |visited_ids|, the V8 value |
76 // associated with it in the map will be returned, otherwise a new V8 value will | 76 // associated with it in the map will be returned, otherwise a new V8 value will |
77 // be created and added to the map. |did_create| indicates whether a new v8 | 77 // be created and added to the map. |did_create| indicates whether a new v8 |
78 // value was created as a result of calling the function. | 78 // value was created as a result of calling the function. |
79 bool GetOrCreateV8Value(v8::Handle<v8::Context> context, | 79 bool GetOrCreateV8Value(v8::Local<v8::Context> context, |
80 const PP_Var& var, | 80 const PP_Var& var, |
81 V8VarConverter::AllowObjectVars object_vars_allowed, | 81 V8VarConverter::AllowObjectVars object_vars_allowed, |
82 v8::Handle<v8::Value>* result, | 82 v8::Local<v8::Value>* result, |
83 bool* did_create, | 83 bool* did_create, |
84 VarHandleMap* visited_ids, | 84 VarHandleMap* visited_ids, |
85 ParentVarSet* parent_ids, | 85 ParentVarSet* parent_ids, |
86 ResourceConverter* resource_converter) { | 86 ResourceConverter* resource_converter) { |
87 v8::Isolate* isolate = context->GetIsolate(); | 87 v8::Isolate* isolate = context->GetIsolate(); |
88 *did_create = false; | 88 *did_create = false; |
89 | 89 |
90 if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { | 90 if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) { |
91 if (parent_ids->count(var.value.as_id) != 0) | 91 if (parent_ids->count(var.value.as_id) != 0) |
92 return false; | 92 return false; |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) | 180 if (ppapi::VarTracker::IsVarTypeRefcounted(var.type)) |
181 (*visited_ids)[var.value.as_id] = *result; | 181 (*visited_ids)[var.value.as_id] = *result; |
182 return true; | 182 return true; |
183 } | 183 } |
184 | 184 |
185 // For a given V8 value handle, this returns a PP_Var which corresponds to it. | 185 // For a given V8 value handle, this returns a PP_Var which corresponds to it. |
186 // If the handle already exists in |visited_handles|, the PP_Var associated with | 186 // If the handle already exists in |visited_handles|, the PP_Var associated with |
187 // it will be returned, otherwise a new V8 value will be created and added to | 187 // it will be returned, otherwise a new V8 value will be created and added to |
188 // the map. |did_create| indicates if a new PP_Var was created as a result of | 188 // the map. |did_create| indicates if a new PP_Var was created as a result of |
189 // calling the function. | 189 // calling the function. |
190 bool GetOrCreateVar(v8::Handle<v8::Value> val, | 190 bool GetOrCreateVar(v8::Local<v8::Value> val, |
191 v8::Handle<v8::Context> context, | 191 v8::Local<v8::Context> context, |
192 PP_Instance instance, | 192 PP_Instance instance, |
193 V8VarConverter::AllowObjectVars object_vars_allowed, | 193 V8VarConverter::AllowObjectVars object_vars_allowed, |
194 PP_Var* result, | 194 PP_Var* result, |
195 bool* did_create, | 195 bool* did_create, |
196 HandleVarMap* visited_handles, | 196 HandleVarMap* visited_handles, |
197 ParentHandleSet* parent_handles, | 197 ParentHandleSet* parent_handles, |
198 ResourceConverter* resource_converter) { | 198 ResourceConverter* resource_converter) { |
199 CHECK(!val.IsEmpty()); | 199 CHECK(!val.IsEmpty()); |
200 *did_create = false; | 200 *did_create = false; |
201 | 201 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 // 3) If the object is an array, return an ArrayVar. | 237 // 3) If the object is an array, return an ArrayVar. |
238 // 4) If the object can be converted to a resource, return the ResourceVar. | 238 // 4) If the object can be converted to a resource, return the ResourceVar. |
239 // 5) Otherwise return a DictionaryVar. | 239 // 5) Otherwise return a DictionaryVar. |
240 scoped_ptr<blink::WebArrayBuffer> web_array_buffer( | 240 scoped_ptr<blink::WebArrayBuffer> web_array_buffer( |
241 blink::WebArrayBufferConverter::createFromV8Value(val, isolate)); | 241 blink::WebArrayBufferConverter::createFromV8Value(val, isolate)); |
242 if (web_array_buffer.get()) { | 242 if (web_array_buffer.get()) { |
243 scoped_refptr<HostArrayBufferVar> buffer_var( | 243 scoped_refptr<HostArrayBufferVar> buffer_var( |
244 new HostArrayBufferVar(*web_array_buffer)); | 244 new HostArrayBufferVar(*web_array_buffer)); |
245 *result = buffer_var->GetPPVar(); | 245 *result = buffer_var->GetPPVar(); |
246 } else if (object_vars_allowed == V8VarConverter::kAllowObjectVars) { | 246 } else if (object_vars_allowed == V8VarConverter::kAllowObjectVars) { |
247 v8::Handle<v8::Object> object = val.As<v8::Object>(); | 247 v8::Local<v8::Object> object = val.As<v8::Object>(); |
248 *result = content::HostGlobals::Get()-> | 248 *result = content::HostGlobals::Get()-> |
249 host_var_tracker()->V8ObjectVarForV8Object(instance, object); | 249 host_var_tracker()->V8ObjectVarForV8Object(instance, object); |
250 } else if (val->IsArray()) { | 250 } else if (val->IsArray()) { |
251 *result = (new ArrayVar())->GetPPVar(); | 251 *result = (new ArrayVar())->GetPPVar(); |
252 } else { | 252 } else { |
253 bool was_resource; | 253 bool was_resource; |
254 if (!resource_converter->FromV8Value(val.As<v8::Object>(), context, | 254 if (!resource_converter->FromV8Value(val.As<v8::Object>(), context, |
255 result, &was_resource)) | 255 result, &was_resource)) |
256 return false; | 256 return false; |
257 if (!was_resource) { | 257 if (!was_resource) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 // iteration, the top node on the stack examined. If the node has not been | 299 // iteration, the top node on the stack examined. If the node has not been |
300 // visited yet (i.e. sentinel == false) then it is added to the list of parents | 300 // visited yet (i.e. sentinel == false) then it is added to the list of parents |
301 // which contains all of the nodes on the path from the start node to the | 301 // which contains all of the nodes on the path from the start node to the |
302 // current node. Each of the current nodes children are examined. If they appear | 302 // current node. Each of the current nodes children are examined. If they appear |
303 // in the list of parents it means we have a cycle and we return NULL. | 303 // in the list of parents it means we have a cycle and we return NULL. |
304 // Otherwise, if they can have children, we add them to the stack. If the | 304 // Otherwise, if they can have children, we add them to the stack. If the |
305 // node at the top of the stack has already been visited, then we pop it off the | 305 // node at the top of the stack has already been visited, then we pop it off the |
306 // stack and erase it from the list of parents. | 306 // stack and erase it from the list of parents. |
307 // static | 307 // static |
308 bool V8VarConverter::ToV8Value(const PP_Var& var, | 308 bool V8VarConverter::ToV8Value(const PP_Var& var, |
309 v8::Handle<v8::Context> context, | 309 v8::Local<v8::Context> context, |
310 v8::Handle<v8::Value>* result) { | 310 v8::Local<v8::Value>* result) { |
311 v8::Context::Scope context_scope(context); | 311 v8::Context::Scope context_scope(context); |
312 v8::Isolate* isolate = context->GetIsolate(); | 312 v8::Isolate* isolate = context->GetIsolate(); |
313 v8::EscapableHandleScope handle_scope(isolate); | 313 v8::EscapableHandleScope handle_scope(isolate); |
314 | 314 |
315 VarHandleMap visited_ids; | 315 VarHandleMap visited_ids; |
316 ParentVarSet parent_ids; | 316 ParentVarSet parent_ids; |
317 | 317 |
318 std::stack<StackEntry<PP_Var> > stack; | 318 std::stack<StackEntry<PP_Var> > stack; |
319 stack.push(StackEntry<PP_Var>(var)); | 319 stack.push(StackEntry<PP_Var>(var)); |
320 v8::Local<v8::Value> root; | 320 v8::Local<v8::Value> root; |
321 bool is_root = true; | 321 bool is_root = true; |
322 | 322 |
323 while (!stack.empty()) { | 323 while (!stack.empty()) { |
324 const PP_Var& current_var = stack.top().val; | 324 const PP_Var& current_var = stack.top().val; |
325 v8::Handle<v8::Value> current_v8; | 325 v8::Local<v8::Value> current_v8; |
326 | 326 |
327 if (stack.top().sentinel) { | 327 if (stack.top().sentinel) { |
328 stack.pop(); | 328 stack.pop(); |
329 if (CanHaveChildren(current_var)) | 329 if (CanHaveChildren(current_var)) |
330 parent_ids.erase(current_var.value.as_id); | 330 parent_ids.erase(current_var.value.as_id); |
331 continue; | 331 continue; |
332 } else { | 332 } else { |
333 stack.top().sentinel = true; | 333 stack.top().sentinel = true; |
334 } | 334 } |
335 | 335 |
(...skipping 16 matching lines...) Expand all Loading... |
352 | 352 |
353 // Add child nodes to the stack. | 353 // Add child nodes to the stack. |
354 if (current_var.type == PP_VARTYPE_ARRAY) { | 354 if (current_var.type == PP_VARTYPE_ARRAY) { |
355 parent_ids.insert(current_var.value.as_id); | 355 parent_ids.insert(current_var.value.as_id); |
356 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 356 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
357 if (!array_var) { | 357 if (!array_var) { |
358 NOTREACHED(); | 358 NOTREACHED(); |
359 return false; | 359 return false; |
360 } | 360 } |
361 DCHECK(current_v8->IsArray()); | 361 DCHECK(current_v8->IsArray()); |
362 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); | 362 v8::Local<v8::Array> v8_array = current_v8.As<v8::Array>(); |
363 | 363 |
364 for (size_t i = 0; i < array_var->elements().size(); ++i) { | 364 for (size_t i = 0; i < array_var->elements().size(); ++i) { |
365 const PP_Var& child_var = array_var->elements()[i].get(); | 365 const PP_Var& child_var = array_var->elements()[i].get(); |
366 v8::Handle<v8::Value> child_v8; | 366 v8::Local<v8::Value> child_v8; |
367 if (!GetOrCreateV8Value(context, | 367 if (!GetOrCreateV8Value(context, |
368 child_var, | 368 child_var, |
369 object_vars_allowed_, | 369 object_vars_allowed_, |
370 &child_v8, | 370 &child_v8, |
371 &did_create, | 371 &did_create, |
372 &visited_ids, | 372 &visited_ids, |
373 &parent_ids, | 373 &parent_ids, |
374 resource_converter_.get())) { | 374 resource_converter_.get())) { |
375 return false; | 375 return false; |
376 } | 376 } |
377 if (did_create && CanHaveChildren(child_var)) | 377 if (did_create && CanHaveChildren(child_var)) |
378 stack.push(child_var); | 378 stack.push(child_var); |
379 v8::TryCatch try_catch; | 379 v8::TryCatch try_catch; |
380 v8_array->Set(static_cast<uint32>(i), child_v8); | 380 v8_array->Set(static_cast<uint32>(i), child_v8); |
381 if (try_catch.HasCaught()) { | 381 if (try_catch.HasCaught()) { |
382 LOG(ERROR) << "Setter for index " << i << " threw an exception."; | 382 LOG(ERROR) << "Setter for index " << i << " threw an exception."; |
383 return false; | 383 return false; |
384 } | 384 } |
385 } | 385 } |
386 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 386 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
387 parent_ids.insert(current_var.value.as_id); | 387 parent_ids.insert(current_var.value.as_id); |
388 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 388 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
389 if (!dict_var) { | 389 if (!dict_var) { |
390 NOTREACHED(); | 390 NOTREACHED(); |
391 return false; | 391 return false; |
392 } | 392 } |
393 DCHECK(current_v8->IsObject()); | 393 DCHECK(current_v8->IsObject()); |
394 v8::Handle<v8::Object> v8_object = current_v8.As<v8::Object>(); | 394 v8::Local<v8::Object> v8_object = current_v8.As<v8::Object>(); |
395 | 395 |
396 for (DictionaryVar::KeyValueMap::const_iterator iter = | 396 for (DictionaryVar::KeyValueMap::const_iterator iter = |
397 dict_var->key_value_map().begin(); | 397 dict_var->key_value_map().begin(); |
398 iter != dict_var->key_value_map().end(); | 398 iter != dict_var->key_value_map().end(); |
399 ++iter) { | 399 ++iter) { |
400 const std::string& key = iter->first; | 400 const std::string& key = iter->first; |
401 const PP_Var& child_var = iter->second.get(); | 401 const PP_Var& child_var = iter->second.get(); |
402 v8::Handle<v8::Value> child_v8; | 402 v8::Local<v8::Value> child_v8; |
403 if (!GetOrCreateV8Value(context, | 403 if (!GetOrCreateV8Value(context, |
404 child_var, | 404 child_var, |
405 object_vars_allowed_, | 405 object_vars_allowed_, |
406 &child_v8, | 406 &child_v8, |
407 &did_create, | 407 &did_create, |
408 &visited_ids, | 408 &visited_ids, |
409 &parent_ids, | 409 &parent_ids, |
410 resource_converter_.get())) { | 410 resource_converter_.get())) { |
411 return false; | 411 return false; |
412 } | 412 } |
(...skipping 11 matching lines...) Expand all Loading... |
424 } | 424 } |
425 } | 425 } |
426 } | 426 } |
427 } | 427 } |
428 | 428 |
429 *result = handle_scope.Escape(root); | 429 *result = handle_scope.Escape(root); |
430 return true; | 430 return true; |
431 } | 431 } |
432 | 432 |
433 V8VarConverter::VarResult V8VarConverter::FromV8Value( | 433 V8VarConverter::VarResult V8VarConverter::FromV8Value( |
434 v8::Handle<v8::Value> val, | 434 v8::Local<v8::Value> val, |
435 v8::Handle<v8::Context> context, | 435 v8::Local<v8::Context> context, |
436 const base::Callback<void(const ScopedPPVar&, bool)>& callback) { | 436 const base::Callback<void(const ScopedPPVar&, bool)>& callback) { |
437 VarResult result; | 437 VarResult result; |
438 result.success = FromV8ValueInternal(val, context, &result.var); | 438 result.success = FromV8ValueInternal(val, context, &result.var); |
439 if (!result.success) | 439 if (!result.success) |
440 resource_converter_->Reset(); | 440 resource_converter_->Reset(); |
441 result.completed_synchronously = !resource_converter_->NeedsFlush(); | 441 result.completed_synchronously = !resource_converter_->NeedsFlush(); |
442 if (!result.completed_synchronously) | 442 if (!result.completed_synchronously) |
443 resource_converter_->Flush(base::Bind(callback, result.var)); | 443 resource_converter_->Flush(base::Bind(callback, result.var)); |
444 | 444 |
445 return result; | 445 return result; |
446 } | 446 } |
447 | 447 |
448 bool V8VarConverter::FromV8ValueSync( | 448 bool V8VarConverter::FromV8ValueSync( |
449 v8::Handle<v8::Value> val, | 449 v8::Local<v8::Value> val, |
450 v8::Handle<v8::Context> context, | 450 v8::Local<v8::Context> context, |
451 ppapi::ScopedPPVar* result_var) { | 451 ppapi::ScopedPPVar* result_var) { |
452 bool success = FromV8ValueInternal(val, context, result_var); | 452 bool success = FromV8ValueInternal(val, context, result_var); |
453 if (!success || resource_converter_->NeedsFlush()) { | 453 if (!success || resource_converter_->NeedsFlush()) { |
454 resource_converter_->Reset(); | 454 resource_converter_->Reset(); |
455 return false; | 455 return false; |
456 } | 456 } |
457 return true; | 457 return true; |
458 } | 458 } |
459 | 459 |
460 bool V8VarConverter::FromV8ValueInternal( | 460 bool V8VarConverter::FromV8ValueInternal( |
461 v8::Handle<v8::Value> val, | 461 v8::Local<v8::Value> val, |
462 v8::Handle<v8::Context> context, | 462 v8::Local<v8::Context> context, |
463 ppapi::ScopedPPVar* result_var) { | 463 ppapi::ScopedPPVar* result_var) { |
464 v8::Context::Scope context_scope(context); | 464 v8::Context::Scope context_scope(context); |
465 v8::HandleScope handle_scope(context->GetIsolate()); | 465 v8::HandleScope handle_scope(context->GetIsolate()); |
466 | 466 |
467 HandleVarMap visited_handles; | 467 HandleVarMap visited_handles; |
468 ParentHandleSet parent_handles; | 468 ParentHandleSet parent_handles; |
469 | 469 |
470 std::stack<StackEntry<v8::Handle<v8::Value> > > stack; | 470 std::stack<StackEntry<v8::Local<v8::Value> > > stack; |
471 stack.push(StackEntry<v8::Handle<v8::Value> >(val)); | 471 stack.push(StackEntry<v8::Local<v8::Value> >(val)); |
472 ScopedPPVar root; | 472 ScopedPPVar root; |
473 *result_var = PP_MakeUndefined(); | 473 *result_var = PP_MakeUndefined(); |
474 bool is_root = true; | 474 bool is_root = true; |
475 | 475 |
476 while (!stack.empty()) { | 476 while (!stack.empty()) { |
477 v8::Handle<v8::Value> current_v8 = stack.top().val; | 477 v8::Local<v8::Value> current_v8 = stack.top().val; |
478 PP_Var current_var; | 478 PP_Var current_var; |
479 | 479 |
480 if (stack.top().sentinel) { | 480 if (stack.top().sentinel) { |
481 stack.pop(); | 481 stack.pop(); |
482 if (current_v8->IsObject()) | 482 if (current_v8->IsObject()) |
483 parent_handles.erase(HashedHandle(current_v8.As<v8::Object>())); | 483 parent_handles.erase(HashedHandle(current_v8.As<v8::Object>())); |
484 continue; | 484 continue; |
485 } else { | 485 } else { |
486 stack.top().sentinel = true; | 486 stack.top().sentinel = true; |
487 } | 487 } |
(...skipping 12 matching lines...) Expand all Loading... |
500 } | 500 } |
501 | 501 |
502 if (is_root) { | 502 if (is_root) { |
503 is_root = false; | 503 is_root = false; |
504 root = current_var; | 504 root = current_var; |
505 } | 505 } |
506 | 506 |
507 // Add child nodes to the stack. | 507 // Add child nodes to the stack. |
508 if (current_var.type == PP_VARTYPE_ARRAY) { | 508 if (current_var.type == PP_VARTYPE_ARRAY) { |
509 DCHECK(current_v8->IsArray()); | 509 DCHECK(current_v8->IsArray()); |
510 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); | 510 v8::Local<v8::Array> v8_array = current_v8.As<v8::Array>(); |
511 parent_handles.insert(HashedHandle(v8_array)); | 511 parent_handles.insert(HashedHandle(v8_array)); |
512 | 512 |
513 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 513 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
514 if (!array_var) { | 514 if (!array_var) { |
515 NOTREACHED(); | 515 NOTREACHED(); |
516 return false; | 516 return false; |
517 } | 517 } |
518 | 518 |
519 for (uint32 i = 0; i < v8_array->Length(); ++i) { | 519 for (uint32 i = 0; i < v8_array->Length(); ++i) { |
520 v8::TryCatch try_catch; | 520 v8::TryCatch try_catch; |
521 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); | 521 v8::Local<v8::Value> child_v8 = v8_array->Get(i); |
522 if (try_catch.HasCaught()) | 522 if (try_catch.HasCaught()) |
523 return false; | 523 return false; |
524 | 524 |
525 if (!v8_array->HasRealIndexedProperty(i)) | 525 if (!v8_array->HasRealIndexedProperty(i)) |
526 continue; | 526 continue; |
527 | 527 |
528 PP_Var child_var; | 528 PP_Var child_var; |
529 if (!GetOrCreateVar(child_v8, | 529 if (!GetOrCreateVar(child_v8, |
530 context, | 530 context, |
531 instance_, | 531 instance_, |
532 object_vars_allowed_, | 532 object_vars_allowed_, |
533 &child_var, | 533 &child_var, |
534 &did_create, | 534 &did_create, |
535 &visited_handles, | 535 &visited_handles, |
536 &parent_handles, | 536 &parent_handles, |
537 resource_converter_.get())) { | 537 resource_converter_.get())) { |
538 return false; | 538 return false; |
539 } | 539 } |
540 if (did_create && child_v8->IsObject()) | 540 if (did_create && child_v8->IsObject()) |
541 stack.push(child_v8); | 541 stack.push(child_v8); |
542 | 542 |
543 array_var->Set(i, child_var); | 543 array_var->Set(i, child_var); |
544 } | 544 } |
545 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 545 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
546 DCHECK(current_v8->IsObject()); | 546 DCHECK(current_v8->IsObject()); |
547 v8::Handle<v8::Object> v8_object = current_v8.As<v8::Object>(); | 547 v8::Local<v8::Object> v8_object = current_v8.As<v8::Object>(); |
548 parent_handles.insert(HashedHandle(v8_object)); | 548 parent_handles.insert(HashedHandle(v8_object)); |
549 | 549 |
550 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 550 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
551 if (!dict_var) { | 551 if (!dict_var) { |
552 NOTREACHED(); | 552 NOTREACHED(); |
553 return false; | 553 return false; |
554 } | 554 } |
555 | 555 |
556 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); | 556 v8::Local<v8::Array> property_names(v8_object->GetOwnPropertyNames()); |
557 for (uint32 i = 0; i < property_names->Length(); ++i) { | 557 for (uint32 i = 0; i < property_names->Length(); ++i) { |
558 v8::Handle<v8::Value> key(property_names->Get(i)); | 558 v8::Local<v8::Value> key(property_names->Get(i)); |
559 | 559 |
560 // Extend this test to cover more types as necessary and if sensible. | 560 // Extend this test to cover more types as necessary and if sensible. |
561 if (!key->IsString() && !key->IsNumber()) { | 561 if (!key->IsString() && !key->IsNumber()) { |
562 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) | 562 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) |
563 << "\" " | 563 << "\" " |
564 "is neither a string nor a number"; | 564 "is neither a string nor a number"; |
565 return false; | 565 return false; |
566 } | 566 } |
567 | 567 |
568 v8::Handle<v8::String> key_string = | 568 v8::Local<v8::String> key_string = |
569 key->ToString(context->GetIsolate()); | 569 key->ToString(context->GetIsolate()); |
570 // Skip all callbacks: crbug.com/139933 | 570 // Skip all callbacks: crbug.com/139933 |
571 if (v8_object->HasRealNamedCallbackProperty(key_string)) | 571 if (v8_object->HasRealNamedCallbackProperty(key_string)) |
572 continue; | 572 continue; |
573 | 573 |
574 v8::String::Utf8Value name_utf8(key_string); | 574 v8::String::Utf8Value name_utf8(key_string); |
575 | 575 |
576 v8::TryCatch try_catch; | 576 v8::TryCatch try_catch; |
577 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); | 577 v8::Local<v8::Value> child_v8 = v8_object->Get(key); |
578 if (try_catch.HasCaught()) | 578 if (try_catch.HasCaught()) |
579 return false; | 579 return false; |
580 | 580 |
581 PP_Var child_var; | 581 PP_Var child_var; |
582 if (!GetOrCreateVar(child_v8, | 582 if (!GetOrCreateVar(child_v8, |
583 context, | 583 context, |
584 instance_, | 584 instance_, |
585 object_vars_allowed_, | 585 object_vars_allowed_, |
586 &child_var, | 586 &child_var, |
587 &did_create, | 587 &did_create, |
588 &visited_handles, | 588 &visited_handles, |
589 &parent_handles, | 589 &parent_handles, |
590 resource_converter_.get())) { | 590 resource_converter_.get())) { |
591 return false; | 591 return false; |
592 } | 592 } |
593 if (did_create && child_v8->IsObject()) | 593 if (did_create && child_v8->IsObject()) |
594 stack.push(child_v8); | 594 stack.push(child_v8); |
595 | 595 |
596 bool success = dict_var->SetWithStringKey( | 596 bool success = dict_var->SetWithStringKey( |
597 std::string(*name_utf8, name_utf8.length()), child_var); | 597 std::string(*name_utf8, name_utf8.length()), child_var); |
598 DCHECK(success); | 598 DCHECK(success); |
599 } | 599 } |
600 } | 600 } |
601 } | 601 } |
602 *result_var = root; | 602 *result_var = root; |
603 return true; | 603 return true; |
604 } | 604 } |
605 | 605 |
606 } // namespace content | 606 } // namespace content |
OLD | NEW |