OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 return it->second == val; | 75 return it->second == val; |
76 (*visited_ids)[var.value.as_id] = val; | 76 (*visited_ids)[var.value.as_id] = val; |
77 } | 77 } |
78 | 78 |
79 if (val->IsUndefined()) { | 79 if (val->IsUndefined()) { |
80 return var.type == PP_VARTYPE_UNDEFINED; | 80 return var.type == PP_VARTYPE_UNDEFINED; |
81 } else if (val->IsNull()) { | 81 } else if (val->IsNull()) { |
82 return var.type == PP_VARTYPE_NULL; | 82 return var.type == PP_VARTYPE_NULL; |
83 } else if (val->IsBoolean() || val->IsBooleanObject()) { | 83 } else if (val->IsBoolean() || val->IsBooleanObject()) { |
84 return var.type == PP_VARTYPE_BOOL && | 84 return var.type == PP_VARTYPE_BOOL && |
85 PP_FromBool(val->ToBoolean()->Value()) == var.value.as_bool; | 85 PP_FromBool(val->ToBoolean()->Value()) == var.value.as_bool; |
86 } else if (val->IsInt32()) { | 86 } else if (val->IsInt32()) { |
87 return var.type == PP_VARTYPE_INT32 && | 87 return var.type == PP_VARTYPE_INT32 && |
88 val->ToInt32()->Value() == var.value.as_int; | 88 val->ToInt32()->Value() == var.value.as_int; |
89 } else if (val->IsNumber() || val->IsNumberObject()) { | 89 } else if (val->IsNumber() || val->IsNumberObject()) { |
90 return var.type == PP_VARTYPE_DOUBLE && | 90 return var.type == PP_VARTYPE_DOUBLE && |
91 fabs(val->ToNumber()->Value() - var.value.as_double) <= 1.0e-4; | 91 fabs(val->ToNumber()->Value() - var.value.as_double) <= 1.0e-4; |
92 } else if (val->IsString() || val->IsStringObject()) { | 92 } else if (val->IsString() || val->IsStringObject()) { |
93 if (var.type != PP_VARTYPE_STRING) | 93 if (var.type != PP_VARTYPE_STRING) |
94 return false; | 94 return false; |
95 StringVar* string_var = StringVar::FromPPVar(var); | 95 StringVar* string_var = StringVar::FromPPVar(var); |
96 DCHECK(string_var); | 96 DCHECK(string_var); |
97 v8::String::Utf8Value utf8(val->ToString()); | 97 v8::String::Utf8Value utf8(val->ToString()); |
98 return std::string(*utf8, utf8.length()) == string_var->value(); | 98 return std::string(*utf8, utf8.length()) == string_var->value(); |
99 } else if (val->IsArray()) { | 99 } else if (val->IsArray()) { |
100 if (var.type != PP_VARTYPE_ARRAY) | 100 if (var.type != PP_VARTYPE_ARRAY) |
101 return false; | 101 return false; |
(...skipping 24 matching lines...) Expand all Loading... |
126 return false; | 126 return false; |
127 for (uint32 i = 0; i < property_names->Length(); ++i) { | 127 for (uint32 i = 0; i < property_names->Length(); ++i) { |
128 v8::Handle<v8::Value> key(property_names->Get(i)); | 128 v8::Handle<v8::Value> key(property_names->Get(i)); |
129 | 129 |
130 if (!key->IsString() && !key->IsNumber()) | 130 if (!key->IsString() && !key->IsNumber()) |
131 return false; | 131 return false; |
132 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); | 132 v8::Handle<v8::Value> child_v8 = v8_object->Get(key); |
133 | 133 |
134 v8::String::Utf8Value name_utf8(key->ToString()); | 134 v8::String::Utf8Value name_utf8(key->ToString()); |
135 ScopedPPVar release_key(ScopedPPVar::PassRef(), | 135 ScopedPPVar release_key(ScopedPPVar::PassRef(), |
136 StringVar::StringToPPVar( | 136 StringVar::StringToPPVar(std::string( |
137 std::string(*name_utf8, name_utf8.length()))); | 137 *name_utf8, name_utf8.length()))); |
138 if (!dict_var->HasKey(release_key.get())) | 138 if (!dict_var->HasKey(release_key.get())) |
139 return false; | 139 return false; |
140 ScopedPPVar release_value(ScopedPPVar::PassRef(), | 140 ScopedPPVar release_value(ScopedPPVar::PassRef(), |
141 dict_var->Get(release_key.get())); | 141 dict_var->Get(release_key.get())); |
142 if (!Equals(release_value.get(), child_v8, visited_ids)) | 142 if (!Equals(release_value.get(), child_v8, visited_ids)) |
143 return false; | 143 return false; |
144 } | 144 } |
145 return true; | 145 return true; |
146 } | 146 } |
147 } | 147 } |
148 return false; | 148 return false; |
149 } | 149 } |
150 | 150 |
151 bool Equals(const PP_Var& var, | 151 bool Equals(const PP_Var& var, v8::Handle<v8::Value> val) { |
152 v8::Handle<v8::Value> val) { | |
153 VarHandleMap var_handle_map; | 152 VarHandleMap var_handle_map; |
154 return Equals(var, val, &var_handle_map); | 153 return Equals(var, val, &var_handle_map); |
155 } | 154 } |
156 | 155 |
157 class V8VarConverterTest : public testing::Test { | 156 class V8VarConverterTest : public testing::Test { |
158 public: | 157 public: |
159 V8VarConverterTest() | 158 V8VarConverterTest() |
160 : isolate_(v8::Isolate::GetCurrent()), | 159 : isolate_(v8::Isolate::GetCurrent()), conversion_success_(false) { |
161 conversion_success_(false) { | |
162 PP_Instance dummy = 1234; | 160 PP_Instance dummy = 1234; |
163 converter_.reset(new V8VarConverter( | 161 converter_.reset(new V8VarConverter( |
164 dummy, | 162 dummy, |
165 scoped_ptr<ResourceConverter>(new MockResourceConverter).Pass())); | 163 scoped_ptr<ResourceConverter>(new MockResourceConverter).Pass())); |
166 } | 164 } |
167 virtual ~V8VarConverterTest() {} | 165 virtual ~V8VarConverterTest() {} |
168 | 166 |
169 // testing::Test implementation. | 167 // testing::Test implementation. |
170 virtual void SetUp() { | 168 virtual void SetUp() { |
171 ProxyLock::Acquire(); | 169 ProxyLock::Acquire(); |
172 v8::HandleScope handle_scope(isolate_); | 170 v8::HandleScope handle_scope(isolate_); |
173 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_); | 171 v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate_); |
174 context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); | 172 context_.Reset(isolate_, v8::Context::New(isolate_, NULL, global)); |
175 } | 173 } |
176 virtual void TearDown() { | 174 virtual void TearDown() { |
177 context_.Reset(); | 175 context_.Reset(); |
178 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); | 176 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); |
179 ProxyLock::Release(); | 177 ProxyLock::Release(); |
180 } | 178 } |
181 | 179 |
182 protected: | 180 protected: |
183 bool FromV8ValueSync(v8::Handle<v8::Value> val, | 181 bool FromV8ValueSync(v8::Handle<v8::Value> val, |
184 v8::Handle<v8::Context> context, | 182 v8::Handle<v8::Context> context, |
185 PP_Var* result) { | 183 PP_Var* result) { |
186 base::RunLoop loop; | 184 base::RunLoop loop; |
187 converter_->FromV8Value(val, context, base::Bind( | 185 converter_->FromV8Value(val, |
188 &V8VarConverterTest::FromV8ValueComplete, base::Unretained(this), | 186 context, |
189 loop.QuitClosure())); | 187 base::Bind(&V8VarConverterTest::FromV8ValueComplete, |
| 188 base::Unretained(this), |
| 189 loop.QuitClosure())); |
190 loop.Run(); | 190 loop.Run(); |
191 if (conversion_success_) | 191 if (conversion_success_) |
192 *result = conversion_result_; | 192 *result = conversion_result_; |
193 return conversion_success_; | 193 return conversion_success_; |
194 } | 194 } |
195 | 195 |
196 void FromV8ValueComplete(base::Closure quit_closure, | 196 void FromV8ValueComplete(base::Closure quit_closure, |
197 const ScopedPPVar& scoped_var, | 197 const ScopedPPVar& scoped_var, |
198 bool success) { | 198 bool success) { |
199 conversion_success_ = success; | 199 conversion_success_ = success; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 | 274 |
275 // Array with primitives. | 275 // Array with primitives. |
276 array->Set(index++, PP_MakeUndefined()); | 276 array->Set(index++, PP_MakeUndefined()); |
277 array->Set(index++, PP_MakeNull()); | 277 array->Set(index++, PP_MakeNull()); |
278 array->Set(index++, PP_MakeInt32(100)); | 278 array->Set(index++, PP_MakeInt32(100)); |
279 array->Set(index++, PP_MakeBool(PP_FALSE)); | 279 array->Set(index++, PP_MakeBool(PP_FALSE)); |
280 array->Set(index++, PP_MakeDouble(0.123)); | 280 array->Set(index++, PP_MakeDouble(0.123)); |
281 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 281 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
282 | 282 |
283 // Array with 2 references to the same string. | 283 // Array with 2 references to the same string. |
284 ScopedPPVar release_string( | 284 ScopedPPVar release_string(ScopedPPVar::PassRef(), |
285 ScopedPPVar::PassRef(), StringVar::StringToPPVar("abc")); | 285 StringVar::StringToPPVar("abc")); |
286 array->Set(index++, release_string.get()); | 286 array->Set(index++, release_string.get()); |
287 array->Set(index++, release_string.get()); | 287 array->Set(index++, release_string.get()); |
288 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 288 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
289 | 289 |
290 // Array with nested array that references the same string. | 290 // Array with nested array that references the same string. |
291 scoped_refptr<ArrayVar> array2(new ArrayVar); | 291 scoped_refptr<ArrayVar> array2(new ArrayVar); |
292 ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar()); | 292 ScopedPPVar release_array2(ScopedPPVar::PassRef(), array2->GetPPVar()); |
293 array2->Set(0, release_string.get()); | 293 array2->Set(0, release_string.get()); |
294 array->Set(index++, release_array2.get()); | 294 array->Set(index++, release_array2.get()); |
295 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 295 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
346 scoped_refptr<ArrayVar> array(new ArrayVar); | 346 scoped_refptr<ArrayVar> array(new ArrayVar); |
347 ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar()); | 347 ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar()); |
348 | 348 |
349 dictionary->SetWithStringKey("1", release_array.get()); | 349 dictionary->SetWithStringKey("1", release_array.get()); |
350 array->Set(0, release_dictionary.get()); | 350 array->Set(0, release_dictionary.get()); |
351 | 351 |
352 v8::Handle<v8::Value> v8_result; | 352 v8::Handle<v8::Value> v8_result; |
353 | 353 |
354 // Array <-> dictionary cycle. | 354 // Array <-> dictionary cycle. |
355 dictionary->SetWithStringKey("1", release_array.get()); | 355 dictionary->SetWithStringKey("1", release_array.get()); |
356 ASSERT_FALSE(converter_->ToV8Value(release_dictionary.get(), | 356 ASSERT_FALSE( |
357 context, &v8_result)); | 357 converter_->ToV8Value(release_dictionary.get(), context, &v8_result)); |
358 // Break the cycle. | 358 // Break the cycle. |
359 // TODO(raymes): We need some better machinery for releasing vars with | 359 // TODO(raymes): We need some better machinery for releasing vars with |
360 // cycles. Remove the code below once we have that. | 360 // cycles. Remove the code below once we have that. |
361 dictionary->DeleteWithStringKey("1"); | 361 dictionary->DeleteWithStringKey("1"); |
362 | 362 |
363 // Array with self reference. | 363 // Array with self reference. |
364 array->Set(0, release_array.get()); | 364 array->Set(0, release_array.get()); |
365 ASSERT_FALSE(converter_->ToV8Value(release_array.get(), | 365 ASSERT_FALSE( |
366 context, &v8_result)); | 366 converter_->ToV8Value(release_array.get(), context, &v8_result)); |
367 // Break the self reference. | 367 // Break the self reference. |
368 array->Set(0, PP_MakeUndefined()); | 368 array->Set(0, PP_MakeUndefined()); |
369 } | 369 } |
370 | 370 |
371 // V8->Var conversion. | 371 // V8->Var conversion. |
372 { | 372 { |
373 v8::Handle<v8::Object> object = v8::Object::New(isolate_); | 373 v8::Handle<v8::Object> object = v8::Object::New(isolate_); |
374 v8::Handle<v8::Array> array = v8::Array::New(isolate_); | 374 v8::Handle<v8::Array> array = v8::Array::New(isolate_); |
375 | 375 |
376 PP_Var var_result; | 376 PP_Var var_result; |
(...skipping 23 matching lines...) Expand all Loading... |
400 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); | 400 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); |
401 } | 401 } |
402 | 402 |
403 { | 403 { |
404 // Test non-string key types. They should be cast to strings. | 404 // Test non-string key types. They should be cast to strings. |
405 v8::HandleScope handle_scope(isolate_); | 405 v8::HandleScope handle_scope(isolate_); |
406 v8::Local<v8::Context> context = | 406 v8::Local<v8::Context> context = |
407 v8::Local<v8::Context>::New(isolate_, context_); | 407 v8::Local<v8::Context>::New(isolate_, context_); |
408 v8::Context::Scope context_scope(context); | 408 v8::Context::Scope context_scope(context); |
409 | 409 |
410 const char* source = "(function() {" | 410 const char* source = |
| 411 "(function() {" |
411 "return {" | 412 "return {" |
412 "1: 'foo'," | 413 "1: 'foo'," |
413 "'2': 'bar'," | 414 "'2': 'bar'," |
414 "true: 'baz'," | 415 "true: 'baz'," |
415 "false: 'qux'," | 416 "false: 'qux'," |
416 "null: 'quux'," | 417 "null: 'quux'," |
417 "undefined: 'oops'" | 418 "undefined: 'oops'" |
418 "};" | 419 "};" |
419 "})();"; | 420 "})();"; |
420 | 421 |
421 v8::Handle<v8::Script> script( | 422 v8::Handle<v8::Script> script( |
422 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source))); | 423 v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source))); |
423 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); | 424 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); |
424 ASSERT_FALSE(object.IsEmpty()); | 425 ASSERT_FALSE(object.IsEmpty()); |
425 | 426 |
426 PP_Var actual; | 427 PP_Var actual; |
427 ASSERT_TRUE(FromV8ValueSync(object, | 428 ASSERT_TRUE(FromV8ValueSync( |
428 v8::Local<v8::Context>::New(isolate_, context_), &actual)); | 429 object, v8::Local<v8::Context>::New(isolate_, context_), &actual)); |
429 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); | 430 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); |
430 | 431 |
431 scoped_refptr<DictionaryVar> expected(new DictionaryVar); | 432 scoped_refptr<DictionaryVar> expected(new DictionaryVar); |
432 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); | 433 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); |
433 expected->SetWithStringKey("1", foo.get()); | 434 expected->SetWithStringKey("1", foo.get()); |
434 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); | 435 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); |
435 expected->SetWithStringKey("2", bar.get()); | 436 expected->SetWithStringKey("2", bar.get()); |
436 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); | 437 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); |
437 expected->SetWithStringKey("true", baz.get()); | 438 expected->SetWithStringKey("true", baz.get()); |
438 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); | 439 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); |
439 expected->SetWithStringKey("false", qux.get()); | 440 expected->SetWithStringKey("false", qux.get()); |
440 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); | 441 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); |
441 expected->SetWithStringKey("null", quux.get()); | 442 expected->SetWithStringKey("null", quux.get()); |
442 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); | 443 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); |
443 expected->SetWithStringKey("undefined", oops.get()); | 444 expected->SetWithStringKey("undefined", oops.get()); |
444 ScopedPPVar release_expected( | 445 ScopedPPVar release_expected(ScopedPPVar::PassRef(), expected->GetPPVar()); |
445 ScopedPPVar::PassRef(), expected->GetPPVar()); | |
446 | 446 |
447 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get(), true)); | 447 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get(), true)); |
448 } | 448 } |
449 } | 449 } |
450 | 450 |
451 } // namespace content | 451 } // namespace content |
OLD | NEW |