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