Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: content/renderer/pepper/v8_var_converter.cc

Issue 23330008: Introduce MockResourceConverter to modularize testing of V8VarConverter (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 } 57 }
58 }; 58 };
59 #elif defined(COMPILER_MSVC) 59 #elif defined(COMPILER_MSVC)
60 inline size_t hash_value(const HashedHandle& handle) { 60 inline size_t hash_value(const HashedHandle& handle) {
61 return handle.hash(); 61 return handle.hash();
62 } 62 }
63 #endif 63 #endif
64 } // namespace BASE_HASH_NAMESPACE 64 } // namespace BASE_HASH_NAMESPACE
65 65
66 namespace content { 66 namespace content {
67 namespace V8VarConverter {
68 67
69 namespace { 68 namespace {
70 69
71 // Maps PP_Var IDs to the V8 value handle they correspond to. 70 // Maps PP_Var IDs to the V8 value handle they correspond to.
72 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap; 71 typedef base::hash_map<int64_t, v8::Handle<v8::Value> > VarHandleMap;
73 typedef base::hash_set<int64_t> ParentVarSet; 72 typedef base::hash_set<int64_t> ParentVarSet;
74 73
75 // Maps V8 value handles to the PP_Var they correspond to. 74 // Maps V8 value handles to the PP_Var they correspond to.
76 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap; 75 typedef base::hash_map<HashedHandle, ScopedPPVar> HandleVarMap;
77 typedef base::hash_set<HashedHandle> ParentHandleSet; 76 typedef base::hash_set<HashedHandle> ParentHandleSet;
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 } 227 }
229 return true; 228 return true;
230 } 229 }
231 230
232 bool CanHaveChildren(PP_Var var) { 231 bool CanHaveChildren(PP_Var var) {
233 return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY; 232 return var.type == PP_VARTYPE_ARRAY || var.type == PP_VARTYPE_DICTIONARY;
234 } 233 }
235 234
236 } // namespace 235 } // namespace
237 236
237 V8VarConverter::V8VarConverter()
238 : message_loop_proxy_(base::MessageLoopProxy::current()),
239 resource_converter_(new ResourceConverterImpl()) {
240 }
241
242 V8VarConverter::V8VarConverter(
243 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy,
244 scoped_ptr<ResourceConverter> resource_converter)
245 : message_loop_proxy_(message_loop_proxy),
246 resource_converter_(resource_converter.release()) {
247 }
248
249 V8VarConverter::~V8VarConverter() {
250 }
251
238 // To/FromV8Value use a stack-based DFS search to traverse V8/Var graph. Each 252 // To/FromV8Value use a stack-based DFS search to traverse V8/Var graph. Each
239 // iteration, the top node on the stack examined. If the node has not been 253 // iteration, the top node on the stack examined. If the node has not been
240 // visited yet (i.e. sentinel == false) then it is added to the list of parents 254 // visited yet (i.e. sentinel == false) then it is added to the list of parents
241 // which contains all of the nodes on the path from the start node to the 255 // which contains all of the nodes on the path from the start node to the
242 // current node. Each of the current nodes children are examined. If they appear 256 // current node. Each of the current nodes children are examined. If they appear
243 // in the list of parents it means we have a cycle and we return NULL. 257 // in the list of parents it means we have a cycle and we return NULL.
244 // Otherwise, if they can have children, we add them to the stack. If the 258 // Otherwise, if they can have children, we add them to the stack. If the
245 // node at the top of the stack has already been visited, then we pop it off the 259 // node at the top of the stack has already been visited, then we pop it off the
246 // stack and erase it from the list of parents. 260 // stack and erase it from the list of parents.
247 // static 261 // static
248 bool ToV8Value(const PP_Var& var, 262 bool V8VarConverter::ToV8Value(const PP_Var& var,
249 v8::Handle<v8::Context> context, 263 v8::Handle<v8::Context> context,
250 v8::Handle<v8::Value>* result) { 264 v8::Handle<v8::Value>* result) {
251 v8::Context::Scope context_scope(context); 265 v8::Context::Scope context_scope(context);
252 v8::HandleScope handle_scope; 266 v8::HandleScope handle_scope;
253 267
254 VarHandleMap visited_ids; 268 VarHandleMap visited_ids;
255 ParentVarSet parent_ids; 269 ParentVarSet parent_ids;
256 270
257 std::stack<StackEntry<PP_Var> > stack; 271 std::stack<StackEntry<PP_Var> > stack;
258 stack.push(StackEntry<PP_Var>(var)); 272 stack.push(StackEntry<PP_Var>(var));
259 v8::Handle<v8::Value> root; 273 v8::Handle<v8::Value> root;
260 bool is_root = true; 274 bool is_root = true;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
341 return false; 355 return false;
342 } 356 }
343 } 357 }
344 } 358 }
345 } 359 }
346 360
347 *result = handle_scope.Close(root); 361 *result = handle_scope.Close(root);
348 return true; 362 return true;
349 } 363 }
350 364
351 void FromV8Value( 365 void V8VarConverter::FromV8Value(
352 v8::Handle<v8::Value> val, 366 v8::Handle<v8::Value> val,
353 v8::Handle<v8::Context> context, 367 v8::Handle<v8::Context> context,
354 const base::Callback<void(const ScopedPPVar&, bool)>& callback, 368 const base::Callback<void(const ScopedPPVar&, bool)>& callback) {
355 const scoped_refptr<base::MessageLoopProxy>& message_loop_proxy) {
356 v8::Context::Scope context_scope(context); 369 v8::Context::Scope context_scope(context);
357 v8::HandleScope handle_scope; 370 v8::HandleScope handle_scope;
358 371
359 HandleVarMap visited_handles; 372 HandleVarMap visited_handles;
360 ParentHandleSet parent_handles; 373 ParentHandleSet parent_handles;
361 374
362 ResourceConverter resource_converter;
363
364 std::stack<StackEntry<v8::Handle<v8::Value> > > stack; 375 std::stack<StackEntry<v8::Handle<v8::Value> > > stack;
365 stack.push(StackEntry<v8::Handle<v8::Value> >(val)); 376 stack.push(StackEntry<v8::Handle<v8::Value> >(val));
366 ScopedPPVar root; 377 ScopedPPVar root;
367 bool is_root = true; 378 bool is_root = true;
368 379
369 while (!stack.empty()) { 380 while (!stack.empty()) {
370 v8::Handle<v8::Value> current_v8 = stack.top().val; 381 v8::Handle<v8::Value> current_v8 = stack.top().val;
371 PP_Var current_var; 382 PP_Var current_var;
372 383
373 if (stack.top().sentinel) { 384 if (stack.top().sentinel) {
374 stack.pop(); 385 stack.pop();
375 if (current_v8->IsObject()) 386 if (current_v8->IsObject())
376 parent_handles.erase(HashedHandle(current_v8->ToObject())); 387 parent_handles.erase(HashedHandle(current_v8->ToObject()));
377 continue; 388 continue;
378 } else { 389 } else {
379 stack.top().sentinel = true; 390 stack.top().sentinel = true;
380 } 391 }
381 392
382 bool did_create = false; 393 bool did_create = false;
383 if (!GetOrCreateVar(current_v8, &current_var, &did_create, 394 if (!GetOrCreateVar(current_v8, &current_var, &did_create,
384 &visited_handles, &parent_handles, 395 &visited_handles, &parent_handles,
385 &resource_converter)) { 396 resource_converter_.get())) {
386 message_loop_proxy->PostTask(FROM_HERE, 397 message_loop_proxy_->PostTask(FROM_HERE,
387 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 398 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
388 return; 399 return;
389 } 400 }
390 401
391 if (is_root) { 402 if (is_root) {
392 is_root = false; 403 is_root = false;
393 root = current_var; 404 root = current_var;
394 } 405 }
395 406
396 // Add child nodes to the stack. 407 // Add child nodes to the stack.
397 if (current_var.type == PP_VARTYPE_ARRAY) { 408 if (current_var.type == PP_VARTYPE_ARRAY) {
398 DCHECK(current_v8->IsArray()); 409 DCHECK(current_v8->IsArray());
399 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>(); 410 v8::Handle<v8::Array> v8_array = current_v8.As<v8::Array>();
400 parent_handles.insert(HashedHandle(v8_array)); 411 parent_handles.insert(HashedHandle(v8_array));
401 412
402 ArrayVar* array_var = ArrayVar::FromPPVar(current_var); 413 ArrayVar* array_var = ArrayVar::FromPPVar(current_var);
403 if (!array_var) { 414 if (!array_var) {
404 NOTREACHED(); 415 NOTREACHED();
405 message_loop_proxy->PostTask(FROM_HERE, 416 message_loop_proxy_->PostTask(FROM_HERE,
406 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 417 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
407 return; 418 return;
408 } 419 }
409 420
410 for (uint32 i = 0; i < v8_array->Length(); ++i) { 421 for (uint32 i = 0; i < v8_array->Length(); ++i) {
411 v8::TryCatch try_catch; 422 v8::TryCatch try_catch;
412 v8::Handle<v8::Value> child_v8 = v8_array->Get(i); 423 v8::Handle<v8::Value> child_v8 = v8_array->Get(i);
413 if (try_catch.HasCaught()) { 424 if (try_catch.HasCaught()) {
414 message_loop_proxy->PostTask(FROM_HERE, 425 message_loop_proxy_->PostTask(FROM_HERE,
415 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 426 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
416 return; 427 return;
417 } 428 }
418 429
419 if (!v8_array->HasRealIndexedProperty(i)) 430 if (!v8_array->HasRealIndexedProperty(i))
420 continue; 431 continue;
421 432
422 PP_Var child_var; 433 PP_Var child_var;
423 if (!GetOrCreateVar(child_v8, &child_var, &did_create, 434 if (!GetOrCreateVar(child_v8, &child_var, &did_create,
424 &visited_handles, &parent_handles, 435 &visited_handles, &parent_handles,
425 &resource_converter)) { 436 resource_converter_.get())) {
426 message_loop_proxy->PostTask(FROM_HERE, 437 message_loop_proxy_->PostTask(FROM_HERE,
427 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 438 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
428 return; 439 return;
429 } 440 }
430 if (did_create && child_v8->IsObject()) 441 if (did_create && child_v8->IsObject())
431 stack.push(child_v8); 442 stack.push(child_v8);
432 443
433 array_var->Set(i, child_var); 444 array_var->Set(i, child_var);
434 } 445 }
435 } else if (current_var.type == PP_VARTYPE_DICTIONARY) { 446 } else if (current_var.type == PP_VARTYPE_DICTIONARY) {
436 DCHECK(current_v8->IsObject()); 447 DCHECK(current_v8->IsObject());
437 v8::Handle<v8::Object> v8_object = current_v8->ToObject(); 448 v8::Handle<v8::Object> v8_object = current_v8->ToObject();
438 parent_handles.insert(HashedHandle(v8_object)); 449 parent_handles.insert(HashedHandle(v8_object));
439 450
440 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var); 451 DictionaryVar* dict_var = DictionaryVar::FromPPVar(current_var);
441 if (!dict_var) { 452 if (!dict_var) {
442 NOTREACHED(); 453 NOTREACHED();
443 message_loop_proxy->PostTask(FROM_HERE, 454 message_loop_proxy_->PostTask(FROM_HERE,
444 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 455 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
445 return; 456 return;
446 } 457 }
447 458
448 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames()); 459 v8::Handle<v8::Array> property_names(v8_object->GetOwnPropertyNames());
449 for (uint32 i = 0; i < property_names->Length(); ++i) { 460 for (uint32 i = 0; i < property_names->Length(); ++i) {
450 v8::Handle<v8::Value> key(property_names->Get(i)); 461 v8::Handle<v8::Value> key(property_names->Get(i));
451 462
452 // Extend this test to cover more types as necessary and if sensible. 463 // Extend this test to cover more types as necessary and if sensible.
453 if (!key->IsString() && !key->IsNumber()) { 464 if (!key->IsString() && !key->IsNumber()) {
454 NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" " 465 NOTREACHED() << "Key \"" << *v8::String::AsciiValue(key) << "\" "
455 "is neither a string nor a number"; 466 "is neither a string nor a number";
456 message_loop_proxy->PostTask(FROM_HERE, 467 message_loop_proxy_->PostTask(FROM_HERE,
457 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 468 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
458 return; 469 return;
459 } 470 }
460 471
461 // Skip all callbacks: crbug.com/139933 472 // Skip all callbacks: crbug.com/139933
462 if (v8_object->HasRealNamedCallbackProperty(key->ToString())) 473 if (v8_object->HasRealNamedCallbackProperty(key->ToString()))
463 continue; 474 continue;
464 475
465 v8::String::Utf8Value name_utf8(key->ToString()); 476 v8::String::Utf8Value name_utf8(key->ToString());
466 477
467 v8::TryCatch try_catch; 478 v8::TryCatch try_catch;
468 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); 479 v8::Handle<v8::Value> child_v8 = v8_object->Get(key);
469 if (try_catch.HasCaught()) { 480 if (try_catch.HasCaught()) {
470 message_loop_proxy->PostTask(FROM_HERE, 481 message_loop_proxy_->PostTask(FROM_HERE,
471 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 482 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
472 return; 483 return;
473 } 484 }
474 485
475 PP_Var child_var; 486 PP_Var child_var;
476 if (!GetOrCreateVar(child_v8, &child_var, &did_create, 487 if (!GetOrCreateVar(child_v8, &child_var, &did_create,
477 &visited_handles, &parent_handles, 488 &visited_handles, &parent_handles,
478 &resource_converter)) { 489 resource_converter_.get())) {
479 message_loop_proxy->PostTask(FROM_HERE, 490 message_loop_proxy_->PostTask(FROM_HERE,
480 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false)); 491 base::Bind(callback, ScopedPPVar(PP_MakeUndefined()), false));
481 return; 492 return;
482 } 493 }
483 if (did_create && child_v8->IsObject()) 494 if (did_create && child_v8->IsObject())
484 stack.push(child_v8); 495 stack.push(child_v8);
485 496
486 bool success = dict_var->SetWithStringKey( 497 bool success = dict_var->SetWithStringKey(
487 std::string(*name_utf8, name_utf8.length()), child_var); 498 std::string(*name_utf8, name_utf8.length()), child_var);
488 DCHECK(success); 499 DCHECK(success);
489 } 500 }
490 } 501 }
491 } 502 }
492 resource_converter.ShutDown(base::Bind(callback, root), message_loop_proxy); 503 resource_converter_->ShutDown(base::Bind(callback, root));
493 } 504 }
494 505
495 void FromV8Value(
496 v8::Handle<v8::Value> val,
497 v8::Handle<v8::Context> context,
498 const base::Callback<void(const ScopedPPVar&, bool)>& callback) {
499 FromV8Value(val, context, callback, base::MessageLoopProxy::current());
500 }
501
502 } // namespace V8VarConverter
503 } // namespace content 506 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/pepper/v8_var_converter.h ('k') | content/renderer/pepper/v8_var_converter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698