1 // Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4
5 #include <sstream>
6
7 #include "include/base/cef_callback.h"
8 #include "include/cef_task.h"
9 #include "include/cef_v8.h"
10 #include "include/wrapper/cef_closure_task.h"
11 #include "tests/ceftests/test_handler.h"
12 #include "tests/gtest/include/gtest/gtest.h"
13 #include "tests/shared/browser/client_app_browser.h"
14 #include "tests/shared/renderer/client_app_renderer.h"
15
16 using client::ClientAppBrowser;
17 using client::ClientAppRenderer;
18
19 // How to add a new test:
20 // 1. Add a new value to the V8TestMode enumeration.
21 // 2. Add a method that implements the test in V8RendererTest.
22 // 3. Add a case for the new enumeration value in V8RendererTest::RunTest.
23 // 4. Add a line for the test in the "Define the tests" section at the bottom of
24 // the file.
25
26 namespace {
27
28 // Unique values for V8 tests.
29 const char kV8TestUrl[] = "http://tests/V8Test.Test";
30 const char kV8BindingTestUrl[] = "http://tests/V8Test.BindingTest";
31 const char kV8ContextParentTestUrl[] = "http://tests/V8Test.ContextParentTest";
32 const char kV8ContextChildTestUrl[] = "http://tests/V8Test.ContextChildTest";
33 const char kV8NavTestUrl[] = "http://tests/V8Test.NavTest";
34 const char kV8ContextEvalCspBypassUnsafeEval[] =
35 "http://tests/V8Test.ContextEvalCspBypassUnsafeEval";
36 const char kV8ContextEvalCspBypassSandbox[] =
37 "http://tests/V8Test.ContextEvalCspBypassSandbox";
38 const char kV8OnUncaughtExceptionTestUrl[] =
39 "http://tests/V8Test.OnUncaughtException";
40 const char kV8HandlerCallOnReleasedContextUrl[] =
41 "http://tests/V8Test.HandlerCallOnReleasedContext/main.html";
42 const char kV8HandlerCallOnReleasedContextChildUrl[] =
43 "http://tests/V8Test.HandlerCallOnReleasedContext/child.html";
44 const char kV8TestMsg[] = "V8Test.Test";
45 const char kV8TestCmdKey[] = "v8-test";
46 const char kV8RunTestMsg[] = "V8Test.RunTest";
47
48 enum V8TestMode {
49 V8TEST_NONE = 0,
50 V8TEST_NULL_CREATE,
51 V8TEST_BOOL_CREATE,
52 V8TEST_INT_CREATE,
53 V8TEST_UINT_CREATE,
54 V8TEST_DOUBLE_CREATE,
55 V8TEST_DATE_CREATE,
56 V8TEST_STRING_CREATE,
57 V8TEST_EMPTY_STRING_CREATE,
58 V8TEST_ARRAY_CREATE,
59 V8TEST_ARRAY_VALUE,
60 V8TEST_ARRAY_BUFFER,
61 V8TEST_ARRAY_BUFFER_VALUE,
62 V8TEST_OBJECT_CREATE,
63 V8TEST_OBJECT_USERDATA,
64 V8TEST_OBJECT_ACCESSOR,
65 V8TEST_OBJECT_ACCESSOR_EXCEPTION,
66 V8TEST_OBJECT_ACCESSOR_FAIL,
67 V8TEST_OBJECT_ACCESSOR_READONLY,
68 V8TEST_OBJECT_INTERCEPTOR,
69 V8TEST_OBJECT_INTERCEPTOR_FAIL,
70 V8TEST_OBJECT_INTERCEPTOR_EXCEPTION,
71 V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR,
72 V8TEST_OBJECT_VALUE,
73 V8TEST_OBJECT_VALUE_READONLY,
74 V8TEST_OBJECT_VALUE_ENUM,
75 V8TEST_OBJECT_VALUE_DONTENUM,
76 V8TEST_OBJECT_VALUE_DELETE,
77 V8TEST_OBJECT_VALUE_DONTDELETE,
78 V8TEST_OBJECT_VALUE_EMPTYKEY,
79 V8TEST_FUNCTION_CREATE,
80 V8TEST_FUNCTION_HANDLER,
81 V8TEST_FUNCTION_HANDLER_EXCEPTION,
82 V8TEST_FUNCTION_HANDLER_FAIL,
83 V8TEST_FUNCTION_HANDLER_NO_OBJECT,
84 V8TEST_FUNCTION_HANDLER_WITH_CONTEXT,
85 V8TEST_FUNCTION_HANDLER_EMPTY_STRING,
86 V8TEST_CONTEXT_EVAL,
87 V8TEST_CONTEXT_EVAL_EXCEPTION,
88 V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL,
89 V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX,
90 V8TEST_CONTEXT_ENTERED,
91 V8TEST_BINDING,
92 V8TEST_STACK_TRACE,
93 V8TEST_ON_UNCAUGHT_EXCEPTION,
94 V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS,
95 V8TEST_EXTENSION,
96 V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT,
97 };
98
99 // Renderer side.
100 class V8RendererTest : public ClientAppRenderer::Delegate,
101 public CefLoadHandler {
102 public:
V8RendererTest()103 V8RendererTest() : test_mode_(V8TEST_NONE) {}
104
105 // Run a test when the process message is received from the browser.
RunTest()106 void RunTest() {
107 switch (test_mode_) {
108 case V8TEST_NULL_CREATE:
109 RunNullCreateTest();
110 break;
111 case V8TEST_BOOL_CREATE:
112 RunBoolCreateTest();
113 break;
114 case V8TEST_INT_CREATE:
115 RunIntCreateTest();
116 break;
117 case V8TEST_UINT_CREATE:
118 RunUIntCreateTest();
119 break;
120 case V8TEST_DOUBLE_CREATE:
121 RunDoubleCreateTest();
122 break;
123 case V8TEST_DATE_CREATE:
124 RunDateCreateTest();
125 break;
126 case V8TEST_STRING_CREATE:
127 RunStringCreateTest();
128 break;
129 case V8TEST_EMPTY_STRING_CREATE:
130 RunEmptyStringCreateTest();
131 break;
132 case V8TEST_ARRAY_CREATE:
133 RunArrayCreateTest();
134 break;
135 case V8TEST_ARRAY_VALUE:
136 RunArrayValueTest();
137 break;
138 case V8TEST_ARRAY_BUFFER:
139 RunArrayBufferTest();
140 break;
141 case V8TEST_ARRAY_BUFFER_VALUE:
142 RunArrayBufferValueTest();
143 break;
144 case V8TEST_OBJECT_CREATE:
145 RunObjectCreateTest();
146 break;
147 case V8TEST_OBJECT_USERDATA:
148 RunObjectUserDataTest();
149 break;
150 case V8TEST_OBJECT_ACCESSOR:
151 RunObjectAccessorTest();
152 break;
153 case V8TEST_OBJECT_ACCESSOR_EXCEPTION:
154 RunObjectAccessorExceptionTest();
155 break;
156 case V8TEST_OBJECT_ACCESSOR_FAIL:
157 RunObjectAccessorFailTest();
158 break;
159 case V8TEST_OBJECT_ACCESSOR_READONLY:
160 RunObjectAccessorReadOnlyTest();
161 break;
162 case V8TEST_OBJECT_INTERCEPTOR:
163 RunObjectInterceptorTest();
164 break;
165 case V8TEST_OBJECT_INTERCEPTOR_FAIL:
166 RunObjectInterceptorFailTest();
167 break;
168 case V8TEST_OBJECT_INTERCEPTOR_EXCEPTION:
169 RunObjectInterceptorExceptionTest();
170 break;
171 case V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR:
172 RunObjectInterceptorAndAccessorTest();
173 break;
174 case V8TEST_OBJECT_VALUE:
175 RunObjectValueTest();
176 break;
177 case V8TEST_OBJECT_VALUE_READONLY:
178 RunObjectValueReadOnlyTest();
179 break;
180 case V8TEST_OBJECT_VALUE_ENUM:
181 RunObjectValueEnumTest();
182 break;
183 case V8TEST_OBJECT_VALUE_DONTENUM:
184 RunObjectValueDontEnumTest();
185 break;
186 case V8TEST_OBJECT_VALUE_DELETE:
187 RunObjectValueDeleteTest();
188 break;
189 case V8TEST_OBJECT_VALUE_DONTDELETE:
190 RunObjectValueDontDeleteTest();
191 break;
192 case V8TEST_OBJECT_VALUE_EMPTYKEY:
193 RunObjectValueEmptyKeyTest();
194 break;
195 case V8TEST_FUNCTION_CREATE:
196 RunFunctionCreateTest();
197 break;
198 case V8TEST_FUNCTION_HANDLER:
199 RunFunctionHandlerTest();
200 break;
201 case V8TEST_FUNCTION_HANDLER_EXCEPTION:
202 RunFunctionHandlerExceptionTest();
203 break;
204 case V8TEST_FUNCTION_HANDLER_FAIL:
205 RunFunctionHandlerFailTest();
206 break;
207 case V8TEST_FUNCTION_HANDLER_NO_OBJECT:
208 RunFunctionHandlerNoObjectTest();
209 break;
210 case V8TEST_FUNCTION_HANDLER_WITH_CONTEXT:
211 RunFunctionHandlerWithContextTest();
212 break;
213 case V8TEST_FUNCTION_HANDLER_EMPTY_STRING:
214 RunFunctionHandlerEmptyStringTest();
215 break;
216 case V8TEST_CONTEXT_EVAL:
217 RunContextEvalTest();
218 break;
219 case V8TEST_CONTEXT_EVAL_EXCEPTION:
220 RunContextEvalExceptionTest();
221 break;
222 case V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL:
223 RunContextEvalCspBypassUnsafeEval();
224 break;
225 case V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX:
226 RunContextEvalCspBypassSandbox();
227 break;
228 case V8TEST_CONTEXT_ENTERED:
229 RunContextEnteredTest();
230 break;
231 case V8TEST_BINDING:
232 RunBindingTest();
233 break;
234 case V8TEST_STACK_TRACE:
235 RunStackTraceTest();
236 break;
237 case V8TEST_ON_UNCAUGHT_EXCEPTION:
238 RunOnUncaughtExceptionTest();
239 break;
240 case V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT:
241 break;
242 default:
243 // Was a startup test.
244 EXPECT_TRUE(startup_test_success_);
245 DestroyTest();
246 break;
247 }
248 }
249
250 // Run a test on render process startup.
RunStartupTest()251 void RunStartupTest() {
252 switch (test_mode_) {
253 case V8TEST_EXTENSION:
254 RunExtensionTest();
255 break;
256 default:
257 break;
258 }
259 }
260
RunNullCreateTest()261 void RunNullCreateTest() {
262 CefRefPtr<CefV8Value> value = CefV8Value::CreateNull();
263 EXPECT_TRUE(value.get());
264 EXPECT_TRUE(value->IsNull());
265
266 EXPECT_FALSE(value->IsUndefined());
267 EXPECT_FALSE(value->IsArray());
268 EXPECT_FALSE(value->IsBool());
269 EXPECT_FALSE(value->IsDate());
270 EXPECT_FALSE(value->IsDouble());
271 EXPECT_FALSE(value->IsFunction());
272 EXPECT_FALSE(value->IsInt());
273 EXPECT_FALSE(value->IsUInt());
274 EXPECT_FALSE(value->IsObject());
275 EXPECT_FALSE(value->IsString());
276
277 DestroyTest();
278 }
279
RunBoolCreateTest()280 void RunBoolCreateTest() {
281 CefRefPtr<CefV8Value> value = CefV8Value::CreateBool(true);
282 EXPECT_TRUE(value.get());
283 EXPECT_TRUE(value->IsBool());
284 EXPECT_EQ(true, value->GetBoolValue());
285
286 EXPECT_FALSE(value->IsUndefined());
287 EXPECT_FALSE(value->IsArray());
288 EXPECT_FALSE(value->IsDate());
289 EXPECT_FALSE(value->IsDouble());
290 EXPECT_FALSE(value->IsFunction());
291 EXPECT_FALSE(value->IsInt());
292 EXPECT_FALSE(value->IsUInt());
293 EXPECT_FALSE(value->IsNull());
294 EXPECT_FALSE(value->IsObject());
295 EXPECT_FALSE(value->IsString());
296
297 DestroyTest();
298 }
299
RunIntCreateTest()300 void RunIntCreateTest() {
301 CefRefPtr<CefV8Value> value = CefV8Value::CreateInt(12);
302 EXPECT_TRUE(value.get());
303 EXPECT_TRUE(value->IsInt());
304 EXPECT_TRUE(value->IsUInt());
305 EXPECT_TRUE(value->IsDouble());
306 EXPECT_EQ(12, value->GetIntValue());
307 EXPECT_EQ((uint32)12, value->GetUIntValue());
308 EXPECT_EQ(12, value->GetDoubleValue());
309
310 EXPECT_FALSE(value->IsUndefined());
311 EXPECT_FALSE(value->IsArray());
312 EXPECT_FALSE(value->IsBool());
313 EXPECT_FALSE(value->IsDate());
314 EXPECT_FALSE(value->IsFunction());
315 EXPECT_FALSE(value->IsNull());
316 EXPECT_FALSE(value->IsObject());
317 EXPECT_FALSE(value->IsString());
318
319 DestroyTest();
320 }
321
RunUIntCreateTest()322 void RunUIntCreateTest() {
323 CefRefPtr<CefV8Value> value = CefV8Value::CreateUInt(12);
324 EXPECT_TRUE(value.get());
325 EXPECT_TRUE(value->IsInt());
326 EXPECT_TRUE(value->IsUInt());
327 EXPECT_TRUE(value->IsDouble());
328 EXPECT_EQ(12, value->GetIntValue());
329 EXPECT_EQ((uint32)12, value->GetUIntValue());
330 EXPECT_EQ(12, value->GetDoubleValue());
331
332 EXPECT_FALSE(value->IsUndefined());
333 EXPECT_FALSE(value->IsArray());
334 EXPECT_FALSE(value->IsBool());
335 EXPECT_FALSE(value->IsDate());
336 EXPECT_FALSE(value->IsFunction());
337 EXPECT_FALSE(value->IsNull());
338 EXPECT_FALSE(value->IsObject());
339 EXPECT_FALSE(value->IsString());
340
341 DestroyTest();
342 }
343
RunDoubleCreateTest()344 void RunDoubleCreateTest() {
345 CefRefPtr<CefV8Value> value = CefV8Value::CreateDouble(12.1223);
346 EXPECT_TRUE(value.get());
347 EXPECT_TRUE(value->IsDouble());
348 EXPECT_EQ(12.1223, value->GetDoubleValue());
349
350 EXPECT_FALSE(value->IsUndefined());
351 EXPECT_FALSE(value->IsArray());
352 EXPECT_FALSE(value->IsBool());
353 EXPECT_FALSE(value->IsDate());
354 EXPECT_FALSE(value->IsFunction());
355 EXPECT_FALSE(value->IsInt());
356 EXPECT_FALSE(value->IsUInt());
357 EXPECT_FALSE(value->IsNull());
358 EXPECT_FALSE(value->IsObject());
359 EXPECT_FALSE(value->IsString());
360
361 DestroyTest();
362 }
363
RunDateCreateTest()364 void RunDateCreateTest() {
365 CefRefPtr<CefV8Context> context = GetContext();
366
367 CefTime date;
368 date.year = 2200;
369 date.month = 4;
370 #if !defined(OS_MAC)
371 date.day_of_week = 5;
372 #endif
373 date.day_of_month = 11;
374 date.hour = 20;
375 date.minute = 15;
376 date.second = 42;
377
378 // Enter the V8 context.
379 EXPECT_TRUE(context->Enter());
380
381 CefRefPtr<CefV8Value> value = CefV8Value::CreateDate(date);
382 EXPECT_TRUE(value.get());
383 EXPECT_TRUE(value->IsDate());
384 EXPECT_EQ(date.GetTimeT(), value->GetDateValue().GetTimeT());
385
386 // Exit the V8 context.
387 EXPECT_TRUE(context->Exit());
388
389 EXPECT_FALSE(value->IsUndefined());
390 EXPECT_FALSE(value->IsArray());
391 EXPECT_FALSE(value->IsBool());
392 EXPECT_FALSE(value->IsDouble());
393 EXPECT_FALSE(value->IsFunction());
394 EXPECT_FALSE(value->IsInt());
395 EXPECT_FALSE(value->IsUInt());
396 EXPECT_FALSE(value->IsObject());
397 EXPECT_FALSE(value->IsNull());
398 EXPECT_FALSE(value->IsString());
399
400 DestroyTest();
401 }
402
RunStringCreateTest()403 void RunStringCreateTest() {
404 CefRefPtr<CefV8Value> value = CefV8Value::CreateString("My string");
405 EXPECT_TRUE(value.get());
406 EXPECT_TRUE(value->IsString());
407 EXPECT_STREQ("My string", value->GetStringValue().ToString().c_str());
408
409 EXPECT_FALSE(value->IsUndefined());
410 EXPECT_FALSE(value->IsArray());
411 EXPECT_FALSE(value->IsBool());
412 EXPECT_FALSE(value->IsDate());
413 EXPECT_FALSE(value->IsDouble());
414 EXPECT_FALSE(value->IsFunction());
415 EXPECT_FALSE(value->IsInt());
416 EXPECT_FALSE(value->IsUInt());
417 EXPECT_FALSE(value->IsNull());
418 EXPECT_FALSE(value->IsObject());
419
420 DestroyTest();
421 }
422
RunEmptyStringCreateTest()423 void RunEmptyStringCreateTest() {
424 CefRefPtr<CefV8Value> value = CefV8Value::CreateString(CefString());
425 EXPECT_TRUE(value.get());
426 EXPECT_TRUE(value->IsString());
427 EXPECT_STREQ("", value->GetStringValue().ToString().c_str());
428
429 EXPECT_FALSE(value->IsUndefined());
430 EXPECT_FALSE(value->IsArray());
431 EXPECT_FALSE(value->IsBool());
432 EXPECT_FALSE(value->IsDate());
433 EXPECT_FALSE(value->IsDouble());
434 EXPECT_FALSE(value->IsFunction());
435 EXPECT_FALSE(value->IsInt());
436 EXPECT_FALSE(value->IsUInt());
437 EXPECT_FALSE(value->IsNull());
438 EXPECT_FALSE(value->IsObject());
439
440 DestroyTest();
441 }
442
RunArrayCreateTest()443 void RunArrayCreateTest() {
444 CefRefPtr<CefV8Context> context = GetContext();
445
446 // Enter the V8 context.
447 EXPECT_TRUE(context->Enter());
448
449 CefRefPtr<CefV8Value> value = CefV8Value::CreateArray(2);
450 EXPECT_TRUE(value.get());
451 EXPECT_TRUE(value->IsArray());
452 EXPECT_TRUE(value->IsObject());
453 EXPECT_EQ(2, value->GetArrayLength());
454 EXPECT_FALSE(value->HasValue(0));
455 EXPECT_FALSE(value->HasValue(1));
456
457 // Exit the V8 context.
458 EXPECT_TRUE(context->Exit());
459
460 EXPECT_FALSE(value->IsUndefined());
461 EXPECT_FALSE(value->IsBool());
462 EXPECT_FALSE(value->IsDate());
463 EXPECT_FALSE(value->IsDouble());
464 EXPECT_FALSE(value->IsFunction());
465 EXPECT_FALSE(value->IsInt());
466 EXPECT_FALSE(value->IsUInt());
467 EXPECT_FALSE(value->IsNull());
468 EXPECT_FALSE(value->IsString());
469
470 DestroyTest();
471 }
472
RunArrayValueTest()473 void RunArrayValueTest() {
474 CefRefPtr<CefV8Context> context = GetContext();
475
476 // Enter the V8 context.
477 EXPECT_TRUE(context->Enter());
478
479 CefRefPtr<CefV8Value> value = CefV8Value::CreateArray(0);
480 EXPECT_TRUE(value.get());
481 EXPECT_TRUE(value->IsArray());
482 EXPECT_EQ(0, value->GetArrayLength());
483
484 // Test addng values.
485 EXPECT_FALSE(value->HasValue(0));
486 EXPECT_FALSE(value->HasValue(1));
487
488 EXPECT_TRUE(value->SetValue(0, CefV8Value::CreateInt(10)));
489 EXPECT_FALSE(value->HasException());
490 EXPECT_TRUE(value->HasValue(0));
491 EXPECT_FALSE(value->HasValue(1));
492
493 EXPECT_TRUE(value->GetValue(0)->IsInt());
494 EXPECT_EQ(10, value->GetValue(0)->GetIntValue());
495 EXPECT_FALSE(value->HasException());
496 EXPECT_EQ(1, value->GetArrayLength());
497
498 EXPECT_TRUE(value->SetValue(1, CefV8Value::CreateInt(43)));
499 EXPECT_FALSE(value->HasException());
500 EXPECT_TRUE(value->HasValue(0));
501 EXPECT_TRUE(value->HasValue(1));
502
503 EXPECT_TRUE(value->GetValue(1)->IsInt());
504 EXPECT_EQ(43, value->GetValue(1)->GetIntValue());
505 EXPECT_FALSE(value->HasException());
506 EXPECT_EQ(2, value->GetArrayLength());
507
508 EXPECT_TRUE(value->DeleteValue(0));
509 EXPECT_FALSE(value->HasValue(0));
510 EXPECT_TRUE(value->HasValue(1));
511 EXPECT_EQ(2, value->GetArrayLength());
512
513 EXPECT_TRUE(value->DeleteValue(1));
514 EXPECT_FALSE(value->HasValue(0));
515 EXPECT_FALSE(value->HasValue(1));
516 EXPECT_EQ(2, value->GetArrayLength());
517
518 // Exit the V8 context.
519 EXPECT_TRUE(context->Exit());
520
521 DestroyTest();
522 }
523
RunArrayBufferTest()524 void RunArrayBufferTest() {
525 class TestArrayBufferReleaseCallback
526 : public CefV8ArrayBufferReleaseCallback {
527 public:
528 TestArrayBufferReleaseCallback(bool* destructorCalled,
529 bool* releaseBufferCalled)
530 : destructorCalled_(destructorCalled),
531 releaseBufferCalled_(releaseBufferCalled) {}
532
533 ~TestArrayBufferReleaseCallback() { *destructorCalled_ = true; }
534
535 void ReleaseBuffer(void* buffer) override {
536 *releaseBufferCalled_ = true;
537 }
538
539 IMPLEMENT_REFCOUNTING(TestArrayBufferReleaseCallback);
540
541 private:
542 bool* destructorCalled_;
543 bool* releaseBufferCalled_;
544 };
545
546 CefRefPtr<CefV8Context> context = GetContext();
547
548 bool destructorCalled = false;
549 bool releaseBufferCalled = false;
550 // Enter the V8 context.
551 EXPECT_TRUE(context->Enter());
552 {
553 int static_data[16];
554 CefRefPtr<TestArrayBufferReleaseCallback> release_callback =
555 new TestArrayBufferReleaseCallback(&destructorCalled,
556 &releaseBufferCalled);
557 CefRefPtr<CefV8Value> value = CefV8Value::CreateArrayBuffer(
558 static_data, sizeof(static_data), release_callback);
559 EXPECT_TRUE(value.get());
560 EXPECT_TRUE(value->IsArrayBuffer());
561 EXPECT_TRUE(value->IsObject());
562 EXPECT_FALSE(value->HasValue(0));
563 EXPECT_TRUE(value->GetArrayBufferReleaseCallback().get() != nullptr);
564 EXPECT_TRUE(((TestArrayBufferReleaseCallback*)value
565 ->GetArrayBufferReleaseCallback()
566 .get()) == release_callback);
567
568 // |Value| buffer is explicitly freed by NeuterArrayBuffer().
569 EXPECT_FALSE(destructorCalled);
570 EXPECT_FALSE(releaseBufferCalled);
571 EXPECT_TRUE(value->NeuterArrayBuffer());
572 EXPECT_TRUE(releaseBufferCalled);
573 }
574 // Exit the V8 context.
575 EXPECT_TRUE(destructorCalled);
576 EXPECT_TRUE(context->Exit());
577 DestroyTest();
578 }
579
RunArrayBufferValueTest()580 void RunArrayBufferValueTest() {
581 class TestArrayBufferReleaseCallback
582 : public CefV8ArrayBufferReleaseCallback {
583 public:
584 TestArrayBufferReleaseCallback() {}
585
586 ~TestArrayBufferReleaseCallback() {}
587
588 void ReleaseBuffer(void* buffer) override {}
589
590 IMPLEMENT_REFCOUNTING(TestArrayBufferReleaseCallback);
591 };
592
593 CefRefPtr<CefV8Context> context = GetContext();
594
595 // Enter the V8 context.
596 CefRefPtr<CefV8Value> value;
597
598 CefRefPtr<TestArrayBufferReleaseCallback> owner =
599 new TestArrayBufferReleaseCallback();
600 EXPECT_TRUE(context->Enter());
601 int static_data[16];
602 static_data[0] = 3;
603 value =
604 CefV8Value::CreateArrayBuffer(static_data, sizeof(static_data), owner);
605
606 CefRefPtr<CefV8Value> object = context->GetGlobal();
607 EXPECT_TRUE(object.get());
608 object->SetValue("arr", value, V8_PROPERTY_ATTRIBUTE_NONE);
609 std::string test =
610 "let data = new Int32Array(window.arr); data[0] += data.length";
611 CefRefPtr<CefV8Value> retval;
612 CefRefPtr<CefV8Exception> exception;
613 EXPECT_TRUE(context->Eval(test, CefString(), 0, retval, exception));
614 if (exception.get())
615 ADD_FAILURE() << exception->GetMessage().c_str();
616
617 EXPECT_TRUE(static_data[0] == 19);
618 EXPECT_TRUE(value->GetArrayBufferReleaseCallback().get() != nullptr);
619 EXPECT_TRUE(value->NeuterArrayBuffer());
620
621 // Exit the V8 context.
622 EXPECT_TRUE(context->Exit());
623 DestroyTest();
624 }
625
RunObjectCreateTest()626 void RunObjectCreateTest() {
627 CefRefPtr<CefV8Context> context = GetContext();
628
629 // Enter the V8 context.
630 EXPECT_TRUE(context->Enter());
631
632 CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(nullptr, nullptr);
633
634 EXPECT_TRUE(value.get());
635 EXPECT_TRUE(value->IsObject());
636 EXPECT_FALSE(value->GetUserData().get());
637
638 EXPECT_FALSE(value->IsUndefined());
639 EXPECT_FALSE(value->IsArray());
640 EXPECT_FALSE(value->IsBool());
641 EXPECT_FALSE(value->IsDate());
642 EXPECT_FALSE(value->IsDouble());
643 EXPECT_FALSE(value->IsFunction());
644 EXPECT_FALSE(value->IsInt());
645 EXPECT_FALSE(value->IsUInt());
646 EXPECT_FALSE(value->IsNull());
647 EXPECT_FALSE(value->IsString());
648
649 // Exit the V8 context.
650 EXPECT_TRUE(context->Exit());
651
652 DestroyTest();
653 }
654
RunObjectUserDataTest()655 void RunObjectUserDataTest() {
656 CefRefPtr<CefV8Context> context = GetContext();
657
658 class UserData : public CefBaseRefCounted {
659 public:
660 explicit UserData(int value) : value_(value) {}
661 int value_;
662 IMPLEMENT_REFCOUNTING(UserData);
663 };
664
665 // Enter the V8 context.
666 EXPECT_TRUE(context->Enter());
667
668 CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(nullptr, nullptr);
669 EXPECT_TRUE(value.get());
670
671 EXPECT_TRUE(value->SetUserData(new UserData(10)));
672
673 CefRefPtr<CefBaseRefCounted> user_data = value->GetUserData();
674 EXPECT_TRUE(user_data.get());
675 UserData* user_data_impl = static_cast<UserData*>(user_data.get());
676 EXPECT_EQ(10, user_data_impl->value_);
677
678 // Exit the V8 context.
679 EXPECT_TRUE(context->Exit());
680
681 DestroyTest();
682 }
683
RunObjectAccessorTest()684 void RunObjectAccessorTest() {
685 CefRefPtr<CefV8Context> context = GetContext();
686
687 static const char* kName = "val";
688 static const int kValue = 20;
689
690 class Accessor : public CefV8Accessor {
691 public:
692 Accessor() : value_(0) {}
693 bool Get(const CefString& name,
694 const CefRefPtr<CefV8Value> object,
695 CefRefPtr<CefV8Value>& retval,
696 CefString& exception) override {
697 EXPECT_STREQ(kName, name.ToString().c_str());
698
699 EXPECT_TRUE(object.get());
700 EXPECT_TRUE(object->IsSame(object_));
701
702 EXPECT_FALSE(retval.get());
703 EXPECT_TRUE(exception.empty());
704
705 got_get_.yes();
706 retval = CefV8Value::CreateInt(value_);
707 EXPECT_EQ(kValue, retval->GetIntValue());
708 return true;
709 }
710
711 bool Set(const CefString& name,
712 const CefRefPtr<CefV8Value> object,
713 const CefRefPtr<CefV8Value> value,
714 CefString& exception) override {
715 EXPECT_STREQ(kName, name.ToString().c_str());
716
717 EXPECT_TRUE(object.get());
718 EXPECT_TRUE(object->IsSame(object_));
719
720 EXPECT_TRUE(value.get());
721 EXPECT_TRUE(exception.empty());
722
723 got_set_.yes();
724 value_ = value->GetIntValue();
725 EXPECT_EQ(kValue, value_);
726 return true;
727 }
728
729 CefRefPtr<CefV8Value> object_;
730 int value_;
731 TrackCallback got_get_;
732 TrackCallback got_set_;
733
734 IMPLEMENT_REFCOUNTING(Accessor);
735 };
736
737 // Enter the V8 context.
738 EXPECT_TRUE(context->Enter());
739
740 Accessor* accessor = new Accessor;
741 CefRefPtr<CefV8Accessor> accessorPtr(accessor);
742
743 CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, nullptr);
744 EXPECT_TRUE(object.get());
745 accessor->object_ = object;
746
747 EXPECT_FALSE(object->HasValue(kName));
748
749 EXPECT_TRUE(object->SetValue(kName, V8_ACCESS_CONTROL_DEFAULT,
750 V8_PROPERTY_ATTRIBUTE_NONE));
751 EXPECT_FALSE(object->HasException());
752 EXPECT_TRUE(object->HasValue(kName));
753
754 EXPECT_TRUE(object->SetValue(kName, CefV8Value::CreateInt(kValue),
755 V8_PROPERTY_ATTRIBUTE_NONE));
756 EXPECT_FALSE(object->HasException());
757 EXPECT_TRUE(accessor->got_set_);
758 EXPECT_EQ(kValue, accessor->value_);
759
760 CefRefPtr<CefV8Value> val = object->GetValue(kName);
761 EXPECT_FALSE(object->HasException());
762 EXPECT_TRUE(val.get());
763 EXPECT_TRUE(accessor->got_get_);
764 EXPECT_TRUE(val->IsInt());
765 EXPECT_EQ(kValue, val->GetIntValue());
766
767 accessor->object_ = nullptr;
768
769 // Exit the V8 context.
770 EXPECT_TRUE(context->Exit());
771
772 DestroyTest();
773 }
774
RunObjectAccessorExceptionTest()775 void RunObjectAccessorExceptionTest() {
776 CefRefPtr<CefV8Context> context = GetContext();
777
778 static const char* kName = "val";
779 static const char* kGetException = "My get exception";
780 static const char* kSetException = "My set exception";
781 static const char* kGetExceptionMsg = "Uncaught Error: My get exception";
782 static const char* kSetExceptionMsg = "Uncaught Error: My set exception";
783
784 class Accessor : public CefV8Accessor {
785 public:
786 Accessor() {}
787 bool Get(const CefString& name,
788 const CefRefPtr<CefV8Value> object,
789 CefRefPtr<CefV8Value>& retval,
790 CefString& exception) override {
791 got_get_.yes();
792 exception = kGetException;
793 return true;
794 }
795
796 bool Set(const CefString& name,
797 const CefRefPtr<CefV8Value> object,
798 const CefRefPtr<CefV8Value> value,
799 CefString& exception) override {
800 got_set_.yes();
801 exception = kSetException;
802 return true;
803 }
804
805 TrackCallback got_get_;
806 TrackCallback got_set_;
807
808 IMPLEMENT_REFCOUNTING(Accessor);
809 };
810
811 // Enter the V8 context.
812 EXPECT_TRUE(context->Enter());
813
814 CefRefPtr<CefV8Exception> exception;
815 Accessor* accessor = new Accessor;
816 CefRefPtr<CefV8Accessor> accessorPtr(accessor);
817
818 CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, nullptr);
819 EXPECT_TRUE(object.get());
820
821 EXPECT_FALSE(object->HasValue(kName));
822
823 EXPECT_TRUE(object->SetValue(kName, V8_ACCESS_CONTROL_DEFAULT,
824 V8_PROPERTY_ATTRIBUTE_NONE));
825 EXPECT_FALSE(object->HasException());
826 EXPECT_TRUE(object->HasValue(kName));
827
828 EXPECT_FALSE(object->SetValue(kName, CefV8Value::CreateInt(1),
829 V8_PROPERTY_ATTRIBUTE_NONE));
830 EXPECT_TRUE(object->HasException());
831 EXPECT_TRUE(accessor->got_set_);
832 exception = object->GetException();
833 EXPECT_TRUE(exception.get());
834 EXPECT_STREQ(kSetExceptionMsg, exception->GetMessage().ToString().c_str());
835
836 EXPECT_TRUE(object->ClearException());
837 EXPECT_FALSE(object->HasException());
838
839 CefRefPtr<CefV8Value> val = object->GetValue(kName);
840 EXPECT_FALSE(val.get());
841 EXPECT_TRUE(object->HasException());
842 EXPECT_TRUE(accessor->got_get_);
843 exception = object->GetException();
844 EXPECT_TRUE(exception.get());
845 EXPECT_STREQ(kGetExceptionMsg, exception->GetMessage().ToString().c_str());
846
847 // Exit the V8 context.
848 EXPECT_TRUE(context->Exit());
849
850 DestroyTest();
851 }
852
RunObjectAccessorFailTest()853 void RunObjectAccessorFailTest() {
854 CefRefPtr<CefV8Context> context = GetContext();
855
856 static const char* kName = "val";
857
858 class Accessor : public CefV8Accessor {
859 public:
860 Accessor() {}
861 bool Get(const CefString& name,
862 const CefRefPtr<CefV8Value> object,
863 CefRefPtr<CefV8Value>& retval,
864 CefString& exception) override {
865 got_get_.yes();
866 return false;
867 }
868
869 bool Set(const CefString& name,
870 const CefRefPtr<CefV8Value> object,
871 const CefRefPtr<CefV8Value> value,
872 CefString& exception) override {
873 got_set_.yes();
874 return false;
875 }
876
877 TrackCallback got_get_;
878 TrackCallback got_set_;
879
880 IMPLEMENT_REFCOUNTING(Accessor);
881 };
882
883 // Enter the V8 context.
884 EXPECT_TRUE(context->Enter());
885
886 CefRefPtr<CefV8Exception> exception;
887 Accessor* accessor = new Accessor;
888 CefRefPtr<CefV8Accessor> accessorPtr(accessor);
889
890 CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, nullptr);
891 EXPECT_TRUE(object.get());
892
893 EXPECT_FALSE(object->HasValue(kName));
894
895 EXPECT_TRUE(object->SetValue(kName, V8_ACCESS_CONTROL_DEFAULT,
896 V8_PROPERTY_ATTRIBUTE_NONE));
897 EXPECT_FALSE(object->HasException());
898 EXPECT_TRUE(object->HasValue(kName));
899
900 EXPECT_TRUE(object->SetValue(kName, CefV8Value::CreateInt(1),
901 V8_PROPERTY_ATTRIBUTE_NONE));
902 EXPECT_FALSE(object->HasException());
903 EXPECT_TRUE(accessor->got_set_);
904
905 CefRefPtr<CefV8Value> val = object->GetValue(kName);
906 EXPECT_TRUE(val.get());
907 EXPECT_FALSE(object->HasException());
908 EXPECT_TRUE(accessor->got_get_);
909 EXPECT_TRUE(val->IsUndefined());
910
911 // Exit the V8 context.
912 EXPECT_TRUE(context->Exit());
913
914 DestroyTest();
915 }
916
RunObjectAccessorReadOnlyTest()917 void RunObjectAccessorReadOnlyTest() {
918 CefRefPtr<CefV8Context> context = GetContext();
919
920 static const char* kName = "val";
921
922 class Accessor : public CefV8Accessor {
923 public:
924 Accessor() {}
925 bool Get(const CefString& name,
926 const CefRefPtr<CefV8Value> object,
927 CefRefPtr<CefV8Value>& retval,
928 CefString& exception) override {
929 got_get_.yes();
930 return true;
931 }
932
933 bool Set(const CefString& name,
934 const CefRefPtr<CefV8Value> object,
935 const CefRefPtr<CefV8Value> value,
936 CefString& exception) override {
937 got_set_.yes();
938 return true;
939 }
940
941 TrackCallback got_get_;
942 TrackCallback got_set_;
943
944 IMPLEMENT_REFCOUNTING(Accessor);
945 };
946
947 // Enter the V8 context.
948 EXPECT_TRUE(context->Enter());
949
950 CefRefPtr<CefV8Exception> exception;
951 Accessor* accessor = new Accessor;
952 CefRefPtr<CefV8Accessor> accessorPtr(accessor);
953
954 CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, nullptr);
955 EXPECT_TRUE(object.get());
956
957 EXPECT_FALSE(object->HasValue(kName));
958
959 EXPECT_TRUE(object->SetValue(kName, V8_ACCESS_CONTROL_DEFAULT,
960 V8_PROPERTY_ATTRIBUTE_READONLY));
961 EXPECT_FALSE(object->HasException());
962 EXPECT_TRUE(object->HasValue(kName));
963
964 EXPECT_TRUE(object->SetValue(kName, CefV8Value::CreateInt(1),
965 V8_PROPERTY_ATTRIBUTE_NONE));
966 EXPECT_FALSE(object->HasException());
967 EXPECT_FALSE(accessor->got_set_);
968
969 CefRefPtr<CefV8Value> val = object->GetValue(kName);
970 EXPECT_TRUE(val.get());
971 EXPECT_FALSE(object->HasException());
972 EXPECT_TRUE(accessor->got_get_);
973 EXPECT_TRUE(val->IsUndefined());
974
975 // Exit the V8 context.
976 EXPECT_TRUE(context->Exit());
977
978 DestroyTest();
979 }
980
RunObjectInterceptorTest()981 void RunObjectInterceptorTest() {
982 CefRefPtr<CefV8Context> context = GetContext();
983
984 static const char* kName1 = "val1";
985 static const char* kName2 = "val2";
986 static const char* kName3 = "val3";
987
988 static const int kValue1 = 20;
989 static const uint32 kValue2 = 30u;
990 static const char* kValue3 = "40";
991
992 static const int kArray[] = {50, 60, 70};
993
994 class Interceptor : public CefV8Interceptor {
995 public:
996 Interceptor() : value1_(0), value2_(0u), array_() {}
997 virtual bool Get(const CefString& name,
998 const CefRefPtr<CefV8Value> object,
999 CefRefPtr<CefV8Value>& retval,
1000 CefString& exception) override {
1001 EXPECT_TRUE(name.ToString() == kName1 || name.ToString() == kName2 ||
1002 name.ToString() == kName3);
1003
1004 EXPECT_TRUE(object.get());
1005 EXPECT_TRUE(object->IsSame(object_));
1006
1007 EXPECT_FALSE(retval.get());
1008 EXPECT_TRUE(exception.empty());
1009
1010 got_get_byname_.yes();
1011 if (name.ToString() == kName1) {
1012 retval = CefV8Value::CreateInt(value1_);
1013 EXPECT_EQ(kValue1, retval->GetIntValue());
1014 } else if (name.ToString() == kName2) {
1015 retval = CefV8Value::CreateUInt(value2_);
1016 EXPECT_EQ(kValue2, retval->GetUIntValue());
1017 } else if (name.ToString() == kName3) {
1018 retval = CefV8Value::CreateString(value3_);
1019 EXPECT_STREQ(kValue3, retval->GetStringValue().ToString().c_str());
1020 }
1021 return true;
1022 }
1023
1024 virtual bool Get(int index,
1025 const CefRefPtr<CefV8Value> object,
1026 CefRefPtr<CefV8Value>& retval,
1027 CefString& exception) override {
1028 EXPECT_TRUE(index >= 0 && index < 3);
1029
1030 EXPECT_TRUE(object.get());
1031 EXPECT_TRUE(object->IsSame(object_));
1032
1033 EXPECT_FALSE(retval.get());
1034 EXPECT_TRUE(exception.empty());
1035
1036 got_get_byindex_.yes();
1037 retval = CefV8Value::CreateInt(array_[index]);
1038 EXPECT_EQ(kArray[index], retval->GetIntValue());
1039 return true;
1040 }
1041
1042 virtual bool Set(const CefString& name,
1043 const CefRefPtr<CefV8Value> object,
1044 const CefRefPtr<CefV8Value> value,
1045 CefString& exception) override {
1046 EXPECT_TRUE(name.ToString() == kName1 || name.ToString() == kName2 ||
1047 name.ToString() == kName3);
1048
1049 EXPECT_TRUE(object.get());
1050 EXPECT_TRUE(object->IsSame(object_));
1051
1052 EXPECT_TRUE(value.get());
1053 EXPECT_TRUE(exception.empty());
1054
1055 got_set_byname_.yes();
1056 if (name.ToString() == kName1) {
1057 value1_ = value->GetIntValue();
1058 EXPECT_EQ(kValue1, value1_);
1059 } else if (name.ToString() == kName2) {
1060 value2_ = value->GetUIntValue();
1061 EXPECT_EQ(kValue2, value2_);
1062 } else if (name.ToString() == kName3) {
1063 value3_ = value->GetStringValue();
1064 EXPECT_STREQ(kValue3, value3_.ToString().c_str());
1065 }
1066 return true;
1067 }
1068
1069 virtual bool Set(int index,
1070 const CefRefPtr<CefV8Value> object,
1071 const CefRefPtr<CefV8Value> value,
1072 CefString& exception) override {
1073 EXPECT_TRUE(index >= 0 && index < 3);
1074
1075 EXPECT_TRUE(object.get());
1076 EXPECT_TRUE(object->IsSame(object_));
1077
1078 EXPECT_TRUE(value.get());
1079 EXPECT_TRUE(exception.empty());
1080
1081 got_set_byindex_.yes();
1082 array_[index] = value->GetIntValue();
1083 EXPECT_EQ(array_[index], kArray[index]);
1084 return true;
1085 }
1086
1087 CefRefPtr<CefV8Value> object_;
1088 int value1_;
1089 unsigned int value2_;
1090 CefString value3_;
1091 int array_[3];
1092
1093 TrackCallback got_get_byname_;
1094 TrackCallback got_get_byindex_;
1095 TrackCallback got_set_byname_;
1096 TrackCallback got_set_byindex_;
1097
1098 IMPLEMENT_REFCOUNTING(Interceptor);
1099 };
1100
1101 // Enter the V8 context.
1102 EXPECT_TRUE(context->Enter());
1103
1104 Interceptor* interceptor = new Interceptor;
1105 CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
1106
1107 CefRefPtr<CefV8Value> object =
1108 CefV8Value::CreateObject(nullptr, interceptor);
1109 EXPECT_TRUE(object.get());
1110 interceptor->object_ = object;
1111
1112 EXPECT_FALSE(object->HasException());
1113
1114 EXPECT_TRUE(object->SetValue(kName1, CefV8Value::CreateInt(kValue1),
1115 V8_PROPERTY_ATTRIBUTE_NONE));
1116 EXPECT_FALSE(object->HasException());
1117 EXPECT_TRUE(interceptor->got_set_byname_);
1118 interceptor->got_set_byname_.reset();
1119
1120 EXPECT_TRUE(object->SetValue(kName2, CefV8Value::CreateUInt(kValue2),
1121 V8_PROPERTY_ATTRIBUTE_NONE));
1122 EXPECT_FALSE(object->HasException());
1123 EXPECT_TRUE(interceptor->got_set_byname_);
1124 interceptor->got_set_byname_.reset();
1125
1126 EXPECT_TRUE(object->SetValue(kName3, CefV8Value::CreateString(kValue3),
1127 V8_PROPERTY_ATTRIBUTE_NONE));
1128 EXPECT_FALSE(object->HasException());
1129 EXPECT_TRUE(interceptor->got_set_byname_);
1130 interceptor->got_set_byname_.reset();
1131
1132 EXPECT_EQ(kValue1, interceptor->value1_);
1133 EXPECT_EQ(kValue2, interceptor->value2_);
1134 EXPECT_STREQ(kValue3, interceptor->value3_.ToString().c_str());
1135
1136 for (int i = 0; i < 3; ++i) {
1137 EXPECT_TRUE(object->SetValue(i, CefV8Value::CreateInt(kArray[i])));
1138 EXPECT_FALSE(object->HasException());
1139 EXPECT_TRUE(interceptor->got_set_byindex_);
1140 interceptor->got_set_byindex_.reset();
1141 EXPECT_EQ(kArray[i], interceptor->array_[i]);
1142 }
1143
1144 CefRefPtr<CefV8Value> val1 = object->GetValue(kName1);
1145 EXPECT_FALSE(object->HasException());
1146 EXPECT_TRUE(val1.get());
1147 EXPECT_TRUE(interceptor->got_get_byname_);
1148 interceptor->got_get_byname_.reset();
1149 EXPECT_TRUE(val1->IsInt());
1150 EXPECT_EQ(kValue1, val1->GetIntValue());
1151
1152 CefRefPtr<CefV8Value> val2 = object->GetValue(kName2);
1153 EXPECT_FALSE(object->HasException());
1154 EXPECT_TRUE(val2.get());
1155 EXPECT_TRUE(interceptor->got_get_byname_);
1156 interceptor->got_get_byname_.reset();
1157 EXPECT_TRUE(val2->IsUInt());
1158 EXPECT_EQ(kValue2, val2->GetUIntValue());
1159
1160 CefRefPtr<CefV8Value> val3 = object->GetValue(kName3);
1161 EXPECT_FALSE(object->HasException());
1162 EXPECT_TRUE(val3.get());
1163 EXPECT_TRUE(interceptor->got_get_byname_);
1164 interceptor->got_get_byname_.reset();
1165 EXPECT_TRUE(val3->IsString());
1166 EXPECT_STREQ(kValue3, val3->GetStringValue().ToString().c_str());
1167
1168 for (int i = 0; i < 3; ++i) {
1169 CefRefPtr<CefV8Value> val = object->GetValue(i);
1170 EXPECT_FALSE(object->HasException());
1171 EXPECT_TRUE(val.get());
1172 EXPECT_TRUE(interceptor->got_get_byindex_);
1173 interceptor->got_get_byname_.reset();
1174 EXPECT_EQ(kArray[i], val->GetIntValue());
1175 }
1176
1177 interceptor->object_ = nullptr;
1178
1179 // Exit the V8 context.
1180 EXPECT_TRUE(context->Exit());
1181
1182 DestroyTest();
1183 }
1184
RunObjectInterceptorFailTest()1185 void RunObjectInterceptorFailTest() {
1186 CefRefPtr<CefV8Context> context = GetContext();
1187
1188 static const char* kName = "val";
1189 static const int kIndex = 0;
1190 static const int kValue1 = 20;
1191 static const int kValue2 = 30;
1192
1193 class Interceptor : public CefV8Interceptor {
1194 typedef std::map<int, int> IntMap;
1195 typedef std::map<std::string, int> StringMap;
1196
1197 public:
1198 Interceptor() {}
1199 virtual bool Get(const CefString& name,
1200 const CefRefPtr<CefV8Value> object,
1201 CefRefPtr<CefV8Value>& retval,
1202 CefString& exception) override {
1203 got_get_byname_.yes();
1204 StringMap::iterator it = string_map_.find(name.ToString());
1205 if (it != string_map_.end()) {
1206 retval = CefV8Value::CreateInt(it->second);
1207 }
1208 return true;
1209 }
1210
1211 virtual bool Get(int index,
1212 const CefRefPtr<CefV8Value> object,
1213 CefRefPtr<CefV8Value>& retval,
1214 CefString& exception) override {
1215 got_get_byindex_.yes();
1216 IntMap::iterator it = int_map_.find(index);
1217 if (it != int_map_.end()) {
1218 retval = CefV8Value::CreateInt(it->second);
1219 }
1220 return true;
1221 }
1222
1223 virtual bool Set(const CefString& name,
1224 const CefRefPtr<CefV8Value> object,
1225 const CefRefPtr<CefV8Value> value,
1226 CefString& exception) override {
1227 EXPECT_TRUE(value->IsInt());
1228 got_set_byname_.yes();
1229 string_map_[name.ToString()] = value->GetIntValue();
1230 return true;
1231 }
1232
1233 virtual bool Set(int index,
1234 const CefRefPtr<CefV8Value> object,
1235 const CefRefPtr<CefV8Value> value,
1236 CefString& exception) override {
1237 EXPECT_TRUE(value->IsInt());
1238 got_set_byindex_.yes();
1239 int_map_[index] = value->GetIntValue();
1240 return true;
1241 }
1242
1243 IntMap int_map_;
1244 StringMap string_map_;
1245
1246 TrackCallback got_get_byname_;
1247 TrackCallback got_get_byindex_;
1248 TrackCallback got_set_byname_;
1249 TrackCallback got_set_byindex_;
1250
1251 IMPLEMENT_REFCOUNTING(Interceptor);
1252 };
1253
1254 // Enter the V8 context.
1255 EXPECT_TRUE(context->Enter());
1256
1257 Interceptor* interceptor = new Interceptor;
1258 CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
1259
1260 CefRefPtr<CefV8Value> object =
1261 CefV8Value::CreateObject(nullptr, interceptor);
1262 EXPECT_TRUE(object.get());
1263
1264 EXPECT_FALSE(object->HasValue(kName));
1265 EXPECT_FALSE(object->HasException());
1266 EXPECT_TRUE(interceptor->got_get_byname_);
1267 interceptor->got_get_byname_.reset();
1268
1269 CefRefPtr<CefV8Value> val1 = object->GetValue(kName);
1270 EXPECT_TRUE(val1.get());
1271 EXPECT_FALSE(object->HasException());
1272 EXPECT_TRUE(interceptor->got_get_byname_);
1273 EXPECT_TRUE(val1->IsUndefined());
1274 interceptor->got_get_byname_.reset();
1275
1276 EXPECT_TRUE(object->SetValue(kName, CefV8Value::CreateInt(kValue1),
1277 V8_PROPERTY_ATTRIBUTE_NONE));
1278 EXPECT_FALSE(object->HasException());
1279 EXPECT_TRUE(interceptor->got_set_byname_);
1280
1281 val1 = object->GetValue(kName);
1282 EXPECT_TRUE(val1.get());
1283 EXPECT_FALSE(object->HasException());
1284 EXPECT_TRUE(interceptor->got_get_byname_);
1285 EXPECT_EQ(kValue1, val1->GetIntValue());
1286
1287 EXPECT_FALSE(object->HasValue(kIndex));
1288 EXPECT_FALSE(object->HasException());
1289 EXPECT_TRUE(interceptor->got_get_byindex_);
1290 interceptor->got_get_byindex_.reset();
1291
1292 CefRefPtr<CefV8Value> val2 = object->GetValue(kIndex);
1293 EXPECT_TRUE(val2.get());
1294 EXPECT_FALSE(object->HasException());
1295 EXPECT_TRUE(interceptor->got_get_byindex_);
1296 EXPECT_TRUE(val2->IsUndefined());
1297 interceptor->got_get_byindex_.reset();
1298
1299 EXPECT_TRUE(object->SetValue(kIndex, CefV8Value::CreateInt(kValue2)));
1300 EXPECT_FALSE(object->HasException());
1301 EXPECT_TRUE(interceptor->got_set_byindex_);
1302
1303 val2 = object->GetValue(kIndex);
1304 EXPECT_TRUE(val2.get());
1305 EXPECT_FALSE(object->HasException());
1306 EXPECT_TRUE(interceptor->got_get_byindex_);
1307 EXPECT_EQ(kValue2, val2->GetIntValue());
1308
1309 // Exit the V8 context.
1310 EXPECT_TRUE(context->Exit());
1311
1312 DestroyTest();
1313 }
1314
RunObjectInterceptorExceptionTest()1315 void RunObjectInterceptorExceptionTest() {
1316 CefRefPtr<CefV8Context> context = GetContext();
1317 static const char* kName = "val";
1318 static const int kIndex = 1;
1319
1320 static const char* kGetByNameException = "My get_byname exception";
1321 static const char* kGetByIndexException = "My get_byindex exception";
1322 static const char* kSetByNameException = "My set_byname exception";
1323 static const char* kSetByIndexException = "My set_byindex exception";
1324
1325 static const char* kGetByNameExceptionMsg =
1326 "Uncaught Error: My get_byname exception";
1327 static const char* kGetByIndexExceptionMsg =
1328 "Uncaught Error: My get_byindex exception";
1329 static const char* kSetByNameExceptionMsg =
1330 "Uncaught Error: My set_byname exception";
1331 static const char* kSetByIndexExceptionMsg =
1332 "Uncaught Error: My set_byindex exception";
1333
1334 class Interceptor : public CefV8Interceptor {
1335 public:
1336 Interceptor() {}
1337 virtual bool Get(const CefString& name,
1338 const CefRefPtr<CefV8Value> object,
1339 CefRefPtr<CefV8Value>& retval,
1340 CefString& exception) override {
1341 got_get_byname_.yes();
1342 exception = kGetByNameException;
1343 return true;
1344 }
1345
1346 virtual bool Get(int index,
1347 const CefRefPtr<CefV8Value> object,
1348 CefRefPtr<CefV8Value>& retval,
1349 CefString& exception) override {
1350 got_get_byindex_.yes();
1351 exception = kGetByIndexException;
1352 return true;
1353 }
1354
1355 virtual bool Set(const CefString& name,
1356 const CefRefPtr<CefV8Value> object,
1357 const CefRefPtr<CefV8Value> value,
1358 CefString& exception) override {
1359 got_set_byname_.yes();
1360 exception = kSetByNameException;
1361 return true;
1362 }
1363
1364 virtual bool Set(int index,
1365 const CefRefPtr<CefV8Value> object,
1366 const CefRefPtr<CefV8Value> value,
1367 CefString& exception) override {
1368 got_set_byindex_.yes();
1369 exception = kSetByIndexException;
1370 return true;
1371 }
1372
1373 TrackCallback got_get_byname_;
1374 TrackCallback got_get_byindex_;
1375 TrackCallback got_set_byname_;
1376 TrackCallback got_set_byindex_;
1377
1378 IMPLEMENT_REFCOUNTING(Interceptor);
1379 };
1380
1381 // Enter the V8 context.
1382 EXPECT_TRUE(context->Enter());
1383
1384 CefRefPtr<CefV8Exception> exception;
1385 Interceptor* interceptor = new Interceptor;
1386 CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
1387
1388 CefRefPtr<CefV8Value> object =
1389 CefV8Value::CreateObject(nullptr, interceptor);
1390 EXPECT_TRUE(object.get());
1391
1392 EXPECT_FALSE(object->SetValue(kName, CefV8Value::CreateInt(1),
1393 V8_PROPERTY_ATTRIBUTE_NONE));
1394 EXPECT_TRUE(object->HasException());
1395 EXPECT_TRUE(interceptor->got_set_byname_);
1396 exception = object->GetException();
1397 EXPECT_TRUE(exception.get());
1398 EXPECT_STREQ(kSetByNameExceptionMsg,
1399 exception->GetMessage().ToString().c_str());
1400
1401 EXPECT_TRUE(object->ClearException());
1402 EXPECT_FALSE(object->HasException());
1403
1404 CefRefPtr<CefV8Value> val1 = object->GetValue(kName);
1405 EXPECT_FALSE(val1.get());
1406 EXPECT_TRUE(object->HasException());
1407 EXPECT_TRUE(interceptor->got_get_byname_);
1408 exception = object->GetException();
1409 EXPECT_TRUE(exception.get());
1410 EXPECT_STREQ(kGetByNameExceptionMsg,
1411 exception->GetMessage().ToString().c_str());
1412
1413 EXPECT_TRUE(object->ClearException());
1414 EXPECT_FALSE(object->HasException());
1415
1416 EXPECT_FALSE(object->SetValue(kIndex, CefV8Value::CreateInt(1)));
1417 EXPECT_TRUE(object->HasException());
1418 EXPECT_TRUE(interceptor->got_set_byindex_);
1419 exception = object->GetException();
1420 EXPECT_TRUE(exception.get());
1421 EXPECT_STREQ(kSetByIndexExceptionMsg,
1422 exception->GetMessage().ToString().c_str());
1423
1424 EXPECT_TRUE(object->ClearException());
1425 EXPECT_FALSE(object->HasException());
1426
1427 CefRefPtr<CefV8Value> val2 = object->GetValue(kIndex);
1428 EXPECT_FALSE(val2.get());
1429 EXPECT_TRUE(object->HasException());
1430 EXPECT_TRUE(interceptor->got_get_byindex_);
1431 exception = object->GetException();
1432 EXPECT_TRUE(exception.get());
1433 EXPECT_STREQ(kGetByIndexExceptionMsg,
1434 exception->GetMessage().ToString().c_str());
1435
1436 // Exit the V8 context.
1437 EXPECT_TRUE(context->Exit());
1438
1439 DestroyTest();
1440 }
1441
RunObjectInterceptorAndAccessorTest()1442 void RunObjectInterceptorAndAccessorTest() {
1443 CefRefPtr<CefV8Context> context = GetContext();
1444 static const char* kInterceptorName = "val1";
1445 static const char* kAccessorName = "val2";
1446
1447 static const int kInterceptorValue = 20;
1448 static const int kAccessorValue = 30;
1449
1450 class Interceptor : public CefV8Interceptor {
1451 public:
1452 Interceptor() {}
1453 virtual bool Get(const CefString& name,
1454 const CefRefPtr<CefV8Value> object,
1455 CefRefPtr<CefV8Value>& retval,
1456 CefString& exception) override {
1457 EXPECT_FALSE(retval.get());
1458 got_get_byname_.yes();
1459 if (name.ToString() == kInterceptorName) {
1460 retval = CefV8Value::CreateInt(kInterceptorValue);
1461 }
1462 return true;
1463 }
1464
1465 virtual bool Get(int index,
1466 const CefRefPtr<CefV8Value> object,
1467 CefRefPtr<CefV8Value>& retval,
1468 CefString& exception) override {
1469 got_get_byindex_.yes();
1470 return true;
1471 }
1472
1473 virtual bool Set(const CefString& name,
1474 const CefRefPtr<CefV8Value> object,
1475 const CefRefPtr<CefV8Value> value,
1476 CefString& exception) override {
1477 got_set_byname_.yes();
1478 return true;
1479 }
1480
1481 virtual bool Set(int index,
1482 const CefRefPtr<CefV8Value> object,
1483 const CefRefPtr<CefV8Value> value,
1484 CefString& exception) override {
1485 got_set_byindex_.yes();
1486 return true;
1487 }
1488
1489 TrackCallback got_get_byname_;
1490 TrackCallback got_get_byindex_;
1491 TrackCallback got_set_byname_;
1492 TrackCallback got_set_byindex_;
1493
1494 IMPLEMENT_REFCOUNTING(Interceptor);
1495 };
1496
1497 class Accessor : public CefV8Accessor {
1498 public:
1499 Accessor() {}
1500 virtual bool Get(const CefString& name,
1501 const CefRefPtr<CefV8Value> object,
1502 CefRefPtr<CefV8Value>& retval,
1503 CefString& exception) override {
1504 got_get_.yes();
1505 retval = CefV8Value::CreateInt(kAccessorValue);
1506 return true;
1507 }
1508
1509 virtual bool Set(const CefString& name,
1510 const CefRefPtr<CefV8Value> object,
1511 const CefRefPtr<CefV8Value> value,
1512 CefString& exception) override {
1513 got_set_.yes();
1514 return true;
1515 }
1516
1517 TrackCallback got_get_;
1518 TrackCallback got_set_;
1519
1520 IMPLEMENT_REFCOUNTING(Accessor);
1521 };
1522
1523 // Enter the V8 context.
1524 EXPECT_TRUE(context->Enter());
1525
1526 Interceptor* interceptor = new Interceptor;
1527 CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
1528
1529 Accessor* accessor = new Accessor;
1530 CefRefPtr<CefV8Accessor> accessorPtr(accessor);
1531
1532 CefRefPtr<CefV8Value> object =
1533 CefV8Value::CreateObject(accessor, interceptor);
1534 EXPECT_TRUE(object.get());
1535
1536 // We register both names for accessor.
1537 EXPECT_TRUE(object->SetValue(kAccessorName, V8_ACCESS_CONTROL_DEFAULT,
1538 V8_PROPERTY_ATTRIBUTE_NONE));
1539 EXPECT_FALSE(object->HasException());
1540
1541 EXPECT_TRUE(object->SetValue(kInterceptorName, V8_ACCESS_CONTROL_DEFAULT,
1542 V8_PROPERTY_ATTRIBUTE_NONE));
1543 EXPECT_FALSE(object->HasException());
1544
1545 EXPECT_TRUE(object->SetValue(kAccessorName,
1546 CefV8Value::CreateInt(kAccessorValue),
1547 V8_PROPERTY_ATTRIBUTE_NONE));
1548 EXPECT_FALSE(object->HasException());
1549 EXPECT_TRUE(accessor->got_set_);
1550 accessor->got_set_.reset();
1551 EXPECT_TRUE(interceptor->got_set_byname_);
1552 interceptor->got_set_byname_.reset();
1553
1554 EXPECT_TRUE(object->SetValue(kInterceptorName,
1555 CefV8Value::CreateInt(kInterceptorValue),
1556 V8_PROPERTY_ATTRIBUTE_NONE));
1557 EXPECT_FALSE(object->HasException());
1558 EXPECT_TRUE(accessor->got_set_);
1559 accessor->got_set_.reset();
1560 EXPECT_TRUE(interceptor->got_set_byname_);
1561 interceptor->got_set_byname_.reset();
1562
1563 // When interceptor returns nothing, accessor's getter is called.
1564 CefRefPtr<CefV8Value> val1 = object->GetValue(kAccessorName);
1565 EXPECT_TRUE(val1.get());
1566 EXPECT_TRUE(interceptor->got_get_byname_);
1567 interceptor->got_get_byname_.reset();
1568 EXPECT_TRUE(accessor->got_get_);
1569 accessor->got_get_.reset();
1570 EXPECT_EQ(kAccessorValue, val1->GetIntValue());
1571
1572 // When interceptor returns value, accessor's getter is not called.
1573 CefRefPtr<CefV8Value> val2 = object->GetValue(kInterceptorName);
1574 EXPECT_TRUE(val2.get());
1575 EXPECT_TRUE(interceptor->got_get_byname_);
1576 EXPECT_FALSE(accessor->got_get_);
1577 EXPECT_EQ(kInterceptorValue, val2->GetIntValue());
1578
1579 EXPECT_FALSE(interceptor->got_get_byindex_);
1580 EXPECT_FALSE(interceptor->got_set_byindex_);
1581
1582 // Exit the V8 context.
1583 EXPECT_TRUE(context->Exit());
1584
1585 DestroyTest();
1586 }
1587
RunObjectValueTest()1588 void RunObjectValueTest() {
1589 CefRefPtr<CefV8Context> context = GetContext();
1590
1591 static const char* kName = "test_arg";
1592 static const int kVal1 = 13;
1593 static const int kVal2 = 65;
1594
1595 // Enter the V8 context.
1596 EXPECT_TRUE(context->Enter());
1597
1598 CefRefPtr<CefV8Value> object = context->GetGlobal();
1599 EXPECT_TRUE(object.get());
1600
1601 object->SetValue(kName, CefV8Value::CreateInt(kVal1),
1602 V8_PROPERTY_ATTRIBUTE_NONE);
1603
1604 std::stringstream test;
1605 test << "if (window." << kName << " != " << kVal1 << ") throw 'Fail';\n"
1606 << "window." << kName << " = " << kVal2 << ";";
1607
1608 CefRefPtr<CefV8Value> retval;
1609 CefRefPtr<CefV8Exception> exception;
1610
1611 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1612 if (exception.get())
1613 ADD_FAILURE() << exception->GetMessage().c_str();
1614
1615 CefRefPtr<CefV8Value> newval = object->GetValue(kName);
1616 EXPECT_TRUE(newval.get());
1617 EXPECT_TRUE(newval->IsInt());
1618 EXPECT_EQ(kVal2, newval->GetIntValue());
1619
1620 // Exit the V8 context.
1621 EXPECT_TRUE(context->Exit());
1622
1623 DestroyTest();
1624 }
1625
RunObjectValueReadOnlyTest()1626 void RunObjectValueReadOnlyTest() {
1627 CefRefPtr<CefV8Context> context = GetContext();
1628
1629 static const char* kName = "test_arg";
1630 static const int kVal1 = 13;
1631 static const int kVal2 = 65;
1632
1633 // Enter the V8 context.
1634 EXPECT_TRUE(context->Enter());
1635
1636 CefRefPtr<CefV8Value> object = context->GetGlobal();
1637 EXPECT_TRUE(object.get());
1638
1639 object->SetValue(kName, CefV8Value::CreateInt(kVal1),
1640 V8_PROPERTY_ATTRIBUTE_READONLY);
1641
1642 std::stringstream test;
1643 test << "if (window." << kName << " != " << kVal1 << ") throw 'Fail';\n"
1644 << "window." << kName << " = " << kVal2 << ";";
1645
1646 CefRefPtr<CefV8Value> retval;
1647 CefRefPtr<CefV8Exception> exception;
1648
1649 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1650 if (exception.get())
1651 ADD_FAILURE() << exception->GetMessage().c_str();
1652
1653 CefRefPtr<CefV8Value> newval = object->GetValue(kName);
1654 EXPECT_TRUE(newval.get());
1655 EXPECT_TRUE(newval->IsInt());
1656 EXPECT_EQ(kVal1, newval->GetIntValue());
1657
1658 // Exit the V8 context.
1659 EXPECT_TRUE(context->Exit());
1660
1661 DestroyTest();
1662 }
1663
RunObjectValueEnumTest()1664 void RunObjectValueEnumTest() {
1665 CefRefPtr<CefV8Context> context = GetContext();
1666
1667 static const char* kObjName = "test_obj";
1668 static const char* kArgName = "test_arg";
1669
1670 // Enter the V8 context.
1671 EXPECT_TRUE(context->Enter());
1672
1673 CefRefPtr<CefV8Value> object = context->GetGlobal();
1674 EXPECT_TRUE(object.get());
1675
1676 CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(nullptr, nullptr);
1677 object->SetValue(kObjName, obj1, V8_PROPERTY_ATTRIBUTE_NONE);
1678
1679 obj1->SetValue(kArgName, CefV8Value::CreateInt(0),
1680 V8_PROPERTY_ATTRIBUTE_NONE);
1681
1682 std::stringstream test;
1683 test << "for (var i in window." << kObjName
1684 << ") {\n"
1685 "window."
1686 << kObjName
1687 << "[i]++;\n"
1688 "}";
1689
1690 CefRefPtr<CefV8Value> retval;
1691 CefRefPtr<CefV8Exception> exception;
1692
1693 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1694 if (exception.get())
1695 ADD_FAILURE() << exception->GetMessage().c_str();
1696
1697 CefRefPtr<CefV8Value> newval = obj1->GetValue(kArgName);
1698 EXPECT_TRUE(newval.get());
1699 EXPECT_TRUE(newval->IsInt());
1700 EXPECT_EQ(1, newval->GetIntValue());
1701
1702 // Exit the V8 context.
1703 EXPECT_TRUE(context->Exit());
1704
1705 DestroyTest();
1706 }
1707
RunObjectValueDontEnumTest()1708 void RunObjectValueDontEnumTest() {
1709 CefRefPtr<CefV8Context> context = GetContext();
1710
1711 static const char* kObjName = "test_obj";
1712 static const char* kArgName = "test_arg";
1713
1714 // Enter the V8 context.
1715 EXPECT_TRUE(context->Enter());
1716
1717 CefRefPtr<CefV8Value> object = context->GetGlobal();
1718 EXPECT_TRUE(object.get());
1719
1720 CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(nullptr, nullptr);
1721 object->SetValue(kObjName, obj1, V8_PROPERTY_ATTRIBUTE_NONE);
1722
1723 obj1->SetValue(kArgName, CefV8Value::CreateInt(0),
1724 V8_PROPERTY_ATTRIBUTE_DONTENUM);
1725
1726 std::stringstream test;
1727 test << "for (var i in window." << kObjName
1728 << ") {\n"
1729 "window."
1730 << kObjName
1731 << "[i]++;\n"
1732 "}";
1733
1734 CefRefPtr<CefV8Value> retval;
1735 CefRefPtr<CefV8Exception> exception;
1736
1737 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1738 if (exception.get())
1739 ADD_FAILURE() << exception->GetMessage().c_str();
1740
1741 CefRefPtr<CefV8Value> newval = obj1->GetValue(kArgName);
1742 EXPECT_TRUE(newval.get());
1743 EXPECT_TRUE(newval->IsInt());
1744 EXPECT_EQ(0, newval->GetIntValue());
1745
1746 // Exit the V8 context.
1747 EXPECT_TRUE(context->Exit());
1748
1749 DestroyTest();
1750 }
1751
RunObjectValueDeleteTest()1752 void RunObjectValueDeleteTest() {
1753 CefRefPtr<CefV8Context> context = GetContext();
1754
1755 static const char* kName = "test_arg";
1756 static const int kVal1 = 13;
1757 static const int kVal2 = 65;
1758
1759 // Enter the V8 context.
1760 EXPECT_TRUE(context->Enter());
1761
1762 CefRefPtr<CefV8Value> object = context->GetGlobal();
1763 EXPECT_TRUE(object.get());
1764
1765 object->SetValue(kName, CefV8Value::CreateInt(kVal1),
1766 V8_PROPERTY_ATTRIBUTE_NONE);
1767
1768 std::stringstream test;
1769 test << "if (window." << kName << " != " << kVal1 << ") throw 'Fail';\n"
1770 << "window." << kName << " = " << kVal2
1771 << ";\n"
1772 "delete window."
1773 << kName << ";";
1774
1775 CefRefPtr<CefV8Value> retval;
1776 CefRefPtr<CefV8Exception> exception;
1777
1778 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1779 if (exception.get())
1780 ADD_FAILURE() << exception->GetMessage().c_str();
1781
1782 CefRefPtr<CefV8Value> newval = object->GetValue(kName);
1783 EXPECT_TRUE(newval.get());
1784 EXPECT_TRUE(newval->IsUndefined());
1785 EXPECT_FALSE(newval->IsInt());
1786
1787 // Exit the V8 context.
1788 EXPECT_TRUE(context->Exit());
1789
1790 DestroyTest();
1791 }
1792
RunObjectValueDontDeleteTest()1793 void RunObjectValueDontDeleteTest() {
1794 CefRefPtr<CefV8Context> context = GetContext();
1795
1796 static const char* kName = "test_arg";
1797 static const int kVal1 = 13;
1798 static const int kVal2 = 65;
1799
1800 // Enter the V8 context.
1801 EXPECT_TRUE(context->Enter());
1802
1803 CefRefPtr<CefV8Value> object = context->GetGlobal();
1804 EXPECT_TRUE(object.get());
1805
1806 object->SetValue(kName, CefV8Value::CreateInt(kVal1),
1807 V8_PROPERTY_ATTRIBUTE_DONTDELETE);
1808
1809 std::stringstream test;
1810 test << "if (window." << kName << " != " << kVal1 << ") throw 'Fail';\n"
1811 << "window." << kName << " = " << kVal2
1812 << ";\n"
1813 "delete window."
1814 << kName << ";";
1815
1816 CefRefPtr<CefV8Value> retval;
1817 CefRefPtr<CefV8Exception> exception;
1818
1819 EXPECT_TRUE(context->Eval(test.str(), CefString(), 0, retval, exception));
1820 if (exception.get())
1821 ADD_FAILURE() << exception->GetMessage().c_str();
1822
1823 CefRefPtr<CefV8Value> newval = object->GetValue(kName);
1824 EXPECT_TRUE(newval.get());
1825 EXPECT_TRUE(newval->IsInt());
1826 EXPECT_EQ(kVal2, newval->GetIntValue());
1827
1828 // Exit the V8 context.
1829 EXPECT_TRUE(context->Exit());
1830
1831 DestroyTest();
1832 }
1833
RunObjectValueEmptyKeyTest()1834 void RunObjectValueEmptyKeyTest() {
1835 CefRefPtr<CefV8Context> context = GetContext();
1836
1837 static const char* kName = "";
1838 static const int kVal = 13;
1839
1840 // Enter the V8 context.
1841 EXPECT_TRUE(context->Enter());
1842
1843 CefRefPtr<CefV8Value> object = context->GetGlobal();
1844 EXPECT_TRUE(object.get());
1845
1846 EXPECT_FALSE(object->HasValue(kName));
1847
1848 object->SetValue(kName, CefV8Value::CreateInt(kVal),
1849 V8_PROPERTY_ATTRIBUTE_NONE);
1850 EXPECT_TRUE(object->HasValue(kName));
1851
1852 CefRefPtr<CefV8Value> newval = object->GetValue(kName);
1853 EXPECT_TRUE(newval.get());
1854 EXPECT_TRUE(newval->IsInt());
1855 EXPECT_EQ(kVal, newval->GetIntValue());
1856
1857 EXPECT_TRUE(object->DeleteValue(kName));
1858 EXPECT_FALSE(object->HasValue(kName));
1859
1860 // Exit the V8 context.
1861 EXPECT_TRUE(context->Exit());
1862
1863 DestroyTest();
1864 }
1865
RunFunctionCreateTest()1866 void RunFunctionCreateTest() {
1867 CefRefPtr<CefV8Context> context = GetContext();
1868
1869 class Handler : public CefV8Handler {
1870 public:
1871 Handler() {}
1872 bool Execute(const CefString& name,
1873 CefRefPtr<CefV8Value> object,
1874 const CefV8ValueList& arguments,
1875 CefRefPtr<CefV8Value>& retval,
1876 CefString& exception) override {
1877 return false;
1878 }
1879 IMPLEMENT_REFCOUNTING(Handler);
1880 };
1881
1882 // Enter the V8 context.
1883 EXPECT_TRUE(context->Enter());
1884
1885 CefRefPtr<CefV8Value> value = CefV8Value::CreateFunction("f", new Handler);
1886
1887 // Exit the V8 context.
1888 EXPECT_TRUE(context->Exit());
1889
1890 EXPECT_TRUE(value.get());
1891 EXPECT_TRUE(value->IsFunction());
1892 EXPECT_TRUE(value->IsObject());
1893
1894 EXPECT_FALSE(value->IsUndefined());
1895 EXPECT_FALSE(value->IsArray());
1896 EXPECT_FALSE(value->IsBool());
1897 EXPECT_FALSE(value->IsDate());
1898 EXPECT_FALSE(value->IsDouble());
1899 EXPECT_FALSE(value->IsInt());
1900 EXPECT_FALSE(value->IsUInt());
1901 EXPECT_FALSE(value->IsNull());
1902 EXPECT_FALSE(value->IsString());
1903
1904 DestroyTest();
1905 }
1906
RunFunctionHandlerTest()1907 void RunFunctionHandlerTest() {
1908 CefRefPtr<CefV8Context> context = GetContext();
1909
1910 static const char* kFuncName = "myfunc";
1911 static const int kVal1 = 32;
1912 static const int kVal2 = 41;
1913 static const int kRetVal = 8;
1914
1915 class Handler : public CefV8Handler {
1916 public:
1917 Handler() {}
1918 bool Execute(const CefString& name,
1919 CefRefPtr<CefV8Value> object,
1920 const CefV8ValueList& arguments,
1921 CefRefPtr<CefV8Value>& retval,
1922 CefString& exception) override {
1923 EXPECT_STREQ(kFuncName, name.ToString().c_str());
1924 EXPECT_TRUE(object->IsSame(object_));
1925
1926 EXPECT_EQ((size_t)2, arguments.size());
1927 EXPECT_TRUE(arguments[0]->IsInt());
1928 EXPECT_EQ(kVal1, arguments[0]->GetIntValue());
1929 EXPECT_TRUE(arguments[1]->IsInt());
1930 EXPECT_EQ(kVal2, arguments[1]->GetIntValue());
1931
1932 EXPECT_TRUE(exception.empty());
1933
1934 retval = CefV8Value::CreateInt(kRetVal);
1935 EXPECT_TRUE(retval.get());
1936 EXPECT_EQ(kRetVal, retval->GetIntValue());
1937
1938 got_execute_.yes();
1939 return true;
1940 }
1941
1942 CefRefPtr<CefV8Value> object_;
1943 TrackCallback got_execute_;
1944
1945 IMPLEMENT_REFCOUNTING(Handler);
1946 };
1947
1948 // Enter the V8 context.
1949 EXPECT_TRUE(context->Enter());
1950
1951 Handler* handler = new Handler;
1952 CefRefPtr<CefV8Handler> handlerPtr(handler);
1953
1954 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(kFuncName, handler);
1955 EXPECT_TRUE(func.get());
1956
1957 CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(nullptr, nullptr);
1958 EXPECT_TRUE(obj.get());
1959 handler->object_ = obj;
1960
1961 CefV8ValueList args;
1962 args.push_back(CefV8Value::CreateInt(kVal1));
1963 args.push_back(CefV8Value::CreateInt(kVal2));
1964
1965 CefRefPtr<CefV8Value> retval = func->ExecuteFunction(obj, args);
1966 EXPECT_TRUE(handler->got_execute_);
1967 EXPECT_TRUE(retval.get());
1968 EXPECT_FALSE(func->HasException());
1969 EXPECT_TRUE(retval->IsInt());
1970 EXPECT_EQ(kRetVal, retval->GetIntValue());
1971
1972 handler->object_ = nullptr;
1973
1974 // Exit the V8 context.
1975 EXPECT_TRUE(context->Exit());
1976
1977 DestroyTest();
1978 }
1979
RunFunctionHandlerExceptionTest()1980 void RunFunctionHandlerExceptionTest() {
1981 CefRefPtr<CefV8Context> context = GetContext();
1982
1983 static const char* kException = "My error";
1984 static const char* kExceptionMsg = "Uncaught Error: My error";
1985
1986 class Handler : public CefV8Handler {
1987 public:
1988 Handler() {}
1989 bool Execute(const CefString& name,
1990 CefRefPtr<CefV8Value> object,
1991 const CefV8ValueList& arguments,
1992 CefRefPtr<CefV8Value>& retval,
1993 CefString& exception) override {
1994 exception = kException;
1995 got_execute_.yes();
1996 return true;
1997 }
1998
1999 TrackCallback got_execute_;
2000
2001 IMPLEMENT_REFCOUNTING(Handler);
2002 };
2003
2004 // Enter the V8 context.
2005 EXPECT_TRUE(context->Enter());
2006
2007 Handler* handler = new Handler;
2008 CefRefPtr<CefV8Handler> handlerPtr(handler);
2009
2010 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
2011 EXPECT_TRUE(func.get());
2012
2013 CefV8ValueList args;
2014
2015 CefRefPtr<CefV8Value> retval = func->ExecuteFunction(nullptr, args);
2016 EXPECT_TRUE(handler->got_execute_);
2017 EXPECT_FALSE(retval.get());
2018 EXPECT_TRUE(func->HasException());
2019 CefRefPtr<CefV8Exception> exception = func->GetException();
2020 EXPECT_TRUE(exception.get());
2021 EXPECT_STREQ(kExceptionMsg, exception->GetMessage().ToString().c_str());
2022
2023 // Exit the V8 context.
2024 EXPECT_TRUE(context->Exit());
2025
2026 DestroyTest();
2027 }
2028
RunFunctionHandlerFailTest()2029 void RunFunctionHandlerFailTest() {
2030 CefRefPtr<CefV8Context> context = GetContext();
2031
2032 class Handler : public CefV8Handler {
2033 public:
2034 Handler() {}
2035 bool Execute(const CefString& name,
2036 CefRefPtr<CefV8Value> object,
2037 const CefV8ValueList& arguments,
2038 CefRefPtr<CefV8Value>& retval,
2039 CefString& exception) override {
2040 got_execute_.yes();
2041 return false;
2042 }
2043
2044 TrackCallback got_execute_;
2045
2046 IMPLEMENT_REFCOUNTING(Handler);
2047 };
2048
2049 // Enter the V8 context.
2050 EXPECT_TRUE(context->Enter());
2051
2052 Handler* handler = new Handler;
2053 CefRefPtr<CefV8Handler> handlerPtr(handler);
2054
2055 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
2056 EXPECT_TRUE(func.get());
2057
2058 CefV8ValueList args;
2059
2060 CefRefPtr<CefV8Value> retval = func->ExecuteFunction(nullptr, args);
2061 EXPECT_TRUE(handler->got_execute_);
2062 EXPECT_TRUE(retval.get());
2063 EXPECT_FALSE(func->HasException());
2064 EXPECT_TRUE(retval->IsUndefined());
2065
2066 // Exit the V8 context.
2067 EXPECT_TRUE(context->Exit());
2068
2069 DestroyTest();
2070 }
2071
RunFunctionHandlerNoObjectTest()2072 void RunFunctionHandlerNoObjectTest() {
2073 CefRefPtr<CefV8Context> context = GetContext();
2074
2075 class Handler : public CefV8Handler {
2076 public:
2077 Handler() {}
2078 bool Execute(const CefString& name,
2079 CefRefPtr<CefV8Value> object,
2080 const CefV8ValueList& arguments,
2081 CefRefPtr<CefV8Value>& retval,
2082 CefString& exception) override {
2083 EXPECT_TRUE(object.get());
2084 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
2085 EXPECT_TRUE(context.get());
2086 CefRefPtr<CefV8Value> global = context->GetGlobal();
2087 EXPECT_TRUE(global.get());
2088 EXPECT_TRUE(global->IsSame(object));
2089
2090 got_execute_.yes();
2091 return true;
2092 }
2093
2094 TrackCallback got_execute_;
2095
2096 IMPLEMENT_REFCOUNTING(Handler);
2097 };
2098
2099 // Enter the V8 context.
2100 EXPECT_TRUE(context->Enter());
2101
2102 Handler* handler = new Handler;
2103 CefRefPtr<CefV8Handler> handlerPtr(handler);
2104
2105 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
2106 EXPECT_TRUE(func.get());
2107
2108 CefV8ValueList args;
2109
2110 CefRefPtr<CefV8Value> retval = func->ExecuteFunction(nullptr, args);
2111 EXPECT_TRUE(handler->got_execute_);
2112 EXPECT_TRUE(retval.get());
2113 EXPECT_FALSE(func->HasException());
2114
2115 // Exit the V8 context.
2116 EXPECT_TRUE(context->Exit());
2117
2118 DestroyTest();
2119 }
2120
RunFunctionHandlerWithContextTest()2121 void RunFunctionHandlerWithContextTest() {
2122 CefRefPtr<CefV8Context> context = GetContext();
2123
2124 class Handler : public CefV8Handler {
2125 public:
2126 Handler() {}
2127 bool Execute(const CefString& name,
2128 CefRefPtr<CefV8Value> object,
2129 const CefV8ValueList& arguments,
2130 CefRefPtr<CefV8Value>& retval,
2131 CefString& exception) override {
2132 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
2133 EXPECT_TRUE(context.get());
2134 EXPECT_TRUE(context->IsSame(context_));
2135 got_execute_.yes();
2136 return true;
2137 }
2138
2139 CefRefPtr<CefV8Context> context_;
2140 TrackCallback got_execute_;
2141
2142 IMPLEMENT_REFCOUNTING(Handler);
2143 };
2144
2145 // Enter the V8 context.
2146 EXPECT_TRUE(context->Enter());
2147
2148 Handler* handler = new Handler;
2149 CefRefPtr<CefV8Handler> handlerPtr(handler);
2150 handler->context_ = context;
2151
2152 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
2153 EXPECT_TRUE(func.get());
2154
2155 // Exit the V8 context.
2156 EXPECT_TRUE(context->Exit());
2157
2158 CefV8ValueList args;
2159
2160 CefRefPtr<CefV8Value> retval =
2161 func->ExecuteFunctionWithContext(context, nullptr, args);
2162 EXPECT_TRUE(handler->got_execute_);
2163 EXPECT_TRUE(retval.get());
2164 EXPECT_FALSE(func->HasException());
2165
2166 handler->context_ = nullptr;
2167
2168 DestroyTest();
2169 }
2170
RunFunctionHandlerEmptyStringTest()2171 void RunFunctionHandlerEmptyStringTest() {
2172 CefRefPtr<CefV8Context> context = GetContext();
2173
2174 class Handler : public CefV8Handler {
2175 public:
2176 Handler() {}
2177 bool Execute(const CefString& name,
2178 CefRefPtr<CefV8Value> object,
2179 const CefV8ValueList& arguments,
2180 CefRefPtr<CefV8Value>& retval,
2181 CefString& exception) override {
2182 EXPECT_TRUE(object.get());
2183 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
2184 EXPECT_TRUE(context.get());
2185 CefRefPtr<CefV8Value> global = context->GetGlobal();
2186 EXPECT_TRUE(global.get());
2187 EXPECT_TRUE(global->IsSame(object));
2188
2189 EXPECT_EQ((size_t)1, arguments.size());
2190 EXPECT_TRUE(arguments[0]->IsString());
2191 EXPECT_STREQ("", arguments[0]->GetStringValue().ToString().c_str());
2192
2193 retval = CefV8Value::CreateString(CefString());
2194
2195 got_execute_.yes();
2196 return true;
2197 }
2198
2199 TrackCallback got_execute_;
2200
2201 IMPLEMENT_REFCOUNTING(Handler);
2202 };
2203
2204 // Enter the V8 context.
2205 EXPECT_TRUE(context->Enter());
2206
2207 Handler* handler = new Handler;
2208 CefRefPtr<CefV8Handler> handlerPtr(handler);
2209
2210 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction("myfunc", handler);
2211 EXPECT_TRUE(func.get());
2212
2213 CefV8ValueList args;
2214 args.push_back(CefV8Value::CreateString(CefString()));
2215
2216 CefRefPtr<CefV8Value> retval = func->ExecuteFunction(nullptr, args);
2217 EXPECT_TRUE(handler->got_execute_);
2218 EXPECT_TRUE(retval.get());
2219 EXPECT_FALSE(func->HasException());
2220
2221 EXPECT_TRUE(retval->IsString());
2222 EXPECT_STREQ("", retval->GetStringValue().ToString().c_str());
2223
2224 // Exit the V8 context.
2225 EXPECT_TRUE(context->Exit());
2226
2227 DestroyTest();
2228 }
2229
RunContextEvalTest()2230 void RunContextEvalTest() {
2231 CefRefPtr<CefV8Context> context = GetContext();
2232
2233 CefRefPtr<CefV8Value> retval;
2234 CefRefPtr<CefV8Exception> exception;
2235
2236 EXPECT_TRUE(context->Eval("1+2", CefString(), 0, retval, exception));
2237 EXPECT_TRUE(retval.get());
2238 EXPECT_TRUE(retval->IsInt());
2239 EXPECT_EQ(3, retval->GetIntValue());
2240 EXPECT_FALSE(exception.get());
2241
2242 DestroyTest();
2243 }
2244
RunContextEvalExceptionTest()2245 void RunContextEvalExceptionTest() {
2246 CefRefPtr<CefV8Context> context = GetContext();
2247
2248 CefRefPtr<CefV8Value> retval;
2249 CefRefPtr<CefV8Exception> exception;
2250
2251 EXPECT_FALSE(
2252 context->Eval("\n\n\n1+foo", CefString(), 0, retval, exception));
2253 EXPECT_FALSE(retval.get());
2254 EXPECT_TRUE(exception.get());
2255 EXPECT_EQ(4, exception->GetLineNumber());
2256
2257 DestroyTest();
2258 }
2259
RunContextEvalCspBypassUnsafeEval()2260 void RunContextEvalCspBypassUnsafeEval() {
2261 CefRefPtr<CefV8Context> context = GetContext();
2262
2263 CefRefPtr<CefV8Value> retval;
2264 CefRefPtr<CefV8Exception> exception;
2265
2266 bool success =
2267 context->Eval("(document.getElementById('result').innerHTML)",
2268 CefString(), 0, retval, exception);
2269 if (exception.get()) {
2270 ADD_FAILURE() << exception->GetMessage().c_str();
2271 EXPECT_FALSE(success);
2272 }
2273
2274 EXPECT_TRUE(success);
2275 EXPECT_TRUE(retval.get());
2276 if (retval.get()) {
2277 EXPECT_TRUE(retval->IsString());
2278 EXPECT_EQ(CefString("CSP_BYPASSED"), retval->GetStringValue());
2279 }
2280
2281 DestroyTest();
2282 }
2283
RunContextEvalCspBypassSandbox()2284 void RunContextEvalCspBypassSandbox() {
2285 CefRefPtr<CefV8Context> context = GetContext();
2286
2287 CefRefPtr<CefV8Value> retval;
2288 CefRefPtr<CefV8Exception> exception;
2289
2290 bool success =
2291 context->Eval("(document.getElementById('result').innerHTML)",
2292 CefString(), 0, retval, exception);
2293 if (exception.get()) {
2294 ADD_FAILURE() << exception->GetMessage().c_str();
2295 EXPECT_FALSE(success);
2296 }
2297
2298 EXPECT_TRUE(success);
2299 EXPECT_TRUE(retval.get());
2300 if (retval.get()) {
2301 EXPECT_TRUE(retval->IsString());
2302 EXPECT_EQ(CefString("CSP_BYPASSED"), retval->GetStringValue());
2303 }
2304
2305 DestroyTest();
2306 }
2307
RunContextEnteredTest()2308 void RunContextEnteredTest() {
2309 CefRefPtr<CefV8Context> context = GetContext();
2310
2311 CefRefPtr<CefV8Value> retval;
2312 CefRefPtr<CefV8Exception> exception;
2313
2314 // Test value defined in OnContextCreated
2315 EXPECT_TRUE(context->Eval(
2316 "document.getElementById('f').contentWindow.v8_context_entered_test()",
2317 CefString(), 0, retval, exception));
2318 if (exception.get())
2319 ADD_FAILURE() << exception->GetMessage().c_str();
2320
2321 EXPECT_TRUE(retval.get());
2322 EXPECT_TRUE(retval->IsInt());
2323 EXPECT_EQ(21, retval->GetIntValue());
2324
2325 DestroyTest();
2326 }
2327
RunBindingTest()2328 void RunBindingTest() {
2329 CefRefPtr<CefV8Context> context = GetContext();
2330
2331 // Enter the V8 context.
2332 EXPECT_TRUE(context->Enter());
2333
2334 CefRefPtr<CefV8Value> object = context->GetGlobal();
2335 EXPECT_TRUE(object.get());
2336
2337 // Test value defined in OnContextCreated
2338 CefRefPtr<CefV8Value> value = object->GetValue("v8_binding_test");
2339 EXPECT_TRUE(value.get());
2340 EXPECT_TRUE(value->IsInt());
2341 EXPECT_EQ(12, value->GetIntValue());
2342
2343 // Exit the V8 context.
2344 EXPECT_TRUE(context->Exit());
2345
2346 DestroyTest();
2347 }
2348
RunStackTraceTest()2349 void RunStackTraceTest() {
2350 CefRefPtr<CefV8Context> context = GetContext();
2351
2352 static const char* kFuncName = "myfunc";
2353
2354 class Handler : public CefV8Handler {
2355 public:
2356 Handler() {}
2357 bool Execute(const CefString& name,
2358 CefRefPtr<CefV8Value> object,
2359 const CefV8ValueList& arguments,
2360 CefRefPtr<CefV8Value>& retval,
2361 CefString& exception) override {
2362 EXPECT_STREQ(kFuncName, name.ToString().c_str());
2363
2364 stack_trace_ = CefV8StackTrace::GetCurrent(10);
2365
2366 retval = CefV8Value::CreateInt(3);
2367 got_execute_.yes();
2368 return true;
2369 }
2370
2371 TrackCallback got_execute_;
2372 CefRefPtr<CefV8StackTrace> stack_trace_;
2373
2374 IMPLEMENT_REFCOUNTING(Handler);
2375 };
2376
2377 // Enter the V8 context.
2378 EXPECT_TRUE(context->Enter());
2379
2380 Handler* handler = new Handler;
2381 CefRefPtr<CefV8Handler> handlerPtr(handler);
2382
2383 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(kFuncName, handler);
2384 EXPECT_TRUE(func.get());
2385 CefRefPtr<CefV8Value> obj = context->GetGlobal();
2386 EXPECT_TRUE(obj.get());
2387 obj->SetValue(kFuncName, func, V8_PROPERTY_ATTRIBUTE_NONE);
2388
2389 CefRefPtr<CefV8Value> retval;
2390 CefRefPtr<CefV8Exception> exception;
2391
2392 EXPECT_TRUE(
2393 context->Eval("function jsfunc() { return window.myfunc(); }\n"
2394 "jsfunc();",
2395 CefString(), 0, retval, exception));
2396 EXPECT_TRUE(retval.get());
2397 EXPECT_TRUE(retval->IsInt());
2398 EXPECT_EQ(3, retval->GetIntValue());
2399 EXPECT_FALSE(exception.get());
2400
2401 EXPECT_TRUE(handler->stack_trace_.get());
2402 EXPECT_EQ(2, handler->stack_trace_->GetFrameCount());
2403
2404 CefRefPtr<CefV8StackFrame> frame;
2405
2406 frame = handler->stack_trace_->GetFrame(0);
2407 EXPECT_TRUE(frame->GetScriptName().empty());
2408 EXPECT_TRUE(frame->GetScriptNameOrSourceURL().empty());
2409 EXPECT_STREQ("jsfunc", frame->GetFunctionName().ToString().c_str());
2410 EXPECT_EQ(1, frame->GetLineNumber());
2411 EXPECT_EQ(35, frame->GetColumn());
2412 EXPECT_TRUE(frame.get());
2413 EXPECT_FALSE(frame->IsEval());
2414 EXPECT_FALSE(frame->IsConstructor());
2415
2416 frame = handler->stack_trace_->GetFrame(1);
2417 EXPECT_TRUE(frame->GetScriptName().empty());
2418 EXPECT_TRUE(frame->GetScriptNameOrSourceURL().empty());
2419 EXPECT_TRUE(frame->GetFunctionName().empty());
2420 EXPECT_EQ(2, frame->GetLineNumber());
2421 EXPECT_EQ(1, frame->GetColumn());
2422 EXPECT_TRUE(frame.get());
2423 EXPECT_FALSE(frame->IsEval());
2424 EXPECT_FALSE(frame->IsConstructor());
2425
2426 // Exit the V8 context.
2427 EXPECT_TRUE(context->Exit());
2428
2429 DestroyTest();
2430 }
2431
RunOnUncaughtExceptionTest()2432 void RunOnUncaughtExceptionTest() {
2433 test_context_ = browser_->GetMainFrame()->GetV8Context();
2434 browser_->GetMainFrame()->ExecuteJavaScript(
2435 "window.setTimeout(test, 0)", browser_->GetMainFrame()->GetURL(), 0);
2436 }
2437
2438 // Test execution of a native function when the extension is loaded.
RunExtensionTest()2439 void RunExtensionTest() {
2440 std::string code =
2441 "native function v8_extension_test();"
2442 "v8_extension_test();";
2443
2444 class Handler : public CefV8Handler {
2445 public:
2446 Handler(TrackCallback* callback) : callback_(callback) {}
2447
2448 bool Execute(const CefString& name,
2449 CefRefPtr<CefV8Value> object,
2450 const CefV8ValueList& arguments,
2451 CefRefPtr<CefV8Value>& retval,
2452 CefString& exception) override {
2453 EXPECT_STREQ("v8_extension_test", name.ToString().c_str());
2454 callback_->yes();
2455 return true;
2456 }
2457
2458 TrackCallback* callback_;
2459
2460 IMPLEMENT_REFCOUNTING(Handler);
2461 };
2462
2463 CefRegisterExtension("v8/test-extension", code,
2464 new Handler(&startup_test_success_));
2465 }
2466
OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefDictionaryValue> extra_info)2467 void OnBrowserCreated(CefRefPtr<ClientAppRenderer> app,
2468 CefRefPtr<CefBrowser> browser,
2469 CefRefPtr<CefDictionaryValue> extra_info) override {
2470 if (extra_info && extra_info->HasKey(kV8TestCmdKey)) {
2471 test_mode_ = static_cast<V8TestMode>(extra_info->GetInt(kV8TestCmdKey));
2472 }
2473 if (test_mode_ > V8TEST_NONE)
2474 RunStartupTest();
2475 if (test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL ||
2476 test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX) {
2477 browser_ = browser;
2478 }
2479 }
2480
GetLoadHandler(CefRefPtr<ClientAppRenderer> app)2481 CefRefPtr<CefLoadHandler> GetLoadHandler(
2482 CefRefPtr<ClientAppRenderer> app) override {
2483 if (test_mode_ == V8TEST_NONE)
2484 return nullptr;
2485
2486 return this;
2487 }
2488
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)2489 void OnLoadEnd(CefRefPtr<CefBrowser> browser,
2490 CefRefPtr<CefFrame> frame,
2491 int httpStatusCode) override {
2492 if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS &&
2493 browser->IsPopup()) {
2494 DevToolsLoadHook(browser);
2495 }
2496 }
2497
OnContextCreated(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context)2498 void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
2499 CefRefPtr<CefBrowser> browser,
2500 CefRefPtr<CefFrame> frame,
2501 CefRefPtr<CefV8Context> context) override {
2502 if (test_mode_ == V8TEST_NONE)
2503 return;
2504
2505 if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
2506 if (!browser->IsPopup()) {
2507 app_ = app;
2508 browser_ = browser;
2509 test_context_ = context;
2510 }
2511 return;
2512 }
2513
2514 app_ = app;
2515 browser_ = browser;
2516
2517 std::string url = frame->GetURL();
2518 if (url == kV8ContextChildTestUrl) {
2519 // For V8TEST_CONTEXT_ENTERED
2520 class Handler : public CefV8Handler {
2521 public:
2522 Handler() {}
2523 bool Execute(const CefString& name,
2524 CefRefPtr<CefV8Value> object,
2525 const CefV8ValueList& arguments,
2526 CefRefPtr<CefV8Value>& retval,
2527 CefString& exception) override {
2528 // context for the sub-frame
2529 CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
2530 EXPECT_TRUE(context.get());
2531
2532 // entered context should be the same as the main frame context
2533 CefRefPtr<CefV8Context> entered = CefV8Context::GetEnteredContext();
2534 EXPECT_TRUE(entered.get());
2535 EXPECT_TRUE(entered->IsSame(context_));
2536
2537 context_ = nullptr;
2538 retval = CefV8Value::CreateInt(21);
2539 return true;
2540 }
2541
2542 CefRefPtr<CefV8Context> context_;
2543 IMPLEMENT_REFCOUNTING(Handler);
2544 };
2545
2546 Handler* handler = new Handler;
2547 CefRefPtr<CefV8Handler> handlerPtr(handler);
2548
2549 // main frame context
2550 handler->context_ = GetContext();
2551
2552 // Function that will be called from the parent frame context.
2553 CefRefPtr<CefV8Value> func =
2554 CefV8Value::CreateFunction("v8_context_entered_test", handler);
2555 EXPECT_TRUE(func.get());
2556
2557 CefRefPtr<CefV8Value> object = context->GetGlobal();
2558 EXPECT_TRUE(object.get());
2559 EXPECT_TRUE(object->SetValue("v8_context_entered_test", func,
2560 V8_PROPERTY_ATTRIBUTE_NONE));
2561 } else if (url == kV8ContextParentTestUrl) {
2562 // For V8TEST_CONTEXT_ENTERED. Do nothing.
2563 return;
2564 } else if (url == kV8BindingTestUrl) {
2565 // For V8TEST_BINDING
2566 CefRefPtr<CefV8Value> object = context->GetGlobal();
2567 EXPECT_TRUE(object.get());
2568 EXPECT_TRUE(object->SetValue("v8_binding_test", CefV8Value::CreateInt(12),
2569 V8_PROPERTY_ATTRIBUTE_NONE));
2570 } else if (url == kV8HandlerCallOnReleasedContextUrl) {
2571 // For V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT
2572 class Handler : public CefV8Handler {
2573 public:
2574 Handler(CefRefPtr<V8RendererTest> renderer_test)
2575 : renderer_test_(renderer_test) {}
2576
2577 bool Execute(const CefString& name,
2578 CefRefPtr<CefV8Value> object,
2579 const CefV8ValueList& arguments,
2580 CefRefPtr<CefV8Value>& retval,
2581 CefString& exception) override {
2582 if (name == "notify_test_done") {
2583 CefPostDelayedTask(TID_RENDERER,
2584 base::BindOnce(&V8RendererTest::DestroyTest,
2585 renderer_test_.get()),
2586 1000);
2587 return true;
2588 }
2589
2590 return false;
2591 }
2592
2593 private:
2594 CefRefPtr<V8RendererTest> renderer_test_;
2595 IMPLEMENT_REFCOUNTING(Handler);
2596 };
2597
2598 Handler* handler = new Handler(this);
2599 CefRefPtr<CefV8Handler> handlerPtr(handler);
2600
2601 // Function that will be called from the parent frame context.
2602 CefRefPtr<CefV8Value> func =
2603 CefV8Value::CreateFunction("notify_test_done", handler);
2604 EXPECT_TRUE(func.get());
2605
2606 CefRefPtr<CefV8Value> object = context->GetGlobal();
2607 EXPECT_TRUE(object.get());
2608 EXPECT_TRUE(object->SetValue("notify_test_done", func,
2609 V8_PROPERTY_ATTRIBUTE_NONE));
2610 } else if (url == kV8HandlerCallOnReleasedContextChildUrl) {
2611 // For V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT
2612 class Handler : public CefV8Handler {
2613 public:
2614 Handler() {}
2615 bool Execute(const CefString& name,
2616 CefRefPtr<CefV8Value> object,
2617 const CefV8ValueList& arguments,
2618 CefRefPtr<CefV8Value>& retval,
2619 CefString& exception) override {
2620 if (name == "v8_context_is_alive") {
2621 retval = CefV8Value::CreateBool(true);
2622 return true;
2623 }
2624
2625 return false;
2626 }
2627
2628 IMPLEMENT_REFCOUNTING(Handler);
2629 };
2630
2631 Handler* handler = new Handler;
2632 CefRefPtr<CefV8Handler> handlerPtr(handler);
2633
2634 // Function that will be called from the parent frame context.
2635 CefRefPtr<CefV8Value> func =
2636 CefV8Value::CreateFunction("v8_context_is_alive", handler);
2637 EXPECT_TRUE(func.get());
2638
2639 CefRefPtr<CefV8Value> object = context->GetGlobal();
2640 EXPECT_TRUE(object.get());
2641 EXPECT_TRUE(object->SetValue("v8_context_is_alive", func,
2642 V8_PROPERTY_ATTRIBUTE_NONE));
2643 }
2644 }
2645
OnUncaughtException(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefV8Context> context,CefRefPtr<CefV8Exception> exception,CefRefPtr<CefV8StackTrace> stackTrace)2646 void OnUncaughtException(CefRefPtr<ClientAppRenderer> app,
2647 CefRefPtr<CefBrowser> browser,
2648 CefRefPtr<CefFrame> frame,
2649 CefRefPtr<CefV8Context> context,
2650 CefRefPtr<CefV8Exception> exception,
2651 CefRefPtr<CefV8StackTrace> stackTrace) override {
2652 if (test_mode_ == V8TEST_NONE)
2653 return;
2654
2655 if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
2656 test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
2657 EXPECT_TRUE(test_context_->IsSame(context));
2658 EXPECT_STREQ("Uncaught ReferenceError: asd is not defined",
2659 exception->GetMessage().ToString().c_str());
2660 std::ostringstream stackFormatted;
2661 for (int i = 0; i < stackTrace->GetFrameCount(); ++i) {
2662 stackFormatted << "at "
2663 << stackTrace->GetFrame(i)->GetFunctionName().ToString()
2664 << "() in "
2665 << stackTrace->GetFrame(i)->GetScriptName().ToString()
2666 << " on line "
2667 << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
2668 }
2669 const char* stackFormattedShouldBe =
2670 "at test2() in http://tests/V8Test.OnUncaughtException on line 3\n"
2671 "at test() in http://tests/V8Test.OnUncaughtException on line 2\n";
2672 EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
2673 DestroyTest();
2674 }
2675 }
2676
OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)2677 bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
2678 CefRefPtr<CefBrowser> browser,
2679 CefRefPtr<CefFrame> frame,
2680 CefProcessId source_process,
2681 CefRefPtr<CefProcessMessage> message) override {
2682 if (test_mode_ == V8TEST_NONE)
2683 return false;
2684
2685 const std::string& message_name = message->GetName();
2686 if (message_name == kV8RunTestMsg) {
2687 // Run the test asynchronously.
2688 CefPostTask(TID_RENDERER, base::BindOnce(&V8RendererTest::RunTest, this));
2689 return true;
2690 }
2691 return false;
2692 }
2693
DevToolsLoadHook(CefRefPtr<CefBrowser> browser)2694 void DevToolsLoadHook(CefRefPtr<CefBrowser> browser) {
2695 EXPECT_TRUE(browser->IsPopup());
2696 CefRefPtr<CefFrame> frame = browser->GetMainFrame();
2697 CefRefPtr<CefV8Context> context = frame->GetV8Context();
2698 static const char* kFuncName = "DevToolsLoaded";
2699
2700 class Handler : public CefV8Handler {
2701 public:
2702 Handler() {}
2703 bool Execute(const CefString& name,
2704 CefRefPtr<CefV8Value> object,
2705 const CefV8ValueList& arguments,
2706 CefRefPtr<CefV8Value>& retval,
2707 CefString& exception) override {
2708 EXPECT_STREQ(kFuncName, name.ToString().c_str());
2709 if (name == kFuncName) {
2710 EXPECT_TRUE(exception.empty());
2711 retval = CefV8Value::CreateNull();
2712 EXPECT_TRUE(retval.get());
2713 renderer_test_->DevToolsLoaded(browser_);
2714 return true;
2715 }
2716 return false;
2717 }
2718 CefRefPtr<V8RendererTest> renderer_test_;
2719 CefRefPtr<CefBrowser> browser_;
2720 IMPLEMENT_REFCOUNTING(Handler);
2721 };
2722
2723 EXPECT_TRUE(context->Enter());
2724 Handler* handler = new Handler;
2725 handler->renderer_test_ = this;
2726 handler->browser_ = browser;
2727 CefRefPtr<CefV8Handler> handlerPtr(handler);
2728 CefRefPtr<CefV8Value> func = CefV8Value::CreateFunction(kFuncName, handler);
2729 EXPECT_TRUE(func.get());
2730 EXPECT_TRUE(context->GetGlobal()->SetValue(kFuncName, func,
2731 V8_PROPERTY_ATTRIBUTE_NONE));
2732 EXPECT_TRUE(context->Exit());
2733
2734 // Dismiss the DevTools window after 500ms. It would be better to hook the
2735 // DevTools JS to receive notification of when loading is complete but that
2736 // is no longer possible.
2737 CefPostDelayedTask(
2738 TID_RENDERER,
2739 base::BindOnce(&CefFrame::ExecuteJavaScript, frame.get(),
2740 "window.DevToolsLoaded()", frame->GetURL(), 0),
2741 500);
2742 }
2743
DevToolsLoaded(CefRefPtr<CefBrowser> browser)2744 void DevToolsLoaded(CefRefPtr<CefBrowser> browser) {
2745 EXPECT_TRUE(browser->IsPopup());
2746 // |browser_| will be nullptr if the DevTools window is opened in a separate
2747 // render process.
2748 const int other_browser_id =
2749 (browser_.get() ? browser_->GetIdentifier() : -1);
2750 EXPECT_NE(browser->GetIdentifier(), other_browser_id);
2751
2752 // Close the DevTools window. This will trigger OnBeforeClose in the browser
2753 // process.
2754 CefRefPtr<CefV8Value> retval;
2755 CefRefPtr<CefV8Exception> exception;
2756 EXPECT_TRUE(browser->GetMainFrame()->GetV8Context()->Eval(
2757 "window.close()", CefString(), 0, retval, exception));
2758 }
2759
2760 protected:
2761 // Return from the test.
DestroyTest()2762 void DestroyTest() {
2763 EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
2764
2765 // Check if the test has failed.
2766 bool result = !TestFailed();
2767
2768 // Return the result to the browser process.
2769 CefRefPtr<CefProcessMessage> return_msg =
2770 CefProcessMessage::Create(kV8TestMsg);
2771 EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
2772 browser_->GetMainFrame()->SendProcessMessage(PID_BROWSER, return_msg);
2773
2774 app_ = nullptr;
2775 browser_ = nullptr;
2776 test_context_ = nullptr;
2777 test_object_ = nullptr;
2778 }
2779
2780 // Return the V8 context.
GetContext()2781 CefRefPtr<CefV8Context> GetContext() {
2782 CefRefPtr<CefV8Context> context = browser_->GetMainFrame()->GetV8Context();
2783 EXPECT_TRUE(context.get());
2784 return context;
2785 }
2786
2787 CefRefPtr<ClientAppRenderer> app_;
2788 CefRefPtr<CefBrowser> browser_;
2789 V8TestMode test_mode_;
2790
2791 CefRefPtr<CefV8Context> test_context_;
2792 CefRefPtr<CefV8Value> test_object_;
2793
2794 // Used by startup tests to indicate success.
2795 TrackCallback startup_test_success_;
2796
2797 IMPLEMENT_REFCOUNTING(V8RendererTest);
2798 };
2799
2800 // Browser side.
2801 class V8TestHandler : public TestHandler {
2802 public:
V8TestHandler(V8TestMode test_mode,const char * test_url)2803 V8TestHandler(V8TestMode test_mode, const char* test_url)
2804 : test_mode_(test_mode), test_url_(test_url) {}
2805
RunTest()2806 void RunTest() override {
2807 CefRefPtr<CefDictionaryValue> extra_info = CefDictionaryValue::Create();
2808 extra_info->SetInt(kV8TestCmdKey, test_mode_);
2809
2810 // Nested script tag forces creation of the V8 context.
2811 if (test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL ||
2812 test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX) {
2813 std::string url;
2814 ResourceContent::HeaderMap headers;
2815 if (test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL) {
2816 url = kV8ContextEvalCspBypassUnsafeEval;
2817 headers.insert(std::pair<std::string, std::string>(
2818 "Content-Security-Policy", "script-src 'self'"));
2819 } else if (test_mode_ == V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX) {
2820 url = kV8ContextEvalCspBypassSandbox;
2821 headers.insert(std::pair<std::string, std::string>(
2822 "Content-Security-Policy", "sandbox"));
2823 } else {
2824 NOTREACHED();
2825 }
2826 AddResource(url,
2827 "<html><body>" + url +
2828 "<p id='result' style='display:none'>CSP_BYPASSED</p>"
2829 "</body></html>",
2830 "text/html", headers);
2831 CreateBrowser(test_url_, nullptr, extra_info);
2832 } else if (test_mode_ == V8TEST_CONTEXT_ENTERED) {
2833 AddResource(kV8ContextParentTestUrl,
2834 "<html><body>"
2835 "<script>var i = 0;</script><iframe src=\"" +
2836 std::string(kV8ContextChildTestUrl) +
2837 "\" id=\"f\"></iframe></body>"
2838 "</html>",
2839 "text/html");
2840 AddResource(kV8ContextChildTestUrl,
2841 "<html><body>"
2842 "<script>var i = 0;</script>CHILD</body></html>",
2843 "text/html");
2844 CreateBrowser(kV8ContextParentTestUrl, nullptr, extra_info);
2845 } else if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
2846 test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
2847 AddResource(kV8OnUncaughtExceptionTestUrl,
2848 "<html><body>"
2849 "<h1>OnUncaughtException</h1>"
2850 "<script>\n"
2851 "function test(){ test2(); }\n"
2852 "function test2(){ asd(); }\n"
2853 "</script>\n"
2854 "</body></html>\n",
2855 "text/html");
2856 CreateBrowser(kV8OnUncaughtExceptionTestUrl, nullptr, extra_info);
2857 } else if (test_mode_ == V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT) {
2858 AddResource(kV8HandlerCallOnReleasedContextUrl,
2859 "<html><body onload='createFrame()'>"
2860 "(main)"
2861 "<script>"
2862 "function createFrame() {"
2863 " var el = document.createElement('iframe');"
2864 " el.id = 'child';"
2865 " el.src = '" +
2866 std::string(kV8HandlerCallOnReleasedContextChildUrl) +
2867 "';"
2868 " el.onload = function() {"
2869 " setTimeout(function() {"
2870 " try {"
2871 " el.contentWindow.removeMe();"
2872 " window.notify_test_done();"
2873 " } catch (e) { alert('Unit test error.\\n' + e); }"
2874 " }, 1000);"
2875 " };"
2876 " document.body.appendChild(el);"
2877 "}"
2878 ""
2879 "function removeFrame(id) {"
2880 " var el = document.getElementById(id);"
2881 " if (el) { el.parentElement.removeChild(el); }"
2882 " else { alert('Error in test. No element \"' + id + "
2883 "'\" found.'); }"
2884 "}"
2885 "</script>"
2886 "</body></html>",
2887 "text/html");
2888 AddResource(kV8HandlerCallOnReleasedContextChildUrl,
2889 "<html><body>"
2890 "(child)"
2891 "<script>"
2892 "try {"
2893 " if (!window.v8_context_is_alive()) {"
2894 " throw 'v8_context_is_alive returns non-true value.';"
2895 " }"
2896 "} catch (e) {"
2897 " alert('Unit test error.\\n' + e);"
2898 "}"
2899 ""
2900 "function removeMe() {"
2901 " var w = window;"
2902 " w.parent.removeFrame('child');"
2903 " return w.v8_context_is_alive();"
2904 "}"
2905 "</script>"
2906 "</body></html>",
2907 "text/html");
2908 CreateBrowser(kV8HandlerCallOnReleasedContextUrl, nullptr, extra_info);
2909 } else {
2910 EXPECT_TRUE(test_url_ != nullptr);
2911 AddResource(test_url_,
2912 "<html><body>"
2913 "<script>var i = 0;</script>TEST</body></html>",
2914 "text/html");
2915 CreateBrowser(test_url_, nullptr, extra_info);
2916 }
2917
2918 // Time out the test after a reasonable period of time.
2919 SetTestTimeout(test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ? 10000
2920 : 5000);
2921 }
2922
OnBeforeClose(CefRefPtr<CefBrowser> browser)2923 void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
2924 if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS &&
2925 browser->IsPopup()) {
2926 // Generate the uncaught exception in the main browser. Use a 200ms delay
2927 // because there's a bit of a lag between destroying the DevToolsAgent and
2928 // re-registering for uncaught exceptions.
2929 GetBrowser()->GetMainFrame()->ExecuteJavaScript(
2930 "window.setTimeout(test, 200);",
2931 GetBrowser()->GetMainFrame()->GetURL(), 0);
2932 }
2933
2934 TestHandler::OnBeforeClose(browser);
2935 }
2936
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)2937 void OnLoadEnd(CefRefPtr<CefBrowser> browser,
2938 CefRefPtr<CefFrame> frame,
2939 int httpStatusCode) override {
2940 if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
2941 if (!browser->IsPopup()) {
2942 // Create the DevTools window.
2943 CefWindowInfo windowInfo;
2944 CefBrowserSettings settings;
2945
2946 #if defined(OS_WIN)
2947 windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(),
2948 "DevTools");
2949 #endif
2950
2951 browser->GetHost()->ShowDevTools(windowInfo, this, settings,
2952 CefPoint());
2953 }
2954 return;
2955 }
2956
2957 const std::string& url = frame->GetURL();
2958 if (url != kV8NavTestUrl && url != kV8ContextParentTestUrl &&
2959 url.find("http://tests/") != std::string::npos) {
2960 // Run the test.
2961 CefRefPtr<CefProcessMessage> return_msg =
2962 CefProcessMessage::Create(kV8RunTestMsg);
2963 frame->SendProcessMessage(PID_RENDERER, return_msg);
2964 }
2965 }
2966
OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefProcessId source_process,CefRefPtr<CefProcessMessage> message)2967 bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
2968 CefRefPtr<CefFrame> frame,
2969 CefProcessId source_process,
2970 CefRefPtr<CefProcessMessage> message) override {
2971 EXPECT_TRUE(browser.get());
2972 EXPECT_TRUE(frame.get());
2973 EXPECT_TRUE(frame->IsMain());
2974 EXPECT_EQ(PID_RENDERER, source_process);
2975 EXPECT_TRUE(message.get());
2976 EXPECT_TRUE(message->IsReadOnly());
2977
2978 const std::string& message_name = message->GetName();
2979 EXPECT_STREQ(kV8TestMsg, message_name.c_str());
2980
2981 got_message_.yes();
2982
2983 if (message->GetArgumentList()->GetBool(0))
2984 got_success_.yes();
2985
2986 // Test is complete.
2987 DestroyTest();
2988
2989 return true;
2990 }
2991
2992 V8TestMode test_mode_;
2993 const char* test_url_;
2994 TrackCallback got_message_;
2995 TrackCallback got_success_;
2996
2997 IMPLEMENT_REFCOUNTING(V8TestHandler);
2998 };
2999
3000 } // namespace
3001
3002 // Entry point for creating V8 renderer test objects.
3003 // Called from client_app_delegates.cc.
CreateV8RendererTests(ClientAppRenderer::DelegateSet & delegates)3004 void CreateV8RendererTests(ClientAppRenderer::DelegateSet& delegates) {
3005 delegates.insert(new V8RendererTest);
3006 }
3007
3008 // Helpers for defining V8 tests.
3009 #define V8_TEST_EX(name, test_mode, test_url) \
3010 TEST(V8Test, name) { \
3011 CefRefPtr<V8TestHandler> handler = new V8TestHandler(test_mode, test_url); \
3012 handler->ExecuteTest(); \
3013 EXPECT_TRUE(handler->got_message_); \
3014 EXPECT_TRUE(handler->got_success_); \
3015 ReleaseAndWaitForDestructor(handler); \
3016 }
3017
3018 #define V8_TEST(name, test_mode) V8_TEST_EX(name, test_mode, kV8TestUrl)
3019
3020 // Define the tests.
3021 V8_TEST(NullCreate, V8TEST_NULL_CREATE)
3022 V8_TEST(BoolCreate, V8TEST_BOOL_CREATE)
3023 V8_TEST(IntCreate, V8TEST_INT_CREATE)
3024 V8_TEST(UIntCreate, V8TEST_UINT_CREATE)
3025 V8_TEST(DoubleCreate, V8TEST_DOUBLE_CREATE)
3026 V8_TEST(DateCreate, V8TEST_DATE_CREATE)
3027 V8_TEST(StringCreate, V8TEST_STRING_CREATE)
3028 V8_TEST(EmptyStringCreate, V8TEST_EMPTY_STRING_CREATE)
3029 V8_TEST(ArrayCreate, V8TEST_ARRAY_CREATE)
3030 V8_TEST(ArrayValue, V8TEST_ARRAY_VALUE)
3031 V8_TEST(ArrayBuffer, V8TEST_ARRAY_BUFFER)
3032 V8_TEST(ArrayBufferValue, V8TEST_ARRAY_BUFFER_VALUE)
3033 V8_TEST(ObjectCreate, V8TEST_OBJECT_CREATE)
3034 V8_TEST(ObjectUserData, V8TEST_OBJECT_USERDATA)
3035 V8_TEST(ObjectAccessor, V8TEST_OBJECT_ACCESSOR)
3036 V8_TEST(ObjectAccessorException, V8TEST_OBJECT_ACCESSOR_EXCEPTION)
3037 V8_TEST(ObjectAccessorFail, V8TEST_OBJECT_ACCESSOR_FAIL)
3038 V8_TEST(ObjectAccessorReadOnly, V8TEST_OBJECT_ACCESSOR_READONLY)
3039 V8_TEST(ObjectInterceptor, V8TEST_OBJECT_INTERCEPTOR)
3040 V8_TEST(ObjectInterceptorFail, V8TEST_OBJECT_INTERCEPTOR_FAIL)
3041 V8_TEST(ObjectInterceptorException, V8TEST_OBJECT_INTERCEPTOR_EXCEPTION)
3042 V8_TEST(ObjectInterceptorAndAccessor, V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR)
3043 V8_TEST(ObjectValue, V8TEST_OBJECT_VALUE)
3044 V8_TEST(ObjectValueReadOnly, V8TEST_OBJECT_VALUE_READONLY)
3045 V8_TEST(ObjectValueEnum, V8TEST_OBJECT_VALUE_ENUM)
3046 V8_TEST(ObjectValueDontEnum, V8TEST_OBJECT_VALUE_DONTENUM)
3047 V8_TEST(ObjectValueDelete, V8TEST_OBJECT_VALUE_DELETE)
3048 V8_TEST(ObjectValueDontDelete, V8TEST_OBJECT_VALUE_DONTDELETE)
3049 V8_TEST(ObjectValueEmptyKey, V8TEST_OBJECT_VALUE_EMPTYKEY)
3050 V8_TEST(FunctionCreate, V8TEST_FUNCTION_CREATE)
3051 V8_TEST(FunctionHandler, V8TEST_FUNCTION_HANDLER)
3052 V8_TEST(FunctionHandlerException, V8TEST_FUNCTION_HANDLER_EXCEPTION)
3053 V8_TEST(FunctionHandlerFail, V8TEST_FUNCTION_HANDLER_FAIL)
3054 V8_TEST(FunctionHandlerNoObject, V8TEST_FUNCTION_HANDLER_NO_OBJECT)
3055 V8_TEST(FunctionHandlerWithContext, V8TEST_FUNCTION_HANDLER_WITH_CONTEXT)
3056 V8_TEST(FunctionHandlerEmptyString, V8TEST_FUNCTION_HANDLER_EMPTY_STRING)
3057 V8_TEST(ContextEval, V8TEST_CONTEXT_EVAL)
3058 V8_TEST(ContextEvalException, V8TEST_CONTEXT_EVAL_EXCEPTION)
3059 V8_TEST_EX(ContextEvalCspBypassUnsafeEval,
3060 V8TEST_CONTEXT_EVAL_CSP_BYPASS_UNSAFE_EVAL,
3061 kV8ContextEvalCspBypassUnsafeEval)
3062 V8_TEST_EX(ContextEvalCspBypassSandbox,
3063 V8TEST_CONTEXT_EVAL_CSP_BYPASS_SANDBOX,
3064 kV8ContextEvalCspBypassSandbox)
3065 V8_TEST_EX(ContextEntered, V8TEST_CONTEXT_ENTERED, nullptr)
3066 V8_TEST_EX(Binding, V8TEST_BINDING, kV8BindingTestUrl)
3067 V8_TEST(StackTrace, V8TEST_STACK_TRACE)
3068 V8_TEST(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION)
3069 V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS)
3070 V8_TEST(Extension, V8TEST_EXTENSION)
3071 V8_TEST_EX(HandlerCallOnReleasedContext,
3072 V8TEST_HANDLER_CALL_ON_RELEASED_CONTEXT,
3073 kV8HandlerCallOnReleasedContextUrl)
3074