Allow creation of V8 wrapper objects on any thread with a V8 isolate (issue #451).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@967 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2012-12-30 21:16:59 +00:00
parent e33ea0aff4
commit e574751caa
4 changed files with 213 additions and 169 deletions

View File

@ -105,8 +105,10 @@ CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
const cef_string_t* javascript_code, struct _cef_v8handler_t* handler);
///
// Structure that encapsulates a V8 context handle. The functions of this
// structure may only be called on the render process main thread.
// Structure representing a V8 context handle. Static functions may only be
// called on a render process thread that has entered a V8 isolate (usually the
// render process main thread). Non-static functions may only be called on the
// thread that initially returned the handle.
///
typedef struct _cef_v8context_t {
///
@ -115,8 +117,9 @@ typedef struct _cef_v8context_t {
cef_base_t base;
///
// Returns true (1) if this object is valid. Do not call any other functions
// if this function returns false (0).
// Returns true (1) if the underlying handle is valid and it can be accessed
// on the current thread. Do not call any other functions if this function
// returns false (0).
///
int (CEF_CALLBACK *is_valid)(struct _cef_v8context_t* self);
@ -190,8 +193,8 @@ CEF_EXPORT int cef_v8context_in_context();
///
// Structure that should be implemented to handle V8 function calls. The
// functions of this structure will always be called on the render process main
// thread.
// functions of this structure will only be called on a render process thread
// that the handler was registered on.
///
typedef struct _cef_v8handler_t {
///
@ -216,8 +219,8 @@ typedef struct _cef_v8handler_t {
///
// Structure that should be implemented to handle V8 accessor calls. Accessor
// identifiers are registered by calling cef_v8value_t::set_value_byaccessor().
// The functions of this structure will always be called on the render process
// main thread.
// The functions of this structure will only be called on a render process
// thread that the accessor was registered on.
///
typedef struct _cef_v8accessor_t {
///
@ -250,7 +253,8 @@ typedef struct _cef_v8accessor_t {
///
// Structure representing a V8 exception.
// Structure representing a V8 exception. The functions of this structure may be
// called on any render process thread.
///
typedef struct _cef_v8exception_t {
///
@ -313,8 +317,10 @@ typedef struct _cef_v8exception_t {
///
// Structure representing a V8 value. The functions of this structure may only
// be called on the render process main thread.
// Structure representing a V8 value handle. Static functions may only be called
// on a render process thread that has entered a V8 isolate (usually the render
// process main thread). Non-static functions may only be called on the thread
// that initially returned the handle.
///
typedef struct _cef_v8value_t {
///
@ -323,8 +329,9 @@ typedef struct _cef_v8value_t {
cef_base_t base;
///
// Returns true (1) if this object is valid. Do not call any other functions
// if this function returns false (0).
// Returns true (1) if the underlying handle is valid and it can be accessed
// on the current thread. Do not call any other functions if this function
// returns false (0).
///
int (CEF_CALLBACK *is_valid)(struct _cef_v8value_t* self);
@ -713,8 +720,10 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name,
///
// Structure representing a V8 stack trace. The functions of this structure may
// only be called on the render process main thread.
// Structure representing a V8 stack trace handle. Static functions may only be
// called on a render process thread that has entered a V8 isolate (usually the
// render process main thread). Non-static functions may only be called on the
// thread that initially returned the handle.
///
typedef struct _cef_v8stack_trace_t {
///
@ -723,8 +732,9 @@ typedef struct _cef_v8stack_trace_t {
cef_base_t base;
///
// Returns true (1) if this object is valid. Do not call any other functions
// if this function returns false (0).
// Returns true (1) if the underlying handle is valid and it can be accessed
// on the current thread. Do not call any other functions if this function
// returns false (0).
///
int (CEF_CALLBACK *is_valid)(struct _cef_v8stack_trace_t* self);
@ -749,8 +759,10 @@ CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit);
///
// Structure representing a V8 stack frame. The functions of this structure may
// only be called on the render process main thread.
// Structure representing a V8 stack frame handle. Static functions may only be
// called on a render process thread that has entered a V8 isolate (usually the
// render process main thread). Non-static functions may only be called on the
// thread that initially returned the handle.
///
typedef struct _cef_v8stack_frame_t {
///
@ -759,8 +771,9 @@ typedef struct _cef_v8stack_frame_t {
cef_base_t base;
///
// Returns true (1) if this object is valid. Do not call any other functions
// if this function returns false (0).
// Returns true (1) if the underlying handle is valid and it can be accessed
// on the current thread. Do not call any other functions if this function
// returns false (0).
///
int (CEF_CALLBACK *is_valid)(struct _cef_v8stack_frame_t* self);

View File

@ -116,8 +116,10 @@ bool CefRegisterExtension(const CefString& extension_name,
///
// Class that encapsulates a V8 context handle. The methods of this class may
// only be called on the render process main thread.
// Class representing a V8 context handle. Static methods may only be called
// on a render process thread that has entered a V8 isolate (usually the render
// process main thread). Non-static methods may only be called on the thread
// that initially returned the handle.
///
/*--cef(source=library)--*/
class CefV8Context : public virtual CefBase {
@ -141,8 +143,9 @@ class CefV8Context : public virtual CefBase {
static bool InContext();
///
// Returns true if this object is valid. Do not call any other methods if this
// method returns false.
// Returns true if the underlying handle is valid and it can be accessed on
// the current thread. Do not call any other methods if this method returns
// false.
///
/*--cef()--*/
virtual bool IsValid() =0;
@ -207,7 +210,8 @@ typedef std::vector<CefRefPtr<CefV8Value> > CefV8ValueList;
///
// Interface that should be implemented to handle V8 function calls. The methods
// of this class will always be called on the render process main thread.
// of this class will only be called on a render process thread that the handler
// was registered on.
///
/*--cef(source=client)--*/
class CefV8Handler : public virtual CefBase {
@ -230,7 +234,8 @@ class CefV8Handler : public virtual CefBase {
///
// Interface that should be implemented to handle V8 accessor calls. Accessor
// identifiers are registered by calling CefV8Value::SetValue(). The methods
// of this class will always be called on the render process main thread.
// of this class will only be called on a render process thread that the
// accessor was registered on.
///
/*--cef(source=client)--*/
class CefV8Accessor : public virtual CefBase {
@ -263,7 +268,8 @@ class CefV8Accessor : public virtual CefBase {
};
///
// Class representing a V8 exception.
// Class representing a V8 exception. The methods of this class may be called on
// any render process thread.
///
/*--cef(source=library)--*/
class CefV8Exception : public virtual CefBase {
@ -324,8 +330,10 @@ class CefV8Exception : public virtual CefBase {
};
///
// Class representing a V8 value. The methods of this class may only be called
// on the render process main thread.
// Class representing a V8 value handle. Static methods may only be called on a
// render process thread that has entered a V8 isolate (usually the render
// process main thread). Non-static methods may only be called on the thread
// that initially returned the handle.
///
/*--cef(source=library)--*/
class CefV8Value : public virtual CefBase {
@ -415,8 +423,9 @@ class CefV8Value : public virtual CefBase {
CefRefPtr<CefV8Handler> handler);
///
// Returns true if this object is valid. Do not call any other methods if this
// method returns false.
// Returns true if the underlying handle is valid and it can be accessed on
// the current thread. Do not call any other methods if this method returns
// false.
///
/*--cef()--*/
virtual bool IsValid() =0;
@ -755,8 +764,10 @@ class CefV8Value : public virtual CefBase {
};
///
// Class representing a V8 stack trace. The methods of this class may only be
// called on the render process main thread.
// Class representing a V8 stack trace handle. Static methods may only be called
// on a render process thread that has entered a V8 isolate (usually the render
// process main thread). Non-static methods may only be called on the thread
// that initially returned the handle.
///
/*--cef(source=library)--*/
class CefV8StackTrace : public virtual CefBase {
@ -769,8 +780,9 @@ class CefV8StackTrace : public virtual CefBase {
static CefRefPtr<CefV8StackTrace> GetCurrent(int frame_limit);
///
// Returns true if this object is valid. Do not call any other methods if this
// method returns false.
// Returns true if the underlying handle is valid and it can be accessed on
// the current thread. Do not call any other methods if this method returns
// false.
///
/*--cef()--*/
virtual bool IsValid() =0;
@ -789,15 +801,18 @@ class CefV8StackTrace : public virtual CefBase {
};
///
// Class representing a V8 stack frame. The methods of this class may only be
// called on the render process main thread.
// Class representing a V8 stack frame handle. Static methods may only be called
// on a render process thread that has entered a V8 isolate (usually the render
// process main thread). Non-static methods may only be called on the thread
// that initially returned the handle.
///
/*--cef(source=library)--*/
class CefV8StackFrame : public virtual CefBase {
public:
///
// Returns true if this object is valid. Do not call any other methods if this
// method returns false.
// Returns true if the underlying handle is valid and it can be accessed on
// the current thread. Do not call any other methods if this method returns
// false.
///
/*--cef()--*/
virtual bool IsValid() =0;

View File

@ -403,7 +403,7 @@ v8::Handle<v8::Value> FunctionCallbackImpl(const v8::Arguments& args) {
return v8::ThrowException(v8::Exception::Error(GetV8String(exception)));
} else {
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
if (rv)
if (rv && rv->IsValid())
return rv->GetHandle(true);
}
}
@ -437,7 +437,7 @@ v8::Handle<v8::Value> AccessorGetterCallbackImpl(v8::Local<v8::String> property,
v8::Exception::Error(GetV8String(exception)));
} else {
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
if (rv)
if (rv && rv->IsValid())
return rv->GetHandle(true);
}
}
@ -577,52 +577,36 @@ bool CefRegisterExtension(const CefString& extension_name,
}
// CefV8HandleBase
// Helper macros
CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context) {
context_state_ = g_v8_tracker.Pointer()->GetContextState(context);
}
// CefV8Context
// static
CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext() {
CefRefPtr<CefV8Context> context;
CEF_REQUIRE_RT_RETURN(context);
if (v8::Context::InContext()) {
v8::HandleScope handle_scope;
context = new CefV8ContextImpl(v8::Context::GetCurrent());
#define CEF_V8_HAS_ISOLATE() (!!v8::Isolate::GetCurrent())
#define CEF_V8_REQUIRE_ISOLATE_RETURN(var) \
if (!CEF_V8_HAS_ISOLATE()) { \
NOTREACHED() << "V8 isolate is not valid"; \
return var; \
}
return context;
}
// static
CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext() {
CefRefPtr<CefV8Context> context;
CEF_REQUIRE_RT_RETURN(context);
if (v8::Context::InContext()) {
v8::HandleScope handle_scope;
context = new CefV8ContextImpl(v8::Context::GetEntered());
#define CEF_V8_CURRENTLY_ON_MLT() (handle_->BelongsToCurrentThread())
#define CEF_V8_REQUIRE_MLT_RETURN(var) \
CEF_V8_REQUIRE_ISOLATE_RETURN(var); \
if (!CEF_V8_CURRENTLY_ON_MLT()) { \
NOTREACHED() << "called on incorrect thread"; \
return var; \
}
return context;
}
// static
bool CefV8Context::InContext() {
CEF_REQUIRE_RT_RETURN(false);
return v8::Context::InContext();
}
// CefV8ContextImpl
#define CEF_V8_HANDLE_IS_VALID() (handle_->IsValid())
#define CEF_V8_REQUIRE_VALID_RETURN(ret) \
if (!handle_->IsValid()) { \
CEF_V8_REQUIRE_MLT_RETURN(ret); \
if (!CEF_V8_HANDLE_IS_VALID()) { \
NOTREACHED() << "V8 handle is not valid"; \
return ret; \
}
#define CEF_V8_IS_VALID() \
(CEF_V8_HAS_ISOLATE() && \
CEF_V8_CURRENTLY_ON_MLT() && \
CEF_V8_HANDLE_IS_VALID())
#define CEF_V8_REQUIRE_OBJECT_RETURN(ret) \
CEF_V8_REQUIRE_VALID_RETURN(ret); \
if (!GetHandle(false)->IsObject()) { \
@ -644,6 +628,57 @@ bool CefV8Context::InContext() {
return ret; \
}
// CefV8HandleBase
CefV8HandleBase::~CefV8HandleBase() {
DCHECK(BelongsToCurrentThread());
}
bool CefV8HandleBase::BelongsToCurrentThread() const {
return message_loop_proxy_->BelongsToCurrentThread();
}
CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context)
: message_loop_proxy_(base::MessageLoopProxy::current()) {
DCHECK(message_loop_proxy_.get());
context_state_ = g_v8_tracker.Pointer()->GetContextState(context);
}
// CefV8Context
// static
CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext() {
CefRefPtr<CefV8Context> context;
CEF_V8_REQUIRE_ISOLATE_RETURN(context);
if (v8::Context::InContext()) {
v8::HandleScope handle_scope;
context = new CefV8ContextImpl(v8::Context::GetCurrent());
}
return context;
}
// static
CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext() {
CefRefPtr<CefV8Context> context;
CEF_V8_REQUIRE_ISOLATE_RETURN(context);
if (v8::Context::InContext()) {
v8::HandleScope handle_scope;
context = new CefV8ContextImpl(v8::Context::GetEntered());
}
return context;
}
// static
bool CefV8Context::InContext() {
CEF_V8_REQUIRE_ISOLATE_RETURN(false);
return v8::Context::InContext();
}
// CefV8ContextImpl
CefV8ContextImpl::CefV8ContextImpl(v8::Handle<v8::Context> context)
: handle_(new Handle(context, context))
#ifndef NDEBUG
@ -657,13 +692,11 @@ CefV8ContextImpl::~CefV8ContextImpl() {
}
bool CefV8ContextImpl::IsValid() {
CEF_REQUIRE_RT_RETURN(false);
return handle_->IsValid();
return CEF_V8_IS_VALID();
}
CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser() {
CefRefPtr<CefBrowser> browser;
CEF_REQUIRE_RT_RETURN(browser);
CEF_V8_REQUIRE_VALID_RETURN(browser);
WebKit::WebFrame* webframe = GetWebFrame();
@ -675,7 +708,6 @@ CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser() {
CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
CefRefPtr<CefFrame> frame;
CEF_REQUIRE_RT_RETURN(frame);
CEF_V8_REQUIRE_VALID_RETURN(frame);
WebKit::WebFrame* webframe = GetWebFrame();
@ -689,7 +721,6 @@ CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
}
CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_VALID_RETURN(NULL);
v8::HandleScope handle_scope;
@ -698,7 +729,6 @@ CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal() {
}
bool CefV8ContextImpl::Enter() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
WebCore::V8PerIsolateData::current()->incrementRecursionLevel();
@ -710,7 +740,6 @@ bool CefV8ContextImpl::Enter() {
}
bool CefV8ContextImpl::Exit() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
DLOG_ASSERT(enter_count_ > 0);
@ -723,7 +752,6 @@ bool CefV8ContextImpl::Exit() {
}
bool CefV8ContextImpl::IsSame(CefRefPtr<CefV8Context> that) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
v8::HandleScope handle_scope;
@ -732,7 +760,7 @@ bool CefV8ContextImpl::IsSame(CefRefPtr<CefV8Context> that) {
v8::Local<v8::Context> thisHandle = GetContext();
CefV8ContextImpl* impl = static_cast<CefV8ContextImpl*>(that.get());
if (impl)
if (impl && impl->IsValid())
thatHandle = impl->GetContext();
return (thisHandle == thatHandle);
@ -741,7 +769,6 @@ bool CefV8ContextImpl::IsSame(CefRefPtr<CefV8Context> that) {
bool CefV8ContextImpl::Eval(const CefString& code,
CefRefPtr<CefV8Value>& retval,
CefRefPtr<CefV8Exception>& exception) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
if (code.empty()) {
@ -825,49 +852,49 @@ CefV8ValueImpl::Handle::~Handle() {
// static
CefRefPtr<CefV8Value> CefV8Value::CreateUndefined() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Undefined());
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateNull() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Null());
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateBool(bool value) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Boolean::New(value));
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateInt(int32 value) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Int32::New(value));
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateUInt(uint32 value) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Int32::NewFromUnsigned(value));
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateDouble(double value) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(v8::Number::New(value));
}
// static
CefRefPtr<CefV8Value> CefV8Value::CreateDate(const CefTime& date) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
// Convert from seconds to milliseconds.
return new CefV8ValueImpl(v8::Date::New(date.GetDoubleT() * 1000));
@ -875,7 +902,7 @@ CefRefPtr<CefV8Value> CefV8Value::CreateDate(const CefTime& date) {
// static
CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
return new CefV8ValueImpl(GetV8String(value));
}
@ -883,7 +910,7 @@ CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value) {
// static
CefRefPtr<CefV8Value> CefV8Value::CreateObject(
CefRefPtr<CefV8Accessor> accessor) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
@ -909,7 +936,7 @@ CefRefPtr<CefV8Value> CefV8Value::CreateObject(
// static
CefRefPtr<CefV8Value> CefV8Value::CreateArray(int length) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
@ -936,7 +963,7 @@ CefRefPtr<CefV8Value> CefV8Value::CreateArray(int length) {
CefRefPtr<CefV8Value> CefV8Value::CreateFunction(
const CefString& name,
CefRefPtr<CefV8Handler> handler) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
if (!handler.get()) {
NOTREACHED() << "invalid parameter";
@ -995,79 +1022,66 @@ CefV8ValueImpl::~CefV8ValueImpl() {
bool CefV8ValueImpl::IsValid() {
CEF_REQUIRE_RT_RETURN(false);
return handle_->IsValid();
return CEF_V8_IS_VALID();
}
bool CefV8ValueImpl::IsUndefined() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsUndefined();
}
bool CefV8ValueImpl::IsNull() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsNull();
}
bool CefV8ValueImpl::IsBool() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return (GetHandle(false)->IsBoolean() || GetHandle(false)->IsTrue() ||
GetHandle(false)->IsFalse());
}
bool CefV8ValueImpl::IsInt() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsInt32();
}
bool CefV8ValueImpl::IsUInt() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsUint32();
}
bool CefV8ValueImpl::IsDouble() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsNumber();
}
bool CefV8ValueImpl::IsDate() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsDate();
}
bool CefV8ValueImpl::IsString() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsString();
}
bool CefV8ValueImpl::IsObject() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsObject();
}
bool CefV8ValueImpl::IsArray() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsArray();
}
bool CefV8ValueImpl::IsFunction() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
return GetHandle(false)->IsFunction();
}
bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
v8::HandleScope handle_scope;
@ -1076,14 +1090,13 @@ bool CefV8ValueImpl::IsSame(CefRefPtr<CefV8Value> that) {
v8::Handle<v8::Value> thisHandle = GetHandle(false);
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(that.get());
if (impl)
if (impl && impl->IsValid())
thatHandle = impl->GetHandle(false);
return (thisHandle == thatHandle);
}
bool CefV8ValueImpl::GetBoolValue() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
if (GetHandle(false)->IsTrue()) {
return true;
@ -1097,7 +1110,6 @@ bool CefV8ValueImpl::GetBoolValue() {
}
int32 CefV8ValueImpl::GetIntValue() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_VALID_RETURN(0);
v8::HandleScope handle_scope;
v8::Local<v8::Int32> val = GetHandle(false)->ToInt32();
@ -1105,7 +1117,6 @@ int32 CefV8ValueImpl::GetIntValue() {
}
uint32 CefV8ValueImpl::GetUIntValue() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_VALID_RETURN(0);
v8::HandleScope handle_scope;
v8::Local<v8::Uint32> val = GetHandle(false)->ToUint32();
@ -1113,7 +1124,6 @@ uint32 CefV8ValueImpl::GetUIntValue() {
}
double CefV8ValueImpl::GetDoubleValue() {
CEF_REQUIRE_RT_RETURN(0.);
CEF_V8_REQUIRE_VALID_RETURN(0.);
v8::HandleScope handle_scope;
v8::Local<v8::Number> val = GetHandle(false)->ToNumber();
@ -1121,7 +1131,6 @@ double CefV8ValueImpl::GetDoubleValue() {
}
CefTime CefV8ValueImpl::GetDateValue() {
CEF_REQUIRE_RT_RETURN(CefTime(0.));
CEF_V8_REQUIRE_VALID_RETURN(CefTime(0.));
v8::HandleScope handle_scope;
v8::Local<v8::Number> val = GetHandle(false)->ToNumber();
@ -1131,7 +1140,6 @@ CefTime CefV8ValueImpl::GetDateValue() {
CefString CefV8ValueImpl::GetStringValue() {
CefString rv;
CEF_REQUIRE_RT_RETURN(rv);
CEF_V8_REQUIRE_VALID_RETURN(rv);
v8::HandleScope handle_scope;
GetCefString(GetHandle(false)->ToString(), rv);
@ -1139,7 +1147,6 @@ CefString CefV8ValueImpl::GetStringValue() {
}
bool CefV8ValueImpl::IsUserCreated() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1150,21 +1157,18 @@ bool CefV8ValueImpl::IsUserCreated() {
}
bool CefV8ValueImpl::HasException() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
return (last_exception_.get() != NULL);
}
CefRefPtr<CefV8Exception> CefV8ValueImpl::GetException() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
return last_exception_;
}
bool CefV8ValueImpl::ClearException() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
last_exception_ = NULL;
@ -1172,14 +1176,12 @@ bool CefV8ValueImpl::ClearException() {
}
bool CefV8ValueImpl::WillRethrowExceptions() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
return rethrow_exceptions_;
}
bool CefV8ValueImpl::SetRethrowExceptions(bool rethrow) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
rethrow_exceptions_ = rethrow;
@ -1187,7 +1189,6 @@ bool CefV8ValueImpl::SetRethrowExceptions(bool rethrow) {
}
bool CefV8ValueImpl::HasValue(const CefString& key) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1196,7 +1197,6 @@ bool CefV8ValueImpl::HasValue(const CefString& key) {
}
bool CefV8ValueImpl::HasValue(int index) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
if (index < 0) {
@ -1210,7 +1210,6 @@ bool CefV8ValueImpl::HasValue(int index) {
}
bool CefV8ValueImpl::DeleteValue(const CefString& key) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1223,7 +1222,6 @@ bool CefV8ValueImpl::DeleteValue(const CefString& key) {
}
bool CefV8ValueImpl::DeleteValue(int index) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
if (index < 0) {
@ -1241,7 +1239,6 @@ bool CefV8ValueImpl::DeleteValue(int index) {
}
CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(const CefString& key) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
v8::HandleScope handle_scope;
@ -1256,7 +1253,6 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(const CefString& key) {
}
CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(int index) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
if (index < 0) {
@ -1278,11 +1274,10 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(int index) {
bool CefV8ValueImpl::SetValue(const CefString& key,
CefRefPtr<CefV8Value> value,
PropertyAttribute attribute) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
if (impl) {
if (impl && impl->IsValid()) {
v8::HandleScope handle_scope;
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
@ -1298,7 +1293,6 @@ bool CefV8ValueImpl::SetValue(const CefString& key,
}
bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
if (index < 0) {
@ -1307,7 +1301,7 @@ bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value) {
}
CefV8ValueImpl* impl = static_cast<CefV8ValueImpl*>(value.get());
if (impl) {
if (impl && impl->IsValid()) {
v8::HandleScope handle_scope;
v8::Local<v8::Object> obj = GetHandle(false)->ToObject();
@ -1323,7 +1317,6 @@ bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value) {
bool CefV8ValueImpl::SetValue(const CefString& key, AccessControl settings,
PropertyAttribute attribute) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1352,7 +1345,6 @@ bool CefV8ValueImpl::SetValue(const CefString& key, AccessControl settings,
}
bool CefV8ValueImpl::GetKeys(std::vector<CefString>& keys) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1369,7 +1361,6 @@ bool CefV8ValueImpl::GetKeys(std::vector<CefString>& keys) {
}
bool CefV8ValueImpl::SetUserData(CefRefPtr<CefBase> user_data) {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_OBJECT_RETURN(false);
v8::HandleScope handle_scope;
@ -1385,7 +1376,6 @@ bool CefV8ValueImpl::SetUserData(CefRefPtr<CefBase> user_data) {
}
CefRefPtr<CefBase> CefV8ValueImpl::GetUserData() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_OBJECT_RETURN(NULL);
v8::HandleScope handle_scope;
@ -1399,7 +1389,6 @@ CefRefPtr<CefBase> CefV8ValueImpl::GetUserData() {
}
int CefV8ValueImpl::GetExternallyAllocatedMemory() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_OBJECT_RETURN(0);
v8::HandleScope handle_scope;
@ -1413,7 +1402,6 @@ int CefV8ValueImpl::GetExternallyAllocatedMemory() {
}
int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_OBJECT_RETURN(0);
v8::HandleScope handle_scope;
@ -1427,7 +1415,6 @@ int CefV8ValueImpl::AdjustExternallyAllocatedMemory(int change_in_bytes) {
}
int CefV8ValueImpl::GetArrayLength() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_ARRAY_RETURN(0);
v8::HandleScope handle_scope;
@ -1438,7 +1425,6 @@ int CefV8ValueImpl::GetArrayLength() {
CefString CefV8ValueImpl::GetFunctionName() {
CefString rv;
CEF_REQUIRE_RT_RETURN(rv);
CEF_V8_REQUIRE_FUNCTION_RETURN(rv);
v8::HandleScope handle_scope;
@ -1449,7 +1435,6 @@ CefString CefV8ValueImpl::GetFunctionName() {
}
CefRefPtr<CefV8Handler> CefV8ValueImpl::GetFunctionHandler() {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_FUNCTION_RETURN(NULL);
v8::HandleScope handle_scope;
@ -1474,9 +1459,27 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_FUNCTION_RETURN(NULL);
if (context.get() && !context->IsValid()) {
NOTREACHED() << "invalid V8 context parameter";
return NULL;
}
if (object.get() && (!object->IsValid() || !object->IsObject())) {
NOTREACHED() << "invalid V8 object parameter";
return NULL;
}
int argc = arguments.size();
if (argc > 0) {
for (int i = 0; i < argc; ++i) {
if (!arguments[i].get() || !arguments[i]->IsValid()) {
NOTREACHED() << "invalid V8 arguments parameter";
return NULL;
}
}
}
v8::HandleScope handle_scope;
v8::Local<v8::Context> context_local;
@ -1494,15 +1497,14 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
v8::Handle<v8::Object> recv;
// Default to the global object if no object or a non-object was provided.
if (object.get() && object->IsObject()) {
// Default to the global object if no object was provided.
if (object.get()) {
CefV8ValueImpl* recv_impl = static_cast<CefV8ValueImpl*>(object.get());
recv = v8::Handle<v8::Object>::Cast(recv_impl->GetHandle(true));
} else {
recv = context_local->Global();
}
int argc = arguments.size();
v8::Handle<v8::Value> *argv = NULL;
if (argc > 0) {
argv = new v8::Handle<v8::Value>[argc];
@ -1556,7 +1558,7 @@ bool CefV8ValueImpl::HasCaught(v8::TryCatch& try_catch) {
// static
CefRefPtr<CefV8StackTrace> CefV8StackTrace::GetCurrent(int frame_limit) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_ISOLATE_RETURN(NULL);
v8::HandleScope handle_scope;
v8::Handle<v8::StackTrace> stackTrace =
@ -1578,19 +1580,16 @@ CefV8StackTraceImpl::~CefV8StackTraceImpl() {
}
bool CefV8StackTraceImpl::IsValid() {
CEF_REQUIRE_RT_RETURN(false);
return handle_->IsValid();
return CEF_V8_IS_VALID();
}
int CefV8StackTraceImpl::GetFrameCount() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_VALID_RETURN(0);
v8::HandleScope handle_scope;
return GetHandle()->GetFrameCount();
}
CefRefPtr<CefV8StackFrame> CefV8StackTraceImpl::GetFrame(int index) {
CEF_REQUIRE_RT_RETURN(NULL);
CEF_V8_REQUIRE_VALID_RETURN(NULL);
v8::HandleScope handle_scope;
v8::Handle<v8::StackFrame> stackFrame = GetHandle()->GetFrame(index);
@ -1610,13 +1609,11 @@ CefV8StackFrameImpl::~CefV8StackFrameImpl() {
}
bool CefV8StackFrameImpl::IsValid() {
CEF_REQUIRE_RT_RETURN(false);
return handle_->IsValid();
return CEF_V8_IS_VALID();
}
CefString CefV8StackFrameImpl::GetScriptName() {
CefString rv;
CEF_REQUIRE_RT_RETURN(rv);
CEF_V8_REQUIRE_VALID_RETURN(rv);
v8::HandleScope handle_scope;
GetCefString(v8::Handle<v8::String>::Cast(GetHandle()->GetScriptName()), rv);
@ -1625,7 +1622,6 @@ CefString CefV8StackFrameImpl::GetScriptName() {
CefString CefV8StackFrameImpl::GetScriptNameOrSourceURL() {
CefString rv;
CEF_REQUIRE_RT_RETURN(rv);
CEF_V8_REQUIRE_VALID_RETURN(rv);
v8::HandleScope handle_scope;
GetCefString(
@ -1636,7 +1632,6 @@ CefString CefV8StackFrameImpl::GetScriptNameOrSourceURL() {
CefString CefV8StackFrameImpl::GetFunctionName() {
CefString rv;
CEF_REQUIRE_RT_RETURN(rv);
CEF_V8_REQUIRE_VALID_RETURN(rv);
v8::HandleScope handle_scope;
GetCefString(
@ -1645,28 +1640,24 @@ CefString CefV8StackFrameImpl::GetFunctionName() {
}
int CefV8StackFrameImpl::GetLineNumber() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_VALID_RETURN(0);
v8::HandleScope handle_scope;
return GetHandle()->GetLineNumber();
}
int CefV8StackFrameImpl::GetColumn() {
CEF_REQUIRE_RT_RETURN(0);
CEF_V8_REQUIRE_VALID_RETURN(0);
v8::HandleScope handle_scope;
return GetHandle()->GetColumn();
}
bool CefV8StackFrameImpl::IsEval() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
v8::HandleScope handle_scope;
return GetHandle()->IsEval();
}
bool CefV8StackFrameImpl::IsConstructor() {
CEF_REQUIRE_RT_RETURN(false);
CEF_V8_REQUIRE_VALID_RETURN(false);
v8::HandleScope handle_scope;
return GetHandle()->IsConstructor();
@ -1674,8 +1665,6 @@ bool CefV8StackFrameImpl::IsConstructor() {
void CefV8MessageHandler(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data) {
CEF_REQUIRE_RT_RETURN(void());
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
CefRefPtr<CefBrowser> browser = context->GetBrowser();
CefRefPtr<CefFrame> frame = context->GetFrame();

View File

@ -10,10 +10,12 @@
#include "include/cef_v8.h"
#include "libcef/common/tracker.h"
#include "libcef/renderer/thread_util.h"
#include "v8/include/v8.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop_proxy.h"
class CefTrackNode;
@ -52,25 +54,50 @@ class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
CefTrackManager track_manager_;
};
// Use this template in conjuction with RefCountedThreadSafe to ensure that a
// V8 object is deleted on the correct thread.
struct CefV8DeleteOnMessageLoopThread {
template<typename T>
static void Destruct(const T* x) {
if (x->message_loop_proxy_->BelongsToCurrentThread()) {
delete x;
} else {
if (!x->message_loop_proxy_->DeleteSoon(FROM_HERE, x)) {
#if defined(UNIT_TEST)
// Only logged under unit testing because leaks at shutdown
// are acceptable under normal circumstances.
LOG(ERROR) << "DeleteSoon failed on thread " << thread;
#endif // UNIT_TEST
}
}
}
};
// Base class for V8 Handle types.
class CefV8HandleBase :
public base::RefCountedThreadSafe<CefV8HandleBase,
CefDeleteOnRenderThread> {
CefV8DeleteOnMessageLoopThread> {
public:
virtual ~CefV8HandleBase() {}
virtual ~CefV8HandleBase();
// Returns true if there is no underlying context or if the underlying context
// is valid.
bool IsValid() {
bool IsValid() const {
return (!context_state_.get() || context_state_->IsValid());
}
bool BelongsToCurrentThread() const;
protected:
// |context| is the context that owns this handle. If empty the current
// context will be used.
explicit CefV8HandleBase(v8::Handle<v8::Context> context);
protected:
friend struct CefV8DeleteOnMessageLoopThread;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
scoped_refptr<CefV8ContextState> context_state_;
};