- Allow registration of V8 extensions with no native function handler (issue #433).
- Add a CefV8Context::InContext() method to test if V8 is currently in a context (issue #427). - Verify that a current context exists when creating V8 arrays, functions and objects (issue #427). - Add a v8::HandleScope in GetCurrentContext() and GetEnteredContext() to avoid "Cannot create a handle without a HandleScope" V8 errors (issue #427). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@391 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
3279ee3adf
commit
ead9b4508c
|
@ -2264,6 +2264,12 @@ public:
|
||||||
/*--cef()--*/
|
/*--cef()--*/
|
||||||
static CefRefPtr<CefV8Context> GetEnteredContext();
|
static CefRefPtr<CefV8Context> GetEnteredContext();
|
||||||
|
|
||||||
|
///
|
||||||
|
// Returns true if V8 is currently inside a context.
|
||||||
|
///
|
||||||
|
/*--cef()--*/
|
||||||
|
static bool InContext();
|
||||||
|
|
||||||
///
|
///
|
||||||
// Returns the browser for this context.
|
// Returns the browser for this context.
|
||||||
///
|
///
|
||||||
|
|
|
@ -2081,6 +2081,11 @@ CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context();
|
||||||
///
|
///
|
||||||
CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context();
|
CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context();
|
||||||
|
|
||||||
|
///
|
||||||
|
// Returns true (1) if V8 is currently inside a context.
|
||||||
|
///
|
||||||
|
CEF_EXPORT int cef_v8context_in_context();
|
||||||
|
|
||||||
|
|
||||||
///
|
///
|
||||||
// Structure that should be implemented to handle V8 function calls. The
|
// Structure that should be implemented to handle V8 function calls. The
|
||||||
|
|
|
@ -259,13 +259,18 @@ public:
|
||||||
CefV8Handler* handler)
|
CefV8Handler* handler)
|
||||||
: v8::Extension(extension_name, javascript_code), handler_(handler)
|
: v8::Extension(extension_name, javascript_code), handler_(handler)
|
||||||
{
|
{
|
||||||
|
if (handler) {
|
||||||
// The reference will be released when the application exits.
|
// The reference will be released when the application exits.
|
||||||
TrackAdd(new TrackBase(handler));
|
TrackAdd(new TrackBase(handler));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
|
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
|
||||||
v8::Handle<v8::String> name)
|
v8::Handle<v8::String> name)
|
||||||
{
|
{
|
||||||
|
if (!handler_)
|
||||||
|
return v8::Handle<v8::FunctionTemplate>();
|
||||||
|
|
||||||
return v8::FunctionTemplate::New(FunctionCallbackImpl,
|
return v8::FunctionTemplate::New(FunctionCallbackImpl,
|
||||||
v8::External::Wrap(handler_));
|
v8::External::Wrap(handler_));
|
||||||
}
|
}
|
||||||
|
@ -341,11 +346,6 @@ bool CefRegisterExtension(const CefString& extension_name,
|
||||||
// Verify that the context is in a valid state.
|
// Verify that the context is in a valid state.
|
||||||
CEF_REQUIRE_VALID_CONTEXT(false);
|
CEF_REQUIRE_VALID_CONTEXT(false);
|
||||||
|
|
||||||
if(!handler.get()) {
|
|
||||||
NOTREACHED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
TrackString* name = new TrackString(extension_name);
|
TrackString* name = new TrackString(extension_name);
|
||||||
TrackAdd(name);
|
TrackAdd(name);
|
||||||
TrackString* code = new TrackString(javascript_code);
|
TrackString* code = new TrackString(javascript_code);
|
||||||
|
@ -368,8 +368,10 @@ CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext()
|
||||||
CefRefPtr<CefV8Context> context;
|
CefRefPtr<CefV8Context> context;
|
||||||
CEF_REQUIRE_VALID_CONTEXT(context);
|
CEF_REQUIRE_VALID_CONTEXT(context);
|
||||||
CEF_REQUIRE_UI_THREAD(context);
|
CEF_REQUIRE_UI_THREAD(context);
|
||||||
if (v8::Context::InContext())
|
if (v8::Context::InContext()) {
|
||||||
context = new CefV8ContextImpl( v8::Context::GetCurrent() );
|
v8::HandleScope handle_scope;
|
||||||
|
context = new CefV8ContextImpl(v8::Context::GetCurrent());
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,11 +381,21 @@ CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext()
|
||||||
CefRefPtr<CefV8Context> context;
|
CefRefPtr<CefV8Context> context;
|
||||||
CEF_REQUIRE_VALID_CONTEXT(context);
|
CEF_REQUIRE_VALID_CONTEXT(context);
|
||||||
CEF_REQUIRE_UI_THREAD(context);
|
CEF_REQUIRE_UI_THREAD(context);
|
||||||
if (v8::Context::InContext())
|
if (v8::Context::InContext()) {
|
||||||
context = new CefV8ContextImpl( v8::Context::GetEntered() );
|
v8::HandleScope handle_scope;
|
||||||
|
context = new CefV8ContextImpl(v8::Context::GetEntered());
|
||||||
|
}
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
bool CefV8Context::InContext()
|
||||||
|
{
|
||||||
|
CEF_REQUIRE_VALID_CONTEXT(false);
|
||||||
|
CEF_REQUIRE_UI_THREAD(false);
|
||||||
|
return v8::Context::InContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// CefV8ContextImpl
|
// CefV8ContextImpl
|
||||||
|
|
||||||
|
@ -571,6 +583,12 @@ CefRefPtr<CefV8Value> CefV8Value::CreateObject(
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
|
|
||||||
|
v8::Local<v8::Context> context = v8::Context::GetCurrent();
|
||||||
|
if (context.IsEmpty()) {
|
||||||
|
NOTREACHED() << "not currently in a V8 context";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the new V8 object.
|
// Create the new V8 object.
|
||||||
v8::Local<v8::Object> obj = v8::Object::New();
|
v8::Local<v8::Object> obj = v8::Object::New();
|
||||||
|
|
||||||
|
@ -606,6 +624,13 @@ CefRefPtr<CefV8Value> CefV8Value::CreateArray()
|
||||||
CEF_REQUIRE_UI_THREAD(NULL);
|
CEF_REQUIRE_UI_THREAD(NULL);
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
|
|
||||||
|
v8::Local<v8::Context> context = v8::Context::GetCurrent();
|
||||||
|
if (context.IsEmpty()) {
|
||||||
|
NOTREACHED() << "not currently in a V8 context";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return new CefV8ValueImpl(v8::Array::New());
|
return new CefV8ValueImpl(v8::Array::New());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -623,6 +648,12 @@ CefRefPtr<CefV8Value> CefV8Value::CreateFunction(const CefString& name,
|
||||||
|
|
||||||
v8::HandleScope handle_scope;
|
v8::HandleScope handle_scope;
|
||||||
|
|
||||||
|
v8::Local<v8::Context> context = v8::Context::GetCurrent();
|
||||||
|
if (context.IsEmpty()) {
|
||||||
|
NOTREACHED() << "not currently in a V8 context";
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new V8 function template with one internal field.
|
// Create a new V8 function template with one internal field.
|
||||||
v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
|
v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
|
||||||
|
|
||||||
|
@ -634,7 +665,7 @@ CefRefPtr<CefV8Value> CefV8Value::CreateFunction(const CefString& name,
|
||||||
// Retrieve the function object and set the name.
|
// Retrieve the function object and set the name.
|
||||||
v8::Local<v8::Function> func = tmpl->GetFunction();
|
v8::Local<v8::Function> func = tmpl->GetFunction();
|
||||||
if (func.IsEmpty()) {
|
if (func.IsEmpty()) {
|
||||||
NOTREACHED() << "failed to create function";
|
NOTREACHED() << "failed to create V8 function";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,11 @@ CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CEF_EXPORT int cef_v8context_in_context()
|
||||||
|
{
|
||||||
|
return CefV8Context::InContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,11 @@ CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext()
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefV8Context::InContext()
|
||||||
|
{
|
||||||
|
return cef_v8context_in_context() ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// VIRTUAL METHODS - Body may be edited by hand.
|
// VIRTUAL METHODS - Body may be edited by hand.
|
||||||
|
|
||||||
|
|
|
@ -391,6 +391,108 @@ TEST(V8Test, Extension)
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
class TestNoNativeHandler : public TestHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class TestHandler : public CefV8Handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TestHandler(CefRefPtr<TestNoNativeHandler> test)
|
||||||
|
: test_(test)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Execute(const CefString& name,
|
||||||
|
CefRefPtr<CefV8Value> object,
|
||||||
|
const CefV8ValueList& arguments,
|
||||||
|
CefRefPtr<CefV8Value>& retval,
|
||||||
|
CefString& exception) OVERRIDE
|
||||||
|
{
|
||||||
|
if (name == "result") {
|
||||||
|
if (arguments.size() == 1 && arguments[0]->IsString()) {
|
||||||
|
std::string value = arguments[0]->GetStringValue();
|
||||||
|
if (value == "correct")
|
||||||
|
test_->got_correct_.yes();
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<TestNoNativeHandler> test_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(TestHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
TestNoNativeHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void RunTest() OVERRIDE
|
||||||
|
{
|
||||||
|
std::string testHtml =
|
||||||
|
"<html><body>\n"
|
||||||
|
"<script language=\"JavaScript\">\n"
|
||||||
|
"var result = test_nonative.add(1, 2);\n"
|
||||||
|
"if (result == 3)\n"
|
||||||
|
" window.test.result('correct');\n"
|
||||||
|
"</script>\n"
|
||||||
|
"</body></html>";
|
||||||
|
AddResource("http://tests/run.html", testHtml, "text/html");
|
||||||
|
|
||||||
|
CreateBrowser("http://tests/run.html");
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
int httpStatusCode) OVERRIDE
|
||||||
|
{
|
||||||
|
DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void OnJSBinding(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
CefRefPtr<CefV8Value> object) OVERRIDE
|
||||||
|
{
|
||||||
|
// Create the functions that will be used during the test.
|
||||||
|
CefRefPtr<CefV8Value> obj = CefV8Value::CreateObject(NULL, NULL);
|
||||||
|
CefRefPtr<CefV8Handler> handler = new TestHandler(this);
|
||||||
|
obj->SetValue("result",
|
||||||
|
CefV8Value::CreateFunction("result", handler),
|
||||||
|
V8_PROPERTY_ATTRIBUTE_NONE);
|
||||||
|
object->SetValue("test", obj, V8_PROPERTY_ATTRIBUTE_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackCallback got_correct_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Verify extensions with no native functions
|
||||||
|
TEST(V8Test, ExtensionNoNative)
|
||||||
|
{
|
||||||
|
std::string extensionCode =
|
||||||
|
"var test_nonative;"
|
||||||
|
"if (!test_nonative)"
|
||||||
|
" test_nonative = {};"
|
||||||
|
"(function() {"
|
||||||
|
" test_nonative.add = function(a, b) {"
|
||||||
|
" return a + b;"
|
||||||
|
" };"
|
||||||
|
"})();";
|
||||||
|
CefRegisterExtension("v8/test_nonative", extensionCode, NULL);
|
||||||
|
|
||||||
|
CefRefPtr<TestNoNativeHandler> handler = new TestNoNativeHandler();
|
||||||
|
handler->ExecuteTest();
|
||||||
|
|
||||||
|
EXPECT_TRUE(handler->got_correct_);
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
// Using a delegate so that the code below can remain inline.
|
// Using a delegate so that the code below can remain inline.
|
||||||
class CefV8HandlerDelegate
|
class CefV8HandlerDelegate
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue