Add V8 interceptor support (issue #1159)

This commit is contained in:
Marshall Greenblatt 2016-10-27 13:23:56 -04:00
parent 917b4a0de5
commit e006ec0ab5
17 changed files with 1454 additions and 37 deletions

View File

@ -29,3 +29,4 @@ Felix Bruns <felixbruns@spotify.com>
YuTeh Shen <shenyute@gmail.com>
Andrei Kurushin <ajax16384@gmail.com>
Gonzo Berman <gberman@factset.com>
Jakub Trzebiatowski <kuba.trzebiatowski@gmail.com>

View File

@ -400,6 +400,8 @@
'libcef_dll/cpptoc/v8exception_cpptoc.h',
'libcef_dll/ctocpp/v8handler_ctocpp.cc',
'libcef_dll/ctocpp/v8handler_ctocpp.h',
'libcef_dll/ctocpp/v8interceptor_ctocpp.cc',
'libcef_dll/ctocpp/v8interceptor_ctocpp.h',
'libcef_dll/cpptoc/v8stack_frame_cpptoc.cc',
'libcef_dll/cpptoc/v8stack_frame_cpptoc.h',
'libcef_dll/cpptoc/v8stack_trace_cpptoc.cc',
@ -654,6 +656,8 @@
'libcef_dll/ctocpp/v8exception_ctocpp.h',
'libcef_dll/cpptoc/v8handler_cpptoc.cc',
'libcef_dll/cpptoc/v8handler_cpptoc.h',
'libcef_dll/cpptoc/v8interceptor_cpptoc.cc',
'libcef_dll/cpptoc/v8interceptor_cpptoc.h',
'libcef_dll/ctocpp/v8stack_frame_ctocpp.cc',
'libcef_dll/ctocpp/v8stack_frame_ctocpp.h',
'libcef_dll/ctocpp/v8stack_trace_ctocpp.cc',

View File

@ -213,6 +213,70 @@ typedef struct _cef_v8accessor_t {
} cef_v8accessor_t;
///
// Structure that should be implemented to handle V8 interceptor calls. The
// functions of this structure will be called on the thread associated with the
// V8 interceptor. Interceptor's named property handlers (with first argument of
// type CefString) are called when object is indexed by string. Indexed property
// handlers (with first argument of type int) are called when object is indexed
// by integer.
///
typedef struct _cef_v8interceptor_t {
///
// Base structure.
///
cef_base_t base;
///
// Handle retrieval of the interceptor value identified by |name|. |object| is
// the receiver ('this' object) of the interceptor. If retrieval succeeds, set
// |retval| to the return value. If the requested value does not exist, don't
// set either |retval| or |exception|. If retrieval fails, set |exception| to
// the exception that will be thrown. If the property has an associated
// accessor, it will be called only if you don't set |retval|. Return true (1)
// if interceptor retrieval was handled, false (0) otherwise.
///
int (CEF_CALLBACK *get_byname)(struct _cef_v8interceptor_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
struct _cef_v8value_t** retval, cef_string_t* exception);
///
// Handle retrieval of the interceptor value identified by |index|. |object|
// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
// set |retval| to the return value. If the requested value does not exist,
// don't set either |retval| or |exception|. If retrieval fails, set
// |exception| to the exception that will be thrown. Return true (1) if
// interceptor retrieval was handled, false (0) otherwise.
///
int (CEF_CALLBACK *get_byindex)(struct _cef_v8interceptor_t* self, int index,
struct _cef_v8value_t* object, struct _cef_v8value_t** retval,
cef_string_t* exception);
///
// Handle assignment of the interceptor value identified by |name|. |object|
// is the receiver ('this' object) of the interceptor. |value| is the new
// value being assigned to the interceptor. If assignment fails, set
// |exception| to the exception that will be thrown. This setter will always
// be called, even when the property has an associated accessor. Return true
// (1) if interceptor assignment was handled, false (0) otherwise.
///
int (CEF_CALLBACK *set_byname)(struct _cef_v8interceptor_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
struct _cef_v8value_t* value, cef_string_t* exception);
///
// Handle assignment of the interceptor value identified by |index|. |object|
// is the receiver ('this' object) of the interceptor. |value| is the new
// value being assigned to the interceptor. If assignment fails, set
// |exception| to the exception that will be thrown. Return true (1) if
// interceptor assignment was handled, false (0) otherwise.
///
int (CEF_CALLBACK *set_byindex)(struct _cef_v8interceptor_t* self, int index,
struct _cef_v8value_t* object, struct _cef_v8value_t* value,
cef_string_t* exception);
} cef_v8interceptor_t;
///
// Structure representing a V8 exception. The functions of this structure may be
// called on any render process thread.
@ -654,13 +718,14 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_date(const cef_time_t* date);
CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value);
///
// Create a new cef_v8value_t object of type object with optional accessor. This
// function should only be called from within the scope of a
// cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t callback,
// or in combination with calling enter() and exit() on a stored cef_v8context_t
// reference.
// Create a new cef_v8value_t object of type object with optional accessor
// and/or interceptor. This function should only be called from within the scope
// of a cef_render_process_handler_t, cef_v8handler_t or cef_v8accessor_t
// callback, or in combination with calling enter() and exit() on a stored
// cef_v8context_t reference.
///
CEF_EXPORT cef_v8value_t* cef_v8value_create_object(cef_v8accessor_t* accessor);
CEF_EXPORT cef_v8value_t* cef_v8value_create_object(cef_v8accessor_t* accessor,
cef_v8interceptor_t* interceptor);
///
// Create a new cef_v8value_t object of type array with the specified |length|.

View File

@ -281,6 +281,74 @@ class CefV8Accessor : public virtual CefBase {
CefString& exception) =0;
};
///
// Interface that should be implemented to handle V8 interceptor calls. The
// methods of this class will be called on the thread associated with the V8
// interceptor. Interceptor's named property handlers (with first argument of
// type CefString) are called when object is indexed by string. Indexed property
// handlers (with first argument of type int) are called when object is indexed
// by integer.
///
/*--cef(source=client)--*/
class CefV8Interceptor : public virtual CefBase {
public:
///
// Handle retrieval of the interceptor value identified by |name|. |object| is
// the receiver ('this' object) of the interceptor. If retrieval succeeds, set
// |retval| to the return value. If the requested value does not exist, don't
// set either |retval| or |exception|. If retrieval fails, set |exception| to
// the exception that will be thrown. If the property has an associated
// accessor, it will be called only if you don't set |retval|.
// Return true if interceptor retrieval was handled, false otherwise.
///
/*--cef(capi_name=get_byname)--*/
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
///
// Handle retrieval of the interceptor value identified by |index|. |object|
// is the receiver ('this' object) of the interceptor. If retrieval succeeds,
// set |retval| to the return value. If the requested value does not exist,
// don't set either |retval| or |exception|. If retrieval fails, set
// |exception| to the exception that will be thrown.
// Return true if interceptor retrieval was handled, false otherwise.
///
/*--cef(capi_name=get_byindex,index_param=index)--*/
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
///
// Handle assignment of the interceptor value identified by |name|. |object|
// is the receiver ('this' object) of the interceptor. |value| is the new
// value being assigned to the interceptor. If assignment fails, set
// |exception| to the exception that will be thrown. This setter will always
// be called, even when the property has an associated accessor.
// Return true if interceptor assignment was handled, false otherwise.
///
/*--cef(capi_name=set_byname)--*/
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) =0;
///
// Handle assignment of the interceptor value identified by |index|. |object|
// is the receiver ('this' object) of the interceptor. |value| is the new
// value being assigned to the interceptor. If assignment fails, set
// |exception| to the exception that will be thrown.
// Return true if interceptor assignment was handled, false otherwise.
///
/*--cef(capi_name=set_byindex,index_param=index)--*/
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) =0;
};
///
// Class representing a V8 exception. The methods of this class may be called on
// any render process thread.
@ -408,14 +476,16 @@ class CefV8Value : public virtual CefBase {
static CefRefPtr<CefV8Value> CreateString(const CefString& value);
///
// Create a new CefV8Value object of type object with optional accessor. This
// method should only be called from within the scope of a
// Create a new CefV8Value object of type object with optional accessor and/or
// interceptor. This method should only be called from within the scope of a
// CefRenderProcessHandler, CefV8Handler or CefV8Accessor callback, or in
// combination with calling Enter() and Exit() on a stored CefV8Context
// reference.
///
/*--cef(optional_param=accessor)--*/
static CefRefPtr<CefV8Value> CreateObject(CefRefPtr<CefV8Accessor> accessor);
/*--cef(optional_param=accessor, optional_param=interceptor)--*/
static CefRefPtr<CefV8Value> CreateObject(
CefRefPtr<CefV8Accessor> accessor,
CefRefPtr<CefV8Interceptor> interceptor);
///
// Create a new CefV8Value object of type array with the specified |length|.

View File

@ -337,6 +337,14 @@ class V8TrackObject : public CefTrackNode {
return accessor_;
}
inline void SetInterceptor(CefRefPtr<CefV8Interceptor> interceptor) {
interceptor_ = interceptor;
}
inline CefRefPtr<CefV8Interceptor> GetInterceptor() {
return interceptor_;
}
inline void SetHandler(CefRefPtr<CefV8Handler> handler) {
handler_ = handler;
}
@ -373,6 +381,7 @@ class V8TrackObject : public CefTrackNode {
private:
v8::Isolate* isolate_;
CefRefPtr<CefV8Accessor> accessor_;
CefRefPtr<CefV8Interceptor> interceptor_;
CefRefPtr<CefV8Handler> handler_;
CefRefPtr<CefBase> user_data_;
int external_memory_;
@ -645,6 +654,77 @@ void AccessorNameSetterCallbackImpl(
}
}
// Two helper functions for V8 Interceptor callbacks.
CefString PropertyToIndex(v8::Local<v8::String> str) {
CefString name;
GetCefString(str, name);
return name;
}
int PropertyToIndex(uint32_t index) {
return static_cast<int>(index);
}
// V8 Interceptor callbacks.
// T == v8::Local<v8::String> for named property handlers and
// T == uint32_t for indexed property handlers
template<typename T>
void InterceptorGetterCallbackImpl(
T property,
const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Handle<v8::Object> obj = info.This();
CefRefPtr<CefV8Interceptor> interceptorPtr;
V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
if (tracker)
interceptorPtr = tracker->GetInterceptor();
if (!interceptorPtr.get())
return;
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
CefRefPtr<CefV8Value> retval;
CefString exception;
interceptorPtr->Get(PropertyToIndex(property), object, retval, exception);
if (!exception.empty()) {
info.GetReturnValue().Set(isolate->ThrowException(
v8::Exception::Error(GetV8String(isolate, exception))));
} else {
CefV8ValueImpl* retval_impl = static_cast<CefV8ValueImpl*>(retval.get());
if (retval_impl && retval_impl->IsValid()) {
info.GetReturnValue().Set(retval_impl->GetV8Value(true));
}
}
}
template<typename T>
void InterceptorSetterCallbackImpl(
T property,
v8::Local<v8::Value> value,
const v8::PropertyCallbackInfo<v8::Value>& info) {
v8::Isolate* isolate = info.GetIsolate();
v8::Local<v8::Context> context = isolate->GetCurrentContext();
v8::Handle<v8::Object> obj = info.This();
CefRefPtr<CefV8Interceptor> interceptorPtr;
V8TrackObject* tracker = V8TrackObject::Unwrap(context, obj);
if (tracker)
interceptorPtr = tracker->GetInterceptor();
if (!interceptorPtr.get())
return;
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(isolate, context, obj);
CefRefPtr<CefV8Value> cefValue = new CefV8ValueImpl(isolate, context, value);
CefString exception;
interceptorPtr->Set(PropertyToIndex(property), object, cefValue, exception);
if (!exception.empty()) {
isolate->ThrowException(
v8::Exception::Error(GetV8String(isolate, exception)));
}
}
// V8 extension registration.
class ExtensionWrapper : public v8::Extension {
@ -1260,7 +1340,8 @@ CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
// static
CefRefPtr<CefV8Value> CefV8Value::CreateObject(
CefRefPtr<CefV8Accessor> accessor) {
CefRefPtr<CefV8Accessor> accessor,
CefRefPtr<CefV8Interceptor> interceptor) {
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::Isolate* isolate = GetIsolateManager()->isolate();
@ -1272,13 +1353,28 @@ CefRefPtr<CefV8Value> CefV8Value::CreateObject(
return NULL;
}
// Create the new V8 object.
v8::Local<v8::Object> obj = v8::Object::New(isolate);
// Create the new V8 object. If an interceptor is passed, create object from
// template and set property handlers.
v8::Local<v8::Object> obj;
if (interceptor.get()) {
v8::Local<v8::ObjectTemplate> tmpl = v8::ObjectTemplate::New(isolate);
tmpl->SetNamedPropertyHandler(
InterceptorGetterCallbackImpl<v8::Local<v8::String>>,
InterceptorSetterCallbackImpl<v8::Local<v8::String>>);
tmpl->SetIndexedPropertyHandler(InterceptorGetterCallbackImpl<uint32_t>,
InterceptorSetterCallbackImpl<uint32_t>);
obj = tmpl->NewInstance();
} else {
obj = v8::Object::New(isolate);
}
// Create a tracker object that will cause the user data and/or accessor
// reference to be released when the V8 object is destroyed.
// and/or interceptor reference to be released when the V8 object is
// destroyed.
V8TrackObject* tracker = new V8TrackObject(isolate);
tracker->SetAccessor(accessor);
tracker->SetInterceptor(interceptor);
// Attach the tracker object.
tracker->AttachTo(context, obj);

View File

@ -0,0 +1,234 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/v8interceptor_cpptoc.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK v8interceptor_get_byname(struct _cef_v8interceptor_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
struct _cef_v8value_t** retval, cef_string_t* exception) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: name; type: string_byref_const
DCHECK(name);
if (!name)
return 0;
// Verify param: object; type: refptr_diff
DCHECK(object);
if (!object)
return 0;
// Verify param: retval; type: refptr_diff_byref
DCHECK(retval);
if (!retval)
return 0;
// Verify param: exception; type: string_byref
DCHECK(exception);
if (!exception)
return 0;
// Translate param: retval; type: refptr_diff_byref
CefRefPtr<CefV8Value> retvalPtr;
if (retval && *retval)
retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
CefV8Value* retvalOrig = retvalPtr.get();
// Translate param: exception; type: string_byref
CefString exceptionStr(exception);
// Execute
bool _retval = CefV8InterceptorCppToC::Get(self)->Get(
CefString(name),
CefV8ValueCToCpp::Wrap(object),
retvalPtr,
exceptionStr);
// Restore param: retval; type: refptr_diff_byref
if (retval) {
if (retvalPtr.get()) {
if (retvalPtr.get() != retvalOrig) {
*retval = CefV8ValueCToCpp::Unwrap(retvalPtr);
}
} else {
*retval = NULL;
}
}
// Return type: bool
return _retval;
}
int CEF_CALLBACK v8interceptor_get_byindex(struct _cef_v8interceptor_t* self,
int index, struct _cef_v8value_t* object, struct _cef_v8value_t** retval,
cef_string_t* exception) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: index; type: simple_byval
DCHECK_GE(index, 0);
if (index < 0)
return 0;
// Verify param: object; type: refptr_diff
DCHECK(object);
if (!object)
return 0;
// Verify param: retval; type: refptr_diff_byref
DCHECK(retval);
if (!retval)
return 0;
// Verify param: exception; type: string_byref
DCHECK(exception);
if (!exception)
return 0;
// Translate param: retval; type: refptr_diff_byref
CefRefPtr<CefV8Value> retvalPtr;
if (retval && *retval)
retvalPtr = CefV8ValueCToCpp::Wrap(*retval);
CefV8Value* retvalOrig = retvalPtr.get();
// Translate param: exception; type: string_byref
CefString exceptionStr(exception);
// Execute
bool _retval = CefV8InterceptorCppToC::Get(self)->Get(
index,
CefV8ValueCToCpp::Wrap(object),
retvalPtr,
exceptionStr);
// Restore param: retval; type: refptr_diff_byref
if (retval) {
if (retvalPtr.get()) {
if (retvalPtr.get() != retvalOrig) {
*retval = CefV8ValueCToCpp::Unwrap(retvalPtr);
}
} else {
*retval = NULL;
}
}
// Return type: bool
return _retval;
}
int CEF_CALLBACK v8interceptor_set_byname(struct _cef_v8interceptor_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
struct _cef_v8value_t* value, cef_string_t* exception) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: name; type: string_byref_const
DCHECK(name);
if (!name)
return 0;
// Verify param: object; type: refptr_diff
DCHECK(object);
if (!object)
return 0;
// Verify param: value; type: refptr_diff
DCHECK(value);
if (!value)
return 0;
// Verify param: exception; type: string_byref
DCHECK(exception);
if (!exception)
return 0;
// Translate param: exception; type: string_byref
CefString exceptionStr(exception);
// Execute
bool _retval = CefV8InterceptorCppToC::Get(self)->Set(
CefString(name),
CefV8ValueCToCpp::Wrap(object),
CefV8ValueCToCpp::Wrap(value),
exceptionStr);
// Return type: bool
return _retval;
}
int CEF_CALLBACK v8interceptor_set_byindex(struct _cef_v8interceptor_t* self,
int index, struct _cef_v8value_t* object, struct _cef_v8value_t* value,
cef_string_t* exception) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: index; type: simple_byval
DCHECK_GE(index, 0);
if (index < 0)
return 0;
// Verify param: object; type: refptr_diff
DCHECK(object);
if (!object)
return 0;
// Verify param: value; type: refptr_diff
DCHECK(value);
if (!value)
return 0;
// Verify param: exception; type: string_byref
DCHECK(exception);
if (!exception)
return 0;
// Translate param: exception; type: string_byref
CefString exceptionStr(exception);
// Execute
bool _retval = CefV8InterceptorCppToC::Get(self)->Set(
index,
CefV8ValueCToCpp::Wrap(object),
CefV8ValueCToCpp::Wrap(value),
exceptionStr);
// Return type: bool
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefV8InterceptorCppToC::CefV8InterceptorCppToC() {
GetStruct()->get_byname = v8interceptor_get_byname;
GetStruct()->get_byindex = v8interceptor_get_byindex;
GetStruct()->set_byname = v8interceptor_set_byname;
GetStruct()->set_byindex = v8interceptor_set_byindex;
}
template<> CefRefPtr<CefV8Interceptor> CefCppToC<CefV8InterceptorCppToC,
CefV8Interceptor, cef_v8interceptor_t>::UnwrapDerived(CefWrapperType type,
cef_v8interceptor_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCppToC<CefV8InterceptorCppToC,
CefV8Interceptor, cef_v8interceptor_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCppToC<CefV8InterceptorCppToC, CefV8Interceptor,
cef_v8interceptor_t>::kWrapperType = WT_V8INTERCEPTOR;

View File

@ -0,0 +1,35 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_V8INTERCEPTOR_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_V8INTERCEPTOR_CPPTOC_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_v8.h"
#include "include/capi/cef_v8_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed wrapper-side only.
class CefV8InterceptorCppToC
: public CefCppToC<CefV8InterceptorCppToC, CefV8Interceptor,
cef_v8interceptor_t> {
public:
CefV8InterceptorCppToC();
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_V8INTERCEPTOR_CPPTOC_H_

View File

@ -16,6 +16,7 @@
#include "libcef_dll/ctocpp/base_ctocpp.h"
#include "libcef_dll/ctocpp/v8accessor_ctocpp.h"
#include "libcef_dll/ctocpp/v8handler_ctocpp.h"
#include "libcef_dll/ctocpp/v8interceptor_ctocpp.h"
#include "libcef_dll/transfer_util.h"
@ -117,15 +118,16 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_string(const cef_string_t* value) {
return CefV8ValueCppToC::Wrap(_retval);
}
CEF_EXPORT cef_v8value_t* cef_v8value_create_object(
cef_v8accessor_t* accessor) {
CEF_EXPORT cef_v8value_t* cef_v8value_create_object(cef_v8accessor_t* accessor,
cef_v8interceptor_t* interceptor) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: accessor
// Unverified params: accessor, interceptor
// Execute
CefRefPtr<CefV8Value> _retval = CefV8Value::CreateObject(
CefV8AccessorCToCpp::Wrap(accessor));
CefV8AccessorCToCpp::Wrap(accessor),
CefV8InterceptorCToCpp::Wrap(interceptor));
// Return type: refptr_same
return CefV8ValueCppToC::Wrap(_retval);

View File

@ -0,0 +1,190 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
#include "libcef_dll/ctocpp/v8interceptor_ctocpp.h"
// VIRTUAL METHODS - Body may be edited by hand.
bool CefV8InterceptorCToCpp::Get(const CefString& name,
const CefRefPtr<CefV8Value> object, CefRefPtr<CefV8Value>& retval,
CefString& exception) {
cef_v8interceptor_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_byname))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: name; type: string_byref_const
DCHECK(!name.empty());
if (name.empty())
return false;
// Verify param: object; type: refptr_diff
DCHECK(object.get());
if (!object.get())
return false;
// Translate param: retval; type: refptr_diff_byref
cef_v8value_t* retvalStruct = NULL;
if (retval.get())
retvalStruct = CefV8ValueCppToC::Wrap(retval);
cef_v8value_t* retvalOrig = retvalStruct;
// Execute
int _retval = _struct->get_byname(_struct,
name.GetStruct(),
CefV8ValueCppToC::Wrap(object),
&retvalStruct,
exception.GetWritableStruct());
// Restore param:retval; type: refptr_diff_byref
if (retvalStruct) {
if (retvalStruct != retvalOrig) {
retval = CefV8ValueCppToC::Unwrap(retvalStruct);
}
} else {
retval = NULL;
}
// Return type: bool
return _retval?true:false;
}
bool CefV8InterceptorCToCpp::Get(int index, const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval, CefString& exception) {
cef_v8interceptor_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_byindex))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: index; type: simple_byval
DCHECK_GE(index, 0);
if (index < 0)
return false;
// Verify param: object; type: refptr_diff
DCHECK(object.get());
if (!object.get())
return false;
// Translate param: retval; type: refptr_diff_byref
cef_v8value_t* retvalStruct = NULL;
if (retval.get())
retvalStruct = CefV8ValueCppToC::Wrap(retval);
cef_v8value_t* retvalOrig = retvalStruct;
// Execute
int _retval = _struct->get_byindex(_struct,
index,
CefV8ValueCppToC::Wrap(object),
&retvalStruct,
exception.GetWritableStruct());
// Restore param:retval; type: refptr_diff_byref
if (retvalStruct) {
if (retvalStruct != retvalOrig) {
retval = CefV8ValueCppToC::Unwrap(retvalStruct);
}
} else {
retval = NULL;
}
// Return type: bool
return _retval?true:false;
}
bool CefV8InterceptorCToCpp::Set(const CefString& name,
const CefRefPtr<CefV8Value> object, const CefRefPtr<CefV8Value> value,
CefString& exception) {
cef_v8interceptor_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_byname))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: name; type: string_byref_const
DCHECK(!name.empty());
if (name.empty())
return false;
// Verify param: object; type: refptr_diff
DCHECK(object.get());
if (!object.get())
return false;
// Verify param: value; type: refptr_diff
DCHECK(value.get());
if (!value.get())
return false;
// Execute
int _retval = _struct->set_byname(_struct,
name.GetStruct(),
CefV8ValueCppToC::Wrap(object),
CefV8ValueCppToC::Wrap(value),
exception.GetWritableStruct());
// Return type: bool
return _retval?true:false;
}
bool CefV8InterceptorCToCpp::Set(int index, const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value, CefString& exception) {
cef_v8interceptor_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_byindex))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: index; type: simple_byval
DCHECK_GE(index, 0);
if (index < 0)
return false;
// Verify param: object; type: refptr_diff
DCHECK(object.get());
if (!object.get())
return false;
// Verify param: value; type: refptr_diff
DCHECK(value.get());
if (!value.get())
return false;
// Execute
int _retval = _struct->set_byindex(_struct,
index,
CefV8ValueCppToC::Wrap(object),
CefV8ValueCppToC::Wrap(value),
exception.GetWritableStruct());
// Return type: bool
return _retval?true:false;
}
// CONSTRUCTOR - Do not edit by hand.
CefV8InterceptorCToCpp::CefV8InterceptorCToCpp() {
}
template<> cef_v8interceptor_t* CefCToCpp<CefV8InterceptorCToCpp,
CefV8Interceptor, cef_v8interceptor_t>::UnwrapDerived(CefWrapperType type,
CefV8Interceptor* c) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCToCpp<CefV8InterceptorCToCpp,
CefV8Interceptor, cef_v8interceptor_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCToCpp<CefV8InterceptorCToCpp, CefV8Interceptor,
cef_v8interceptor_t>::kWrapperType = WT_V8INTERCEPTOR;

View File

@ -0,0 +1,45 @@
// Copyright (c) 2016 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_V8INTERCEPTOR_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_V8INTERCEPTOR_CTOCPP_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_v8.h"
#include "include/capi/cef_v8_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed DLL-side only.
class CefV8InterceptorCToCpp
: public CefCToCpp<CefV8InterceptorCToCpp, CefV8Interceptor,
cef_v8interceptor_t> {
public:
CefV8InterceptorCToCpp();
// CefV8Interceptor methods.
bool Get(const CefString& name, const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval, CefString& exception) override;
bool Get(int index, const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval, CefString& exception) override;
bool Set(const CefString& name, const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value, CefString& exception) override;
bool Set(int index, const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value, CefString& exception) override;
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_V8INTERCEPTOR_CTOCPP_H_

View File

@ -13,6 +13,7 @@
#include "libcef_dll/cpptoc/base_cpptoc.h"
#include "libcef_dll/cpptoc/v8accessor_cpptoc.h"
#include "libcef_dll/cpptoc/v8handler_cpptoc.h"
#include "libcef_dll/cpptoc/v8interceptor_cpptoc.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
@ -110,14 +111,16 @@ CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
}
CefRefPtr<CefV8Value> CefV8Value::CreateObject(
CefRefPtr<CefV8Accessor> accessor) {
CefRefPtr<CefV8Accessor> accessor,
CefRefPtr<CefV8Interceptor> interceptor) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: accessor
// Unverified params: accessor, interceptor
// Execute
cef_v8value_t* _retval = cef_v8value_create_object(
CefV8AccessorCppToC::Wrap(accessor));
CefV8AccessorCppToC::Wrap(accessor),
CefV8InterceptorCppToC::Wrap(interceptor));
// Return type: refptr_same
return CefV8ValueCToCpp::Wrap(_retval);

View File

@ -140,6 +140,7 @@
#include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h"
#include "libcef_dll/ctocpp/v8accessor_ctocpp.h"
#include "libcef_dll/ctocpp/v8handler_ctocpp.h"
#include "libcef_dll/ctocpp/v8interceptor_ctocpp.h"
#include "libcef_dll/ctocpp/views/view_delegate_ctocpp.h"
#include "libcef_dll/ctocpp/web_plugin_info_visitor_ctocpp.h"
#include "libcef_dll/ctocpp/web_plugin_unstable_callback_ctocpp.h"
@ -323,6 +324,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8InterceptorCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCppToC::DebugObjCt));

View File

@ -82,6 +82,7 @@
#include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h"
#include "libcef_dll/cpptoc/v8accessor_cpptoc.h"
#include "libcef_dll/cpptoc/v8handler_cpptoc.h"
#include "libcef_dll/cpptoc/v8interceptor_cpptoc.h"
#include "libcef_dll/cpptoc/views/view_delegate_cpptoc.h"
#include "libcef_dll/cpptoc/web_plugin_info_visitor_cpptoc.h"
#include "libcef_dll/cpptoc/web_plugin_unstable_callback_cpptoc.h"
@ -315,6 +316,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefV8ContextCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8ExceptionCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8HandlerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8InterceptorCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8StackFrameCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8StackTraceCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8ValueCToCpp::DebugObjCt));

View File

@ -126,6 +126,7 @@ enum CefWrapperType {
WT_V8CONTEXT,
WT_V8EXCEPTION,
WT_V8HANDLER,
WT_V8INTERCEPTOR,
WT_V8STACK_FRAME,
WT_V8STACK_TRACE,
WT_V8VALUE,

View File

@ -104,7 +104,7 @@ class V8Handler : public CefV8Handler {
retval = CefV8Value::CreateString("Hello, world!");
break;
case 8:
retval = CefV8Value::CreateObject(NULL);
retval = CefV8Value::CreateObject(NULL, NULL);
break;
case 9:
retval = CefV8Value::CreateArray(8);

View File

@ -154,7 +154,7 @@ PERF_TEST_FUNC(V8FunctionExecuteWithContext) {
PERF_TEST_FUNC(V8ObjectCreate) {
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL, NULL);
PERF_ITERATIONS_END()
}
@ -180,15 +180,53 @@ PERF_TEST_FUNC(V8ObjectCreateWithAccessor) {
CefRefPtr<CefV8Accessor> accessor = new Accessor();
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(accessor, NULL);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectCreateWithInterceptor) {
class Interceptor : public CefV8Interceptor {
public:
Interceptor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
return true;
}
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
return true;
}
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
return true;
}
IMPLEMENT_REFCOUNTING(Interceptor);
};
CefRefPtr<CefV8Interceptor> interceptor = new Interceptor();
PERF_ITERATIONS_START()
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL,
interceptor);
PERF_ITERATIONS_END()
}
PERF_TEST_FUNC(V8ObjectSetValue) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL, NULL);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
@ -199,7 +237,7 @@ PERF_TEST_FUNC(V8ObjectSetValue) {
PERF_TEST_FUNC(V8ObjectGetValue) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL, NULL);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
PERF_ITERATIONS_START()
@ -232,7 +270,7 @@ PERF_TEST_FUNC(V8ObjectSetValueWithAccessor) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor, NULL);
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
@ -266,7 +304,7 @@ PERF_TEST_FUNC(V8ObjectGetValueWithAccessor) {
CefString name = "name";
CefRefPtr<CefV8Value> val = CefV8Value::CreateBool(true);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(accessor, NULL);
obj->SetValue(name, V8_ACCESS_CONTROL_DEFAULT, V8_PROPERTY_ATTRIBUTE_NONE);
obj->SetValue(name, val, V8_PROPERTY_ATTRIBUTE_NONE);
@ -316,6 +354,7 @@ const PerfTestEntry kPerfTests[] = {
PERF_TEST_ENTRY(V8FunctionExecuteWithContext),
PERF_TEST_ENTRY(V8ObjectCreate),
PERF_TEST_ENTRY(V8ObjectCreateWithAccessor),
PERF_TEST_ENTRY(V8ObjectCreateWithInterceptor),
PERF_TEST_ENTRY(V8ObjectSetValue),
PERF_TEST_ENTRY(V8ObjectGetValue),
PERF_TEST_ENTRY(V8ObjectSetValueWithAccessor),

View File

@ -59,6 +59,10 @@ enum V8TestMode {
V8TEST_OBJECT_ACCESSOR_EXCEPTION,
V8TEST_OBJECT_ACCESSOR_FAIL,
V8TEST_OBJECT_ACCESSOR_READONLY,
V8TEST_OBJECT_INTERCEPTOR,
V8TEST_OBJECT_INTERCEPTOR_FAIL,
V8TEST_OBJECT_INTERCEPTOR_EXCEPTION,
V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR,
V8TEST_OBJECT_VALUE,
V8TEST_OBJECT_VALUE_READONLY,
V8TEST_OBJECT_VALUE_ENUM,
@ -171,6 +175,18 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
case V8TEST_OBJECT_ACCESSOR_READONLY:
RunObjectAccessorReadOnlyTest();
break;
case V8TEST_OBJECT_INTERCEPTOR:
RunObjectInterceptorTest();
break;
case V8TEST_OBJECT_INTERCEPTOR_FAIL:
RunObjectInterceptorFailTest();
break;
case V8TEST_OBJECT_INTERCEPTOR_EXCEPTION:
RunObjectInterceptorExceptionTest();
break;
case V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR:
RunObjectInterceptorAndAccessorTest();
break;
case V8TEST_OBJECT_VALUE:
RunObjectValueTest();
break;
@ -529,7 +545,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL, NULL);
EXPECT_TRUE(value.get());
EXPECT_TRUE(value->IsObject());
@ -565,7 +581,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> value = CefV8Value::CreateObject(NULL, NULL);
EXPECT_TRUE(value.get());
EXPECT_TRUE(value->SetUserData(new UserData(10)));
@ -640,7 +656,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
Accessor* accessor = new Accessor;
CefRefPtr<CefV8Accessor> accessorPtr(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, NULL);
EXPECT_TRUE(object.get());
accessor->object_ = object;
@ -715,7 +731,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
Accessor* accessor = new Accessor;
CefRefPtr<CefV8Accessor> accessorPtr(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, NULL);
EXPECT_TRUE(object.get());
EXPECT_FALSE(object->HasValue(kName));
@ -787,7 +803,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
Accessor* accessor = new Accessor;
CefRefPtr<CefV8Accessor> accessorPtr(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, NULL);
EXPECT_TRUE(object.get());
EXPECT_FALSE(object->HasValue(kName));
@ -851,7 +867,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
Accessor* accessor = new Accessor;
CefRefPtr<CefV8Accessor> accessorPtr(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(accessor, NULL);
EXPECT_TRUE(object.get());
EXPECT_FALSE(object->HasValue(kName));
@ -878,6 +894,613 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
DestroyTest();
}
void RunObjectInterceptorTest() {
CefRefPtr<CefV8Context> context = GetContext();
static const char* kName1 = "val1";
static const char* kName2 = "val2";
static const char* kName3 = "val3";
static const int kValue1 = 20;
static const uint32 kValue2 = 30u;
static const char* kValue3 = "40";
static const int kArray[] = {50, 60, 70};
class Interceptor : public CefV8Interceptor {
public:
Interceptor() : value1_(0), value2_(0u), array_() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
EXPECT_TRUE(name.ToString() == kName1 ||
name.ToString() == kName2 ||
name.ToString() == kName3);
EXPECT_TRUE(object.get());
EXPECT_TRUE(object->IsSame(object_));
EXPECT_FALSE(retval.get());
EXPECT_TRUE(exception.empty());
got_get_byname_.yes();
if (name.ToString() == kName1) {
retval = CefV8Value::CreateInt(value1_);
EXPECT_EQ(kValue1, retval->GetIntValue());
} else if (name.ToString() == kName2) {
retval = CefV8Value::CreateUInt(value2_);
EXPECT_EQ(kValue2, retval->GetUIntValue());
} else if (name.ToString() == kName3) {
retval = CefV8Value::CreateString(value3_);
EXPECT_STREQ(kValue3, retval->GetStringValue().ToString().c_str());
}
return true;
}
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
EXPECT_TRUE(index >= 0 && index < 3);
EXPECT_TRUE(object.get());
EXPECT_TRUE(object->IsSame(object_));
EXPECT_FALSE(retval.get());
EXPECT_TRUE(exception.empty());
got_get_byindex_.yes();
retval = CefV8Value::CreateInt(array_[index]);
EXPECT_EQ(kArray[index], retval->GetIntValue());
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
EXPECT_TRUE(name.ToString() == kName1 ||
name.ToString() == kName2 ||
name.ToString() == kName3);
EXPECT_TRUE(object.get());
EXPECT_TRUE(object->IsSame(object_));
EXPECT_TRUE(value.get());
EXPECT_TRUE(exception.empty());
got_set_byname_.yes();
if (name.ToString() == kName1) {
value1_ = value->GetIntValue();
EXPECT_EQ(kValue1, value1_);
} else if (name.ToString() == kName2) {
value2_ = value->GetUIntValue();
EXPECT_EQ(kValue2, value2_);
} else if (name.ToString() == kName3) {
value3_ = value->GetStringValue();
EXPECT_STREQ(kValue3, value3_.ToString().c_str());
}
return true;
}
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
EXPECT_TRUE(index >= 0 && index < 3);
EXPECT_TRUE(object.get());
EXPECT_TRUE(object->IsSame(object_));
EXPECT_TRUE(value.get());
EXPECT_TRUE(exception.empty());
got_set_byindex_.yes();
array_[index] = value->GetIntValue();
EXPECT_EQ(array_[index], kArray[index]);
return true;
}
CefRefPtr<CefV8Value> object_;
int value1_;
unsigned int value2_;
CefString value3_;
int array_[3];
TrackCallback got_get_byname_;
TrackCallback got_get_byindex_;
TrackCallback got_set_byname_;
TrackCallback got_set_byindex_;
IMPLEMENT_REFCOUNTING(Interceptor);
};
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
Interceptor* interceptor = new Interceptor;
CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL, interceptor);
EXPECT_TRUE(object.get());
interceptor->object_ = object;
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(object->SetValue(kName1, CefV8Value::CreateInt(kValue1),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byname_);
interceptor->got_set_byname_.reset();
EXPECT_TRUE(object->SetValue(kName2, CefV8Value::CreateUInt(kValue2),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byname_);
interceptor->got_set_byname_.reset();
EXPECT_TRUE(object->SetValue(kName3, CefV8Value::CreateString(kValue3),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byname_);
interceptor->got_set_byname_.reset();
EXPECT_EQ(kValue1, interceptor->value1_);
EXPECT_EQ(kValue2, interceptor->value2_);
EXPECT_STREQ(kValue3, interceptor->value3_.ToString().c_str());
for (int i=0; i<3; ++i) {
EXPECT_TRUE(object->SetValue(i, CefV8Value::CreateInt(kArray[i])));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byindex_);
interceptor->got_set_byindex_.reset();
EXPECT_EQ(kArray[i], interceptor->array_[i]);
}
CefRefPtr<CefV8Value> val1 = object->GetValue(kName1);
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(val1.get());
EXPECT_TRUE(interceptor->got_get_byname_);
interceptor->got_get_byname_.reset();
EXPECT_TRUE(val1->IsInt());
EXPECT_EQ(kValue1, val1->GetIntValue());
CefRefPtr<CefV8Value> val2 = object->GetValue(kName2);
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(val2.get());
EXPECT_TRUE(interceptor->got_get_byname_);
interceptor->got_get_byname_.reset();
EXPECT_TRUE(val2->IsUInt());
EXPECT_EQ(kValue2, val2->GetUIntValue());
CefRefPtr<CefV8Value> val3 = object->GetValue(kName3);
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(val3.get());
EXPECT_TRUE(interceptor->got_get_byname_);
interceptor->got_get_byname_.reset();
EXPECT_TRUE(val3->IsString());
EXPECT_STREQ(kValue3, val3->GetStringValue().ToString().c_str());
for (int i=0; i<3; ++i) {
CefRefPtr<CefV8Value> val = object->GetValue(i);
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(val.get());
EXPECT_TRUE(interceptor->got_get_byindex_);
interceptor->got_get_byname_.reset();
EXPECT_EQ(kArray[i], val->GetIntValue());
}
interceptor->object_ = NULL;
// Exit the V8 context.
EXPECT_TRUE(context->Exit());
DestroyTest();
}
void RunObjectInterceptorFailTest() {
CefRefPtr<CefV8Context> context = GetContext();
static const char* kName = "val";
static const int kIndex = 0;
static const int kValue1 = 20;
static const int kValue2 = 30;
class Interceptor : public CefV8Interceptor {
typedef std::map<int, int> IntMap;
typedef std::map<std::string, int> StringMap;
public:
Interceptor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_byname_.yes();
StringMap::iterator it = string_map_.find(name.ToString());
if(it != string_map_.end()) {
retval = CefV8Value::CreateInt(it->second);
}
return true;
}
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_byindex_.yes();
IntMap::iterator it = int_map_.find(index);
if(it != int_map_.end()) {
retval = CefV8Value::CreateInt(it->second);
}
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
EXPECT_TRUE(value->IsInt());
got_set_byname_.yes();
string_map_[name.ToString()] = value->GetIntValue();
return true;
}
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
EXPECT_TRUE(value->IsInt());
got_set_byindex_.yes();
int_map_[index] = value->GetIntValue();
return true;
}
IntMap int_map_;
StringMap string_map_;
TrackCallback got_get_byname_;
TrackCallback got_get_byindex_;
TrackCallback got_set_byname_;
TrackCallback got_set_byindex_;
IMPLEMENT_REFCOUNTING(Interceptor);
};
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
Interceptor* interceptor = new Interceptor;
CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL, interceptor);
EXPECT_TRUE(object.get());
EXPECT_FALSE(object->HasValue(kName));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byname_);
interceptor->got_get_byname_.reset();
CefRefPtr<CefV8Value> val1 = object->GetValue(kName);
EXPECT_TRUE(val1.get());
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byname_);
EXPECT_TRUE(val1->IsUndefined());
interceptor->got_get_byname_.reset();
EXPECT_TRUE(object->SetValue(
kName,
CefV8Value::CreateInt(kValue1), V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byname_);
val1 = object->GetValue(kName);
EXPECT_TRUE(val1.get());
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byname_);
EXPECT_EQ(kValue1, val1->GetIntValue());
EXPECT_FALSE(object->HasValue(kIndex));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byindex_);
interceptor->got_get_byindex_.reset();
CefRefPtr<CefV8Value> val2 = object->GetValue(kIndex);
EXPECT_TRUE(val2.get());
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byindex_);
EXPECT_TRUE(val2->IsUndefined());
interceptor->got_get_byindex_.reset();
EXPECT_TRUE(object->SetValue(kIndex, CefV8Value::CreateInt(kValue2)));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byindex_);
val2 = object->GetValue(kIndex);
EXPECT_TRUE(val2.get());
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byindex_);
EXPECT_EQ(kValue2, val2->GetIntValue());
// Exit the V8 context.
EXPECT_TRUE(context->Exit());
DestroyTest();
}
void RunObjectInterceptorExceptionTest() {
CefRefPtr<CefV8Context> context = GetContext();
static const char* kName = "val";
static const int kIndex = 1;
static const char* kGetByNameException = "My get_byname exception";
static const char* kGetByIndexException = "My get_byindex exception";
static const char* kSetByNameException = "My set_byname exception";
static const char* kSetByIndexException = "My set_byindex exception";
static const char* kGetByNameExceptionMsg =
"Uncaught Error: My get_byname exception";
static const char* kGetByIndexExceptionMsg =
"Uncaught Error: My get_byindex exception";
static const char* kSetByNameExceptionMsg =
"Uncaught Error: My set_byname exception";
static const char* kSetByIndexExceptionMsg =
"Uncaught Error: My set_byindex exception";
class Interceptor : public CefV8Interceptor {
public:
Interceptor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_byname_.yes();
exception = kGetByNameException;
return true;
}
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_byindex_.yes();
exception = kGetByIndexException;
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
got_set_byname_.yes();
exception = kSetByNameException;
return true;
}
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
got_set_byindex_.yes();
exception = kSetByIndexException;
return true;
}
TrackCallback got_get_byname_;
TrackCallback got_get_byindex_;
TrackCallback got_set_byname_;
TrackCallback got_set_byindex_;
IMPLEMENT_REFCOUNTING(Interceptor);
};
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
CefRefPtr<CefV8Exception> exception;
Interceptor* interceptor = new Interceptor;
CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(NULL,
interceptor);
EXPECT_TRUE(object.get());
EXPECT_FALSE(object->SetValue(kName, CefV8Value::CreateInt(1),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_TRUE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byname_);
exception = object->GetException();
EXPECT_TRUE(exception.get());
EXPECT_STREQ(kSetByNameExceptionMsg,
exception->GetMessage().ToString().c_str());
EXPECT_TRUE(object->ClearException());
EXPECT_FALSE(object->HasException());
CefRefPtr<CefV8Value> val1 = object->GetValue(kName);
EXPECT_FALSE(val1.get());
EXPECT_TRUE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byname_);
exception = object->GetException();
EXPECT_TRUE(exception.get());
EXPECT_STREQ(kGetByNameExceptionMsg,
exception->GetMessage().ToString().c_str());
EXPECT_TRUE(object->ClearException());
EXPECT_FALSE(object->HasException());
EXPECT_FALSE(object->SetValue(kIndex, CefV8Value::CreateInt(1)));
EXPECT_TRUE(object->HasException());
EXPECT_TRUE(interceptor->got_set_byindex_);
exception = object->GetException();
EXPECT_TRUE(exception.get());
EXPECT_STREQ(kSetByIndexExceptionMsg,
exception->GetMessage().ToString().c_str());
EXPECT_TRUE(object->ClearException());
EXPECT_FALSE(object->HasException());
CefRefPtr<CefV8Value> val2 = object->GetValue(kIndex);
EXPECT_FALSE(val2.get());
EXPECT_TRUE(object->HasException());
EXPECT_TRUE(interceptor->got_get_byindex_);
exception = object->GetException();
EXPECT_TRUE(exception.get());
EXPECT_STREQ(kGetByIndexExceptionMsg,
exception->GetMessage().ToString().c_str());
// Exit the V8 context.
EXPECT_TRUE(context->Exit());
DestroyTest();
}
void RunObjectInterceptorAndAccessorTest() {
CefRefPtr<CefV8Context> context = GetContext();
static const char* kInterceptorName = "val1";
static const char* kAccessorName = "val2";
static const int kInterceptorValue = 20;
static const int kAccessorValue = 30;
class Interceptor : public CefV8Interceptor {
public:
Interceptor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
EXPECT_FALSE(retval.get());
got_get_byname_.yes();
if (name.ToString() == kInterceptorName) {
retval = CefV8Value::CreateInt(kInterceptorValue);
}
return true;
}
virtual bool Get(int index,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_byindex_.yes();
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
got_set_byname_.yes();
return true;
}
virtual bool Set(int index,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
got_set_byindex_.yes();
return true;
}
TrackCallback got_get_byname_;
TrackCallback got_get_byindex_;
TrackCallback got_set_byname_;
TrackCallback got_set_byindex_;
IMPLEMENT_REFCOUNTING(Interceptor);
};
class Accessor : public CefV8Accessor {
public:
Accessor() {}
virtual bool Get(const CefString& name,
const CefRefPtr<CefV8Value> object,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
got_get_.yes();
retval = CefV8Value::CreateInt(kAccessorValue);
return true;
}
virtual bool Set(const CefString& name,
const CefRefPtr<CefV8Value> object,
const CefRefPtr<CefV8Value> value,
CefString& exception) OVERRIDE {
got_set_.yes();
return true;
}
TrackCallback got_get_;
TrackCallback got_set_;
IMPLEMENT_REFCOUNTING(Accessor);
};
// Enter the V8 context.
EXPECT_TRUE(context->Enter());
Interceptor* interceptor = new Interceptor;
CefRefPtr<CefV8Interceptor> interceptorPtr(interceptor);
Accessor* accessor = new Accessor;
CefRefPtr<CefV8Accessor> accessorPtr(accessor);
CefRefPtr<CefV8Value> object = CefV8Value::CreateObject(
accessor, interceptor);
EXPECT_TRUE(object.get());
// We register both names for accessor.
EXPECT_TRUE(object->SetValue(kAccessorName, V8_ACCESS_CONTROL_DEFAULT,
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(object->SetValue(kInterceptorName, V8_ACCESS_CONTROL_DEFAULT,
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(object->SetValue(kAccessorName,
CefV8Value::CreateInt(kAccessorValue),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(accessor->got_set_);
accessor->got_set_.reset();
EXPECT_TRUE(interceptor->got_set_byname_);
interceptor->got_set_byname_.reset();
EXPECT_TRUE(object->SetValue(kInterceptorName,
CefV8Value::CreateInt(kInterceptorValue),
V8_PROPERTY_ATTRIBUTE_NONE));
EXPECT_FALSE(object->HasException());
EXPECT_TRUE(accessor->got_set_);
accessor->got_set_.reset();
EXPECT_TRUE(interceptor->got_set_byname_);
interceptor->got_set_byname_.reset();
// When interceptor returns nothing, accessor's getter is called.
CefRefPtr<CefV8Value> val1 = object->GetValue(kAccessorName);
EXPECT_TRUE(val1.get());
EXPECT_TRUE(interceptor->got_get_byname_);
interceptor->got_get_byname_.reset();
EXPECT_TRUE(accessor->got_get_);
accessor->got_get_.reset();
EXPECT_EQ(kAccessorValue, val1->GetIntValue());
// When interceptor returns value, accessor's getter is not called.
CefRefPtr<CefV8Value> val2 = object->GetValue(kInterceptorName);
EXPECT_TRUE(val2.get());
EXPECT_TRUE(interceptor->got_get_byname_);
EXPECT_FALSE(accessor->got_get_);
EXPECT_EQ(kInterceptorValue, val2->GetIntValue());
EXPECT_FALSE(interceptor->got_get_byindex_);
EXPECT_FALSE(interceptor->got_set_byindex_);
// Exit the V8 context.
EXPECT_TRUE(context->Exit());
DestroyTest();
}
void RunObjectValueTest() {
CefRefPtr<CefV8Context> context = GetContext();
@ -968,7 +1591,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
CefRefPtr<CefV8Value> object = context->GetGlobal();
EXPECT_TRUE(object.get());
CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(NULL, NULL);
object->SetValue(kObjName, obj1, V8_PROPERTY_ATTRIBUTE_NONE);
obj1->SetValue(kArgName, CefV8Value::CreateInt(0),
@ -1010,7 +1633,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
CefRefPtr<CefV8Value> object = context->GetGlobal();
EXPECT_TRUE(object.get());
CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> obj1 = CefV8Value::CreateObject(NULL, NULL);
object->SetValue(kObjName, obj1, V8_PROPERTY_ATTRIBUTE_NONE);
obj1->SetValue(kArgName, CefV8Value::CreateInt(0),
@ -1242,7 +1865,7 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
CefV8Value::CreateFunction(kFuncName, handler);
EXPECT_TRUE(func.get());
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL);
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL, NULL);
EXPECT_TRUE(obj.get());
handler->object_ = obj;
@ -2230,6 +2853,11 @@ V8_TEST(ObjectAccessor, V8TEST_OBJECT_ACCESSOR);
V8_TEST(ObjectAccessorException, V8TEST_OBJECT_ACCESSOR_EXCEPTION);
V8_TEST(ObjectAccessorFail, V8TEST_OBJECT_ACCESSOR_FAIL);
V8_TEST(ObjectAccessorReadOnly, V8TEST_OBJECT_ACCESSOR_READONLY);
V8_TEST(RunObjectInterceptorTest, V8TEST_OBJECT_INTERCEPTOR);
V8_TEST(RunObjectInterceptorFailTest, V8TEST_OBJECT_INTERCEPTOR_FAIL);
V8_TEST(RunObjectInterceptorExceptionTest, V8TEST_OBJECT_INTERCEPTOR_EXCEPTION);
V8_TEST(RunObjectInterceptorAndAccessorTest,
V8TEST_OBJECT_INTERCEPTOR_AND_ACCESSOR);
V8_TEST(ObjectValue, V8TEST_OBJECT_VALUE);
V8_TEST(ObjectValueReadOnly, V8TEST_OBJECT_VALUE_READONLY);
V8_TEST(ObjectValueEnum, V8TEST_OBJECT_VALUE_ENUM);