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 |