| 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 "webkit/plugins/ppapi/v8_var_converter.h" | 5 #include "webkit/plugins/ppapi/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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 context_ = v8::Persistent<v8::Context>( | 146 context_ = v8::Persistent<v8::Context>( |
| 147 isolate, v8::Context::New(isolate, NULL, global)); | 147 isolate, v8::Context::New(isolate, NULL, global)); |
| 148 } | 148 } |
| 149 virtual void TearDown() { | 149 virtual void TearDown() { |
| 150 context_.Dispose(context_->GetIsolate()); | 150 context_.Dispose(context_->GetIsolate()); |
| 151 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); | 151 ASSERT_TRUE(PpapiGlobals::Get()->GetVarTracker()->GetLiveVars().empty()); |
| 152 ProxyLock::Release(); | 152 ProxyLock::Release(); |
| 153 } | 153 } |
| 154 | 154 |
| 155 protected: | 155 protected: |
| 156 bool RoundTrip(const PP_Var& var, PP_Var* result) { | 156 bool RoundTrip(const PP_Var& var, PP_Var* result, bool allow_cycles) { |
| 157 V8VarConverter converter; | 157 V8VarConverter converter(allow_cycles); |
| 158 v8::Context::Scope context_scope(context_); | 158 v8::Context::Scope context_scope(context_); |
| 159 v8::HandleScope handle_scope; | 159 v8::HandleScope handle_scope; |
| 160 v8::Handle<v8::Value> v8_result; | 160 v8::Handle<v8::Value> v8_result; |
| 161 if (!converter.ToV8Value(var, context_, &v8_result)) | 161 if (!converter.ToV8Value(var, context_, &v8_result)) |
| 162 return false; | 162 return false; |
| 163 if (!Equals(var, v8_result)) | 163 if (!Equals(var, v8_result)) |
| 164 return false; | 164 return false; |
| 165 if (!converter.FromV8Value(v8_result, context_, result)) | 165 if (!converter.FromV8Value(v8_result, context_, result)) |
| 166 return false; | 166 return false; |
| 167 return true; | 167 return true; |
| 168 } | 168 } |
| 169 | 169 |
| 170 // Assumes a ref for var. | 170 // Assumes a ref for var. |
| 171 bool RoundTripAndCompare(const PP_Var& var) { | 171 bool RoundTripAndCompare(const PP_Var& var) { |
| 172 ScopedPPVar expected(ScopedPPVar::PassRef(), var); | 172 ScopedPPVar expected(ScopedPPVar::PassRef(), var); |
| 173 PP_Var actual_var; | 173 PP_Var actual_var; |
| 174 if (!RoundTrip(expected.get(), &actual_var)) | 174 if (!RoundTrip(expected.get(), &actual_var, false)) |
| 175 return false; | 175 return false; |
| 176 ScopedPPVar actual(ScopedPPVar::PassRef(), actual_var); | 176 ScopedPPVar actual(ScopedPPVar::PassRef(), actual_var); |
| 177 return TestEqual(expected.get(), actual.get()); | 177 return TestEqual(expected.get(), actual.get()); |
| 178 } | 178 } |
| 179 | 179 |
| 180 // Context for the JavaScript in the test. | 180 // Context for the JavaScript in the test. |
| 181 v8::Persistent<v8::Context> context_; | 181 v8::Persistent<v8::Context> context_; |
| 182 | 182 |
| 183 private: | 183 private: |
| 184 TestGlobals globals_; | 184 TestGlobals globals_; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); | 262 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); |
| 263 | 263 |
| 264 // Array with dictionary. | 264 // Array with dictionary. |
| 265 array->Set(index++, release_dictionary.get()); | 265 array->Set(index++, release_dictionary.get()); |
| 266 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 266 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
| 267 | 267 |
| 268 // Array with dictionary with array. | 268 // Array with dictionary with array. |
| 269 array2->Set(0, PP_MakeInt32(100)); | 269 array2->Set(0, PP_MakeInt32(100)); |
| 270 dictionary->SetWithStringKey("9", release_array2.get()); | 270 dictionary->SetWithStringKey("9", release_array2.get()); |
| 271 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); | 271 EXPECT_TRUE(RoundTripAndCompare(array->GetPPVar())); |
| 272 } |
| 273 |
| 274 TEST_F(V8VarConverterTest, Cycles) { |
| 275 v8::Context::Scope context_scope(context_); |
| 276 v8::HandleScope handle_scope; |
| 277 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); |
| 278 ScopedPPVar release_dictionary(ScopedPPVar::PassRef(), |
| 279 dictionary->GetPPVar()); |
| 280 scoped_refptr<ArrayVar> array(new ArrayVar); |
| 281 ScopedPPVar release_array(ScopedPPVar::PassRef(), array->GetPPVar()); |
| 282 |
| 283 dictionary->SetWithStringKey("1", PP_MakeUndefined()); |
| 284 dictionary->SetWithStringKey("2", PP_MakeNull()); |
| 285 dictionary->SetWithStringKey("3", PP_MakeInt32(-100)); |
| 286 dictionary->SetWithStringKey("4", PP_MakeBool(PP_TRUE)); |
| 287 dictionary->SetWithStringKey("5", PP_MakeDouble(-103.52)); |
| 288 dictionary->SetWithStringKey("6", release_array.get()); |
| 289 |
| 290 array->Set(0, PP_MakeUndefined()); |
| 291 array->Set(1, PP_MakeNull()); |
| 292 array->Set(2, PP_MakeInt32(100)); |
| 293 array->Set(3, PP_MakeBool(PP_FALSE)); |
| 294 array->Set(4, PP_MakeDouble(0.123)); |
| 295 array->Set(5, release_dictionary.get()); |
| 296 |
| 297 V8VarConverter converter_with_cycles(true); |
| 298 V8VarConverter converter_without_cycles(false); |
| 299 PP_Var var_result; |
| 300 v8::Handle<v8::Value> v8_result; |
| 272 | 301 |
| 273 // Array <-> dictionary cycle. | 302 // Array <-> dictionary cycle. |
| 274 dictionary->SetWithStringKey("10", release_array.get()); | 303 dictionary->SetWithStringKey("6", release_array.get()); |
| 275 PP_Var result_var; | 304 ASSERT_FALSE(converter_without_cycles.ToV8Value(release_dictionary.get(), |
| 276 EXPECT_TRUE(RoundTrip(release_dictionary.get(), &result_var)); | 305 context_, &v8_result)); |
| 277 ScopedPPVar result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); | 306 ASSERT_TRUE(converter_with_cycles.ToV8Value(release_dictionary.get(), |
| 278 EXPECT_TRUE(TestEqual(release_dictionary.get(), result.get())); | 307 context_, &v8_result)); |
| 308 ASSERT_TRUE(Equals(release_dictionary.get(), v8_result)); |
| 309 ASSERT_FALSE(converter_without_cycles.FromV8Value(v8_result, |
| 310 context_, &var_result)); |
| 311 ASSERT_TRUE(converter_with_cycles.FromV8Value(v8_result, |
| 312 context_, &var_result)); |
| 313 ScopedPPVar release_result = ScopedPPVar(ScopedPPVar::PassRef(), var_result); |
| 314 EXPECT_TRUE(TestEqual(release_dictionary.get(), release_result.get())); |
| 279 // Break the cycle. | 315 // Break the cycle. |
| 280 // TODO(raymes): We need some better machinery for releasing vars with | 316 // TODO(raymes): We need some better machinery for releasing vars with |
| 281 // cycles. Remove the code below once we have that. | 317 // cycles. Remove the code below once we have that. |
| 282 dictionary->DeleteWithStringKey("10"); | 318 dictionary->DeleteWithStringKey("6"); |
| 283 DictionaryVar* result_dictionary = DictionaryVar::FromPPVar(result.get()); | 319 DictionaryVar* result_dictionary = DictionaryVar::FromPPVar( |
| 284 result_dictionary->DeleteWithStringKey("10"); | 320 release_result.get()); |
| 321 result_dictionary->DeleteWithStringKey("6"); |
| 285 | 322 |
| 286 // Array with self references. | 323 // Array with self references. |
| 287 array->Set(index, release_array.get()); | 324 array->Set(5, release_array.get()); |
| 288 EXPECT_TRUE(RoundTrip(release_array.get(), &result_var)); | 325 ASSERT_FALSE(converter_without_cycles.ToV8Value(release_array.get(), |
| 289 result = ScopedPPVar(ScopedPPVar::PassRef(), result_var); | 326 context_, &v8_result)); |
| 290 EXPECT_TRUE(TestEqual(release_array.get(), result.get())); | 327 ASSERT_TRUE(converter_with_cycles.ToV8Value(release_array.get(), |
| 328 context_, &v8_result)); |
| 329 ASSERT_TRUE(Equals(release_array.get(), v8_result)); |
| 330 ASSERT_FALSE(converter_without_cycles.FromV8Value(v8_result, |
| 331 context_, &var_result)); |
| 332 ASSERT_TRUE(converter_with_cycles.FromV8Value(v8_result, |
| 333 context_, &var_result)); |
| 334 release_result = ScopedPPVar(ScopedPPVar::PassRef(), var_result); |
| 335 EXPECT_TRUE(TestEqual(release_array.get(), release_result.get())); |
| 291 // Break the self reference. | 336 // Break the self reference. |
| 292 array->Set(index, PP_MakeUndefined()); | 337 array->Set(5, PP_MakeUndefined()); |
| 293 ArrayVar* result_array = ArrayVar::FromPPVar(result.get()); | 338 ArrayVar* result_array = ArrayVar::FromPPVar(release_result.get()); |
| 294 result_array->Set(index, PP_MakeUndefined()); | 339 result_array->Set(5, PP_MakeUndefined()); |
| 295 } | 340 } |
| 296 | 341 |
| 297 TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { | 342 TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) { |
| 298 { | 343 { |
| 299 // Test keys with '.'. | 344 // Test keys with '.'. |
| 300 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); | 345 scoped_refptr<DictionaryVar> dictionary(new DictionaryVar); |
| 301 dictionary->SetWithStringKey(".", PP_MakeUndefined()); | 346 dictionary->SetWithStringKey(".", PP_MakeUndefined()); |
| 302 dictionary->SetWithStringKey("x.y", PP_MakeUndefined()); | 347 dictionary->SetWithStringKey("x.y", PP_MakeUndefined()); |
| 303 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); | 348 EXPECT_TRUE(RoundTripAndCompare(dictionary->GetPPVar())); |
| 304 } | 349 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 316 "false: 'qux'," | 361 "false: 'qux'," |
| 317 "null: 'quux'," | 362 "null: 'quux'," |
| 318 "undefined: 'oops'" | 363 "undefined: 'oops'" |
| 319 "};" | 364 "};" |
| 320 "})();"; | 365 "})();"; |
| 321 | 366 |
| 322 v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); | 367 v8::Handle<v8::Script> script(v8::Script::New(v8::String::New(source))); |
| 323 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); | 368 v8::Handle<v8::Object> object = script->Run().As<v8::Object>(); |
| 324 ASSERT_FALSE(object.IsEmpty()); | 369 ASSERT_FALSE(object.IsEmpty()); |
| 325 | 370 |
| 326 V8VarConverter converter; | 371 V8VarConverter converter(false); |
| 327 PP_Var actual; | 372 PP_Var actual; |
| 328 ASSERT_TRUE(converter.FromV8Value(object, context_, &actual)); | 373 ASSERT_TRUE(converter.FromV8Value(object, context_, &actual)); |
| 329 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); | 374 ScopedPPVar release_actual(ScopedPPVar::PassRef(), actual); |
| 330 | 375 |
| 331 scoped_refptr<DictionaryVar> expected(new DictionaryVar); | 376 scoped_refptr<DictionaryVar> expected(new DictionaryVar); |
| 332 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); | 377 ScopedPPVar foo(ScopedPPVar::PassRef(), StringVar::StringToPPVar("foo")); |
| 333 expected->SetWithStringKey("1", foo.get()); | 378 expected->SetWithStringKey("1", foo.get()); |
| 334 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); | 379 ScopedPPVar bar(ScopedPPVar::PassRef(), StringVar::StringToPPVar("bar")); |
| 335 expected->SetWithStringKey("2", bar.get()); | 380 expected->SetWithStringKey("2", bar.get()); |
| 336 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); | 381 ScopedPPVar baz(ScopedPPVar::PassRef(), StringVar::StringToPPVar("baz")); |
| 337 expected->SetWithStringKey("true", baz.get()); | 382 expected->SetWithStringKey("true", baz.get()); |
| 338 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); | 383 ScopedPPVar qux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("qux")); |
| 339 expected->SetWithStringKey("false", qux.get()); | 384 expected->SetWithStringKey("false", qux.get()); |
| 340 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); | 385 ScopedPPVar quux(ScopedPPVar::PassRef(), StringVar::StringToPPVar("quux")); |
| 341 expected->SetWithStringKey("null", quux.get()); | 386 expected->SetWithStringKey("null", quux.get()); |
| 342 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); | 387 ScopedPPVar oops(ScopedPPVar::PassRef(), StringVar::StringToPPVar("oops")); |
| 343 expected->SetWithStringKey("undefined", oops.get()); | 388 expected->SetWithStringKey("undefined", oops.get()); |
| 344 ScopedPPVar release_expected( | 389 ScopedPPVar release_expected( |
| 345 ScopedPPVar::PassRef(), expected->GetPPVar()); | 390 ScopedPPVar::PassRef(), expected->GetPPVar()); |
| 346 | 391 |
| 347 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get())); | 392 ASSERT_TRUE(TestEqual(release_expected.get(), release_actual.get())); |
| 348 } | 393 } |
| 349 } | 394 } |
| 350 | 395 |
| 351 } // namespace ppapi | 396 } // namespace ppapi |
| 352 } // namespace webkit | 397 } // namespace webkit |
| OLD | NEW |