diff --git a/include/capi/cef_v8_capi.h b/include/capi/cef_v8_capi.h index 774588be0..e853cc995 100644 --- a/include/capi/cef_v8_capi.h +++ b/include/capi/cef_v8_capi.h @@ -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); diff --git a/include/cef_v8.h b/include/cef_v8.h index e85c3c72a..f48d52037 100644 --- a/include/cef_v8.h +++ b/include/cef_v8.h @@ -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 > 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 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 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; diff --git a/libcef/renderer/v8_impl.cc b/libcef/renderer/v8_impl.cc index 0e4daa952..7cd9f6c51 100644 --- a/libcef/renderer/v8_impl.cc +++ b/libcef/renderer/v8_impl.cc @@ -403,7 +403,7 @@ v8::Handle FunctionCallbackImpl(const v8::Arguments& args) { return v8::ThrowException(v8::Exception::Error(GetV8String(exception))); } else { CefV8ValueImpl* rv = static_cast(retval.get()); - if (rv) + if (rv && rv->IsValid()) return rv->GetHandle(true); } } @@ -437,7 +437,7 @@ v8::Handle AccessorGetterCallbackImpl(v8::Local property, v8::Exception::Error(GetV8String(exception))); } else { CefV8ValueImpl* rv = static_cast(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 context) { - context_state_ = g_v8_tracker.Pointer()->GetContextState(context); -} - - -// CefV8Context - -// static -CefRefPtr CefV8Context::GetCurrentContext() { - CefRefPtr 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::GetEnteredContext() { - CefRefPtr 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 context) + : message_loop_proxy_(base::MessageLoopProxy::current()) { + DCHECK(message_loop_proxy_.get()); + context_state_ = g_v8_tracker.Pointer()->GetContextState(context); +} + + +// CefV8Context + +// static +CefRefPtr CefV8Context::GetCurrentContext() { + CefRefPtr 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::GetEnteredContext() { + CefRefPtr 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 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 CefV8ContextImpl::GetBrowser() { CefRefPtr browser; - CEF_REQUIRE_RT_RETURN(browser); CEF_V8_REQUIRE_VALID_RETURN(browser); WebKit::WebFrame* webframe = GetWebFrame(); @@ -675,7 +708,6 @@ CefRefPtr CefV8ContextImpl::GetBrowser() { CefRefPtr CefV8ContextImpl::GetFrame() { CefRefPtr frame; - CEF_REQUIRE_RT_RETURN(frame); CEF_V8_REQUIRE_VALID_RETURN(frame); WebKit::WebFrame* webframe = GetWebFrame(); @@ -689,7 +721,6 @@ CefRefPtr CefV8ContextImpl::GetFrame() { } CefRefPtr CefV8ContextImpl::GetGlobal() { - CEF_REQUIRE_RT_RETURN(NULL); CEF_V8_REQUIRE_VALID_RETURN(NULL); v8::HandleScope handle_scope; @@ -698,7 +729,6 @@ CefRefPtr 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 that) { - CEF_REQUIRE_RT_RETURN(false); CEF_V8_REQUIRE_VALID_RETURN(false); v8::HandleScope handle_scope; @@ -732,7 +760,7 @@ bool CefV8ContextImpl::IsSame(CefRefPtr that) { v8::Local thisHandle = GetContext(); CefV8ContextImpl* impl = static_cast(that.get()); - if (impl) + if (impl && impl->IsValid()) thatHandle = impl->GetContext(); return (thisHandle == thatHandle); @@ -741,7 +769,6 @@ bool CefV8ContextImpl::IsSame(CefRefPtr that) { bool CefV8ContextImpl::Eval(const CefString& code, CefRefPtr& retval, CefRefPtr& 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::CreateUndefined() { - CEF_REQUIRE_RT_RETURN(NULL); + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); v8::HandleScope handle_scope; return new CefV8ValueImpl(v8::Undefined()); } // static CefRefPtr 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::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::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::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::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::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::CreateDate(const CefTime& date) { // static CefRefPtr 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::CreateString(const CefString& value) { // static CefRefPtr CefV8Value::CreateObject( CefRefPtr accessor) { - CEF_REQUIRE_RT_RETURN(NULL); + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); v8::HandleScope handle_scope; @@ -909,7 +936,7 @@ CefRefPtr CefV8Value::CreateObject( // static CefRefPtr 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::CreateArray(int length) { CefRefPtr CefV8Value::CreateFunction( const CefString& name, CefRefPtr 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 that) { - CEF_REQUIRE_RT_RETURN(false); CEF_V8_REQUIRE_VALID_RETURN(false); v8::HandleScope handle_scope; @@ -1076,14 +1090,13 @@ bool CefV8ValueImpl::IsSame(CefRefPtr that) { v8::Handle thisHandle = GetHandle(false); CefV8ValueImpl* impl = static_cast(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 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 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 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 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 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 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 CefV8ValueImpl::GetValue(const CefString& key) { } CefRefPtr CefV8ValueImpl::GetValue(int index) { - CEF_REQUIRE_RT_RETURN(NULL); CEF_V8_REQUIRE_OBJECT_RETURN(NULL); if (index < 0) { @@ -1278,11 +1274,10 @@ CefRefPtr CefV8ValueImpl::GetValue(int index) { bool CefV8ValueImpl::SetValue(const CefString& key, CefRefPtr value, PropertyAttribute attribute) { - CEF_REQUIRE_RT_RETURN(false); CEF_V8_REQUIRE_OBJECT_RETURN(false); CefV8ValueImpl* impl = static_cast(value.get()); - if (impl) { + if (impl && impl->IsValid()) { v8::HandleScope handle_scope; v8::Local obj = GetHandle(false)->ToObject(); @@ -1298,7 +1293,6 @@ bool CefV8ValueImpl::SetValue(const CefString& key, } bool CefV8ValueImpl::SetValue(int index, CefRefPtr 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 value) { } CefV8ValueImpl* impl = static_cast(value.get()); - if (impl) { + if (impl && impl->IsValid()) { v8::HandleScope handle_scope; v8::Local obj = GetHandle(false)->ToObject(); @@ -1323,7 +1317,6 @@ bool CefV8ValueImpl::SetValue(int index, CefRefPtr 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& 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& keys) { } bool CefV8ValueImpl::SetUserData(CefRefPtr 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 user_data) { } CefRefPtr CefV8ValueImpl::GetUserData() { - CEF_REQUIRE_RT_RETURN(NULL); CEF_V8_REQUIRE_OBJECT_RETURN(NULL); v8::HandleScope handle_scope; @@ -1399,7 +1389,6 @@ CefRefPtr 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 CefV8ValueImpl::GetFunctionHandler() { - CEF_REQUIRE_RT_RETURN(NULL); CEF_V8_REQUIRE_FUNCTION_RETURN(NULL); v8::HandleScope handle_scope; @@ -1474,9 +1459,27 @@ CefRefPtr CefV8ValueImpl::ExecuteFunctionWithContext( CefRefPtr context, CefRefPtr 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 context_local; @@ -1494,15 +1497,14 @@ CefRefPtr CefV8ValueImpl::ExecuteFunctionWithContext( v8::Local func = v8::Local::Cast(obj); v8::Handle 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(object.get()); recv = v8::Handle::Cast(recv_impl->GetHandle(true)); } else { recv = context_local->Global(); } - int argc = arguments.size(); v8::Handle *argv = NULL; if (argc > 0) { argv = new v8::Handle[argc]; @@ -1556,7 +1558,7 @@ bool CefV8ValueImpl::HasCaught(v8::TryCatch& try_catch) { // static CefRefPtr CefV8StackTrace::GetCurrent(int frame_limit) { - CEF_REQUIRE_RT_RETURN(NULL); + CEF_V8_REQUIRE_ISOLATE_RETURN(NULL); v8::HandleScope handle_scope; v8::Handle 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 CefV8StackTraceImpl::GetFrame(int index) { - CEF_REQUIRE_RT_RETURN(NULL); CEF_V8_REQUIRE_VALID_RETURN(NULL); v8::HandleScope handle_scope; v8::Handle 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::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 message, v8::Handle data) { - CEF_REQUIRE_RT_RETURN(void()); - CefRefPtr context = CefV8Context::GetCurrentContext(); CefRefPtr browser = context->GetBrowser(); CefRefPtr frame = context->GetFrame(); diff --git a/libcef/renderer/v8_impl.h b/libcef/renderer/v8_impl.h index 58c577f11..e75ab092b 100644 --- a/libcef/renderer/v8_impl.h +++ b/libcef/renderer/v8_impl.h @@ -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 { 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 + 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 { + 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 context); protected: + friend struct CefV8DeleteOnMessageLoopThread; + + scoped_refptr message_loop_proxy_; scoped_refptr context_state_; };