• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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