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 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
392 } | 392 } |
393 | 393 |
394 *result = handle_scope.Escape(root); | 394 *result = handle_scope.Escape(root); |
395 return true; | 395 return true; |
396 } | 396 } |
397 | 397 |
398 void V8VarConverter::FromV8Value( | 398 void V8VarConverter::FromV8Value( |
399 v8::Handle<v8::Value> val, | 399 v8::Handle<v8::Value> val, |
400 v8::Handle<v8::Context> context, | 400 v8::Handle<v8::Context> context, |
401 const base::Callback<void(const ScopedPPVar&, bool)>& callback) { | 401 const base::Callback<void(const ScopedPPVar&, bool)>& callback) { |
| 402 ScopedPPVar result_var; |
| 403 if (FromV8ValueInternal(val, context, &result_var)) { |
| 404 resource_converter_->Flush(base::Bind(callback, result_var)); |
| 405 } else { |
| 406 message_loop_proxy_->PostTask( |
| 407 FROM_HERE, |
| 408 base::Bind(callback, result_var, false)); |
| 409 } |
| 410 } |
| 411 |
| 412 bool V8VarConverter::FromV8ValueInternal( |
| 413 v8::Handle<v8::Value> val, |
| 414 v8::Handle<v8::Context> context, |
| 415 ppapi::ScopedPPVar* result_var) { |
402 v8::Context::Scope context_scope(context); | 416 v8::Context::Scope context_scope(context); |
403 v8::HandleScope handle_scope(context->GetIsolate()); | 417 v8::HandleScope handle_scope(context->GetIsolate()); |
404 | 418 |
405 HandleVarMap visited_handles; | 419 HandleVarMap visited_handles; |
406 ParentHandleSet parent_handles; | 420 ParentHandleSet parent_handles; |
407 | 421 |
408 std::stack<StackEntry<v8::Handle<v8::Value> > > stack; | 422 std::stack<StackEntry<v8::Handle<v8::Value> > > stack; |
409 stack.push(StackEntry<v8::Handle<v8::Value> >(val)); | 423 stack.push(StackEntry<v8::Handle<v8::Value> >(val)); |
410 ScopedPPVar root; | 424 ScopedPPVar root; |
| 425 *result_var = PP_MakeUndefined(); |
411 bool is_root = true; | 426 bool is_root = true; |
412 | 427 |
413 while (!stack.empty()) { | 428 while (!stack.empty()) { |
414 v8::Handle<v8::Value> current_v8 = stack.top().val; | 429 v8::Handle<v8::Value> current_v8 = stack.top().val; |
415 PP_Var current_var; | 430 PP_Var current_var; |
416 | 431 |
417 if (stack.top().sentinel) { | 432 if (stack.top().sentinel) { |
418 stack.pop(); | 433 stack.pop(); |
419 if (current_v8->IsObject()) | 434 if (current_v8->IsObject()) |
420 parent_handles.erase(HashedHandle(current_v8->ToObject())); | 435 parent_handles.erase(HashedHandle(current_v8->ToObject())); |
421 continue; | 436 continue; |
422 } else { | 437 } else { |
423 stack.top().sentinel = true; | 438 stack.top().sentinel = true; |
424 } | 439 } |
425 | 440 |
426 bool did_create = false; | 441 bool did_create = false; |
427 if (!GetOrCreateVar(current_v8, | 442 if (!GetOrCreateVar(current_v8, |
428 context, | 443 context, |
429 ¤t_var, | 444 ¤t_var, |
430 &did_create, | 445 &did_create, |
431 &visited_handles, | 446 &visited_handles, |
432 &parent_handles, | 447 &parent_handles, |
433 resource_converter_.get())) { | 448 resource_converter_.get())) { |
434 message_loop_proxy_->PostTask( | 449 return false; |
435 FROM_HERE, | |
436 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
437 return; | |
438 } | 450 } |
439 | 451 |
440 if (is_root) { | 452 if (is_root) { |
441 is_root = false; | 453 is_root = false; |
442 root = current_var; | 454 root = current_var; |
443 } | 455 } |
444 | 456 |
445 // Add child nodes to the stack. | 457 // Add child nodes to the stack. |
446 if (current_var.type == PP_VARTYPE_ARRAY) { | 458 if (current_var.type == PP_VARTYPE_ARRAY) { |
447 DCHECK(current_v8->IsArray()); | 459 DCHECK(current_v8->IsArray()); |
448 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); | 460 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); |
449 parent_handles.insert(HashedHandle(v8_array)); | 461 parent_handles.insert(HashedHandle(v8_array)); |
450 | 462 |
451 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); | 463 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); |
452 if (!array_var) { | 464 if (!array_var) { |
453 NOTREACHED(); | 465 NOTREACHED(); |
454 message_loop_proxy_->PostTask( | 466 return false; |
455 FROM_HERE, | |
456 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
457 return; | |
458 } | 467 } |
459 | 468 |
460 for (uint32 i = 0; i < v8_array->Length(); ++i) { | 469 for (uint32 i = 0; i < v8_array->Length(); ++i) { |
461 v8::TryCatch try_catch; | 470 v8::TryCatch try_catch; |
462 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); | 471 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); |
463 if (try_catch.HasCaught()) { | 472 if (try_catch.HasCaught()) |
464 message_loop_proxy_->PostTask( | 473 return false; |
465 FROM_HERE, | |
466 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
467 return; | |
468 } | |
469 | 474 |
470 if (!v8_array->HasRealIndexedProperty(i)) | 475 if (!v8_array->HasRealIndexedProperty(i)) |
471 continue; | 476 continue; |
472 | 477 |
473 PP_Var child_var; | 478 PP_Var child_var; |
474 if (!GetOrCreateVar(child_v8, | 479 if (!GetOrCreateVar(child_v8, |
475 context, | 480 context, |
476 &child_var, | 481 &child_var, |
477 &did_create, | 482 &did_create, |
478 &visited_handles, | 483 &visited_handles, |
479 &parent_handles, | 484 &parent_handles, |
480 resource_converter_.get())) { | 485 resource_converter_.get())) { |
481 message_loop_proxy_->PostTask( | 486 return false; |
482 FROM_HERE, | |
483 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
484 return; | |
485 } | 487 } |
486 if (did_create && child_v8->IsObject()) | 488 if (did_create && child_v8->IsObject()) |
487 stack.push(child_v8); | 489 stack.push(child_v8); |
488 | 490 |
489 array_var->Set(i, child_var); | 491 array_var->Set(i, child_var); |
490 } | 492 } |
491 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { | 493 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { |
492 DCHECK(current_v8->IsObject()); | 494 DCHECK(current_v8->IsObject()); |
493 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); | 495 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); |
494 parent_handles.insert(HashedHandle(v8_object)); | 496 parent_handles.insert(HashedHandle(v8_object)); |
495 | 497 |
496 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); | 498 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); |
497 if (!dict_var) { | 499 if (!dict_var) { |
498 NOTREACHED(); | 500 NOTREACHED(); |
499 message_loop_proxy_->PostTask( | 501 return false; |
500 FROM_HERE, | |
501 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
502 return; | |
503 } | 502 } |
504 | 503 |
505 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); | 504 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); |
506 for (uint32 i = 0; i < property_names->Length(); ++i) { | 505 for (uint32 i = 0; i < property_names->Length(); ++i) { |
507 v8::Handle<v8::Value> key(property_names->Get(i)); | 506 v8::Handle<v8::Value> key(property_names->Get(i)); |
508 | 507 |
509 // Extend this test to cover more types as necessary and if sensible. | 508 // Extend this test to cover more types as necessary and if sensible. |
510 if (!key->IsString() && !key->IsNumber()) { | 509 if (!key->IsString() && !key->IsNumber()) { |
511 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) | 510 NOTREACHED() << "Key \"" << *v8::String::Utf8Value(key) |
512 << "\" " | 511 << "\" " |
513 "is neither a string nor a number"; | 512 "is neither a string nor a number"; |
514 message_loop_proxy_->PostTask( | 513 return false; |
515 FROM_HERE, | |
516 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
517 return; | |
518 } | 514 } |
519 | 515 |
520 // Skip all callbacks: crbug.com/139933 | 516 // Skip all callbacks: crbug.com/139933 |
521 if (v8_object->HasRealNamedCallbackProperty(key->ToString())) | 517 if (v8_object->HasRealNamedCallbackProperty(key->ToString())) |
522 continue; | 518 continue; |
523 | 519 |
524 v8::String::Utf8Value name_utf8(key->ToString()); | 520 v8::String::Utf8Value name_utf8(key->ToString()); |
525 | 521 |
526 v8::TryCatch try_catch; | 522 v8::TryCatch try_catch; |
527 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); | 523 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); |
528 if (try_catch.HasCaught()) { | 524 if (try_catch.HasCaught()) |
529 message_loop_proxy_->PostTask( | 525 return false; |
530 FROM_HERE, | |
531 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
532 return; | |
533 } | |
534 | 526 |
535 PP_Var child_var; | 527 PP_Var child_var; |
536 if (!GetOrCreateVar(child_v8, | 528 if (!GetOrCreateVar(child_v8, |
537 context, | 529 context, |
538 &child_var, | 530 &child_var, |
539 &did_create, | 531 &did_create, |
540 &visited_handles, | 532 &visited_handles, |
541 &parent_handles, | 533 &parent_handles, |
542 resource_converter_.get())) { | 534 resource_converter_.get())) { |
543 message_loop_proxy_->PostTask( | 535 return false; |
544 FROM_HERE, | |
545 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); | |
546 return; | |
547 } | 536 } |
548 if (did_create && child_v8->IsObject()) | 537 if (did_create && child_v8->IsObject()) |
549 stack.push(child_v8); | 538 stack.push(child_v8); |
550 | 539 |
551 bool success = dict_var->SetWithStringKey( | 540 bool success = dict_var->SetWithStringKey( |
552 std::string(*name_utf8, name_utf8.length()), child_var); | 541 std::string(*name_utf8, name_utf8.length()), child_var); |
553 DCHECK(success); | 542 DCHECK(success); |
554 } | 543 } |
555 } | 544 } |
556 } | 545 } |
557 resource_converter_->Flush(base::Bind(callback, root)); | 546 *result_var = root; |
| 547 return true; |
558 } | 548 } |
559 | 549 |
560 } // namespace content | 550 } // namespace content |
OLD | NEW |