2011-02-21 23:44:06 +01:00
|
|
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
|
2010-10-03 23:04:50 +02:00
|
|
|
// reserved. Use of this source code is governed by a BSD-style license that
|
|
|
|
// can be found in the LICENSE file.
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
#include "browser_impl.h"
|
2010-10-03 23:04:50 +02:00
|
|
|
#include "v8_impl.h"
|
|
|
|
#include "cef_context.h"
|
|
|
|
#include "tracker.h"
|
|
|
|
#include "base/lazy_instance.h"
|
2011-02-15 19:07:24 +01:00
|
|
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
|
2011-02-21 23:44:06 +01:00
|
|
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
2011-02-15 19:07:24 +01:00
|
|
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h"
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
#define CEF_REQUIRE_UI_THREAD(var) \
|
|
|
|
if (!CefThread::CurrentlyOn(CefThread::UI)) { \
|
|
|
|
NOTREACHED(); \
|
|
|
|
return var; \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define CEF_REQUIRE_VALID_CONTEXT(var) \
|
|
|
|
if (!CONTEXT_STATE_VALID()) { \
|
|
|
|
NOTREACHED(); \
|
|
|
|
return var; \
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
// Memory manager.
|
|
|
|
|
|
|
|
base::LazyInstance<CefTrackManager> g_v8_tracker(base::LINKER_INITIALIZED);
|
|
|
|
|
|
|
|
class TrackBase : public CefTrackObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TrackBase(CefBase* base) { base_ = base; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
CefRefPtr<CefBase> base_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class TrackString : public CefTrackObject
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
TrackString(const std::string& str) : string_(str) {}
|
|
|
|
const char* GetString() { return string_.c_str(); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string string_;
|
|
|
|
};
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
void TrackAdd(CefTrackObject* object)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
|
|
|
g_v8_tracker.Pointer()->Add(object);
|
|
|
|
}
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
void TrackDelete(CefTrackObject* object)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
|
|
|
g_v8_tracker.Pointer()->Delete(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Callback for weak persistent reference destruction.
|
2011-02-21 23:44:06 +01:00
|
|
|
void TrackDestructor(v8::Persistent<v8::Value> object, void* parameter)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
|
|
|
if(parameter)
|
|
|
|
TrackDelete(static_cast<CefTrackObject*>(parameter));
|
|
|
|
object.Dispose();
|
|
|
|
object.Clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
// Return the browser associated with the specified WebFrame.
|
|
|
|
CefRefPtr<CefBrowserImpl> FindBrowserForFrame(WebKit::WebFrame *frame)
|
|
|
|
{
|
|
|
|
CefRefPtr<CefBrowserImpl> browser;
|
|
|
|
|
|
|
|
CefContext::BrowserList *list;
|
|
|
|
CefContext::BrowserList::const_iterator i;
|
|
|
|
_Context->Lock();
|
|
|
|
list = _Context->GetBrowserList();
|
|
|
|
i = list->begin();
|
|
|
|
for (; i != list->end(); ++i) {
|
|
|
|
WebKit::WebFrame* thisframe = i->get()->UIT_GetMainWebFrame();
|
|
|
|
if (thisframe == frame) {
|
|
|
|
browser = i->get();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_Context->Unlock();
|
|
|
|
return browser;
|
|
|
|
}
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
// Convert a wide string to a V8 string.
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::Handle<v8::String> GetV8String(const CefString& str)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2010-11-22 18:49:46 +01:00
|
|
|
std::string tmpStr = str;
|
2010-11-15 16:39:56 +01:00
|
|
|
return v8::String::New(tmpStr.c_str(), tmpStr.length());
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
// Convert a V8 string to a UTF8 string.
|
2011-02-21 23:44:06 +01:00
|
|
|
std::string GetString(v8::Handle<v8::String> str)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2010-11-15 16:39:56 +01:00
|
|
|
// Allocate enough space for a worst-case conversion.
|
2010-11-22 18:49:46 +01:00
|
|
|
int len = str->Utf8Length();
|
|
|
|
char* buf = new char[len+1];
|
|
|
|
str->WriteUtf8(buf, len+1);
|
|
|
|
std::string ret(buf, len);
|
2010-10-03 23:04:50 +02:00
|
|
|
delete [] buf;
|
2010-11-22 18:49:46 +01:00
|
|
|
return ret;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
// V8 function callback.
|
|
|
|
v8::Handle<v8::Value> FunctionCallbackImpl(const v8::Arguments& args)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
CefV8Handler* handler =
|
|
|
|
static_cast<CefV8Handler*>(v8::External::Unwrap(args.Data()));
|
|
|
|
|
|
|
|
CefV8ValueList params;
|
|
|
|
for(int i = 0; i < args.Length(); i++)
|
|
|
|
params.push_back(new CefV8ValueImpl(args[i]));
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString func_name =
|
|
|
|
GetString(v8::Handle<v8::String>::Cast(args.Callee()->GetName()));
|
2010-10-03 23:04:50 +02:00
|
|
|
CefRefPtr<CefV8Value> object = new CefV8ValueImpl(args.This());
|
|
|
|
CefRefPtr<CefV8Value> retval;
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString exception;
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::Handle<v8::Value> value = v8::Null();
|
|
|
|
|
|
|
|
if(handler->Execute(func_name, object, params, retval, exception)) {
|
|
|
|
if(!exception.empty())
|
|
|
|
value = v8::ThrowException(GetV8String(exception));
|
|
|
|
else {
|
|
|
|
CefV8ValueImpl* rv = static_cast<CefV8ValueImpl*>(retval.get());
|
|
|
|
if(rv)
|
2011-02-21 23:44:06 +01:00
|
|
|
value = rv->GetHandle();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// V8 extension registration.
|
|
|
|
|
|
|
|
class ExtensionWrapper : public v8::Extension {
|
|
|
|
public:
|
|
|
|
ExtensionWrapper(const char* extension_name,
|
|
|
|
const char* javascript_code,
|
|
|
|
CefV8Handler* handler)
|
|
|
|
: v8::Extension(extension_name, javascript_code), handler_(handler)
|
|
|
|
{
|
|
|
|
// The reference will be released when the application exits.
|
|
|
|
TrackAdd(new TrackBase(handler));
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
|
|
|
|
v8::Handle<v8::String> name)
|
|
|
|
{
|
|
|
|
return v8::FunctionTemplate::New(FunctionCallbackImpl,
|
|
|
|
v8::External::New(handler_));
|
|
|
|
}
|
|
|
|
|
|
|
|
void UIT_RegisterExtension()
|
|
|
|
{
|
|
|
|
WebKit::WebScriptController::registerExtension(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddRef() {}
|
|
|
|
void Release() {}
|
|
|
|
|
|
|
|
static bool ImplementsThreadSafeReferenceCounting() { return true; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
CefV8Handler* handler_;
|
|
|
|
};
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
} // namespace
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
bool CefRegisterExtension(const CefString& extension_name,
|
|
|
|
const CefString& javascript_code,
|
2010-10-03 23:04:50 +02:00
|
|
|
CefRefPtr<CefV8Handler> handler)
|
|
|
|
{
|
2011-01-07 02:06:10 +01:00
|
|
|
// Verify that the context is in a valid state.
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(false);
|
2011-01-07 02:06:10 +01:00
|
|
|
|
|
|
|
if(!handler.get()) {
|
|
|
|
NOTREACHED();
|
2010-10-03 23:04:50 +02:00
|
|
|
return false;
|
2011-01-07 02:06:10 +01:00
|
|
|
}
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
TrackString* name = new TrackString(extension_name);
|
2010-10-03 23:04:50 +02:00
|
|
|
TrackAdd(name);
|
2010-11-22 18:49:46 +01:00
|
|
|
TrackString* code = new TrackString(javascript_code);
|
2011-02-21 23:44:06 +01:00
|
|
|
TrackAdd(code);
|
2010-10-03 23:04:50 +02:00
|
|
|
|
|
|
|
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
|
|
|
|
code->GetString(), handler.get());
|
|
|
|
|
|
|
|
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(wrapper,
|
|
|
|
&ExtensionWrapper::UIT_RegisterExtension));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
// CefV8Context
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext()
|
|
|
|
{
|
|
|
|
CefRefPtr<CefV8Context> context;
|
|
|
|
CEF_REQUIRE_VALID_CONTEXT(context);
|
|
|
|
CEF_REQUIRE_UI_THREAD(context);
|
|
|
|
if (v8::Context::InContext())
|
|
|
|
context = new CefV8ContextImpl( v8::Context::GetCurrent() );
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext()
|
|
|
|
{
|
|
|
|
CefRefPtr<CefV8Context> context;
|
|
|
|
CEF_REQUIRE_VALID_CONTEXT(context);
|
|
|
|
CEF_REQUIRE_UI_THREAD(context);
|
|
|
|
if (v8::Context::InContext())
|
|
|
|
context = new CefV8ContextImpl( v8::Context::GetEntered() );
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CefV8ContextImpl
|
|
|
|
|
|
|
|
CefV8ContextImpl::CefV8ContextImpl(v8::Handle<v8::Context> context)
|
|
|
|
{
|
|
|
|
v8_context_ = new CefV8ContextHandle(context);
|
|
|
|
}
|
|
|
|
|
|
|
|
CefV8ContextImpl::~CefV8ContextImpl()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser()
|
|
|
|
{
|
|
|
|
CefRefPtr<CefBrowser> browser;
|
|
|
|
CEF_REQUIRE_UI_THREAD(browser);
|
|
|
|
|
|
|
|
WebKit::WebFrame* webframe = GetWebFrame();
|
|
|
|
if (webframe)
|
|
|
|
browser = FindBrowserForFrame(webframe->top());
|
|
|
|
|
|
|
|
return browser;
|
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame()
|
|
|
|
{
|
|
|
|
CefRefPtr<CefFrame> frame;
|
|
|
|
CEF_REQUIRE_UI_THREAD(frame);
|
|
|
|
|
|
|
|
WebKit::WebFrame* webframe = GetWebFrame();
|
|
|
|
if (webframe) {
|
|
|
|
CefRefPtr<CefBrowserImpl> browser;
|
|
|
|
browser = FindBrowserForFrame(webframe->top());
|
|
|
|
if (browser.get())
|
|
|
|
frame = browser->UIT_GetCefFrame(webframe);
|
|
|
|
}
|
|
|
|
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefV8Value> CefV8ContextImpl::GetGlobal()
|
|
|
|
{
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Context::Scope context_scope(v8_context_->GetHandle());
|
|
|
|
return new CefV8ValueImpl(v8_context_->GetHandle()->Global());
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::Local<v8::Context> CefV8ContextImpl::GetContext()
|
|
|
|
{
|
|
|
|
return v8::Local<v8::Context>::New(v8_context_->GetHandle());
|
|
|
|
}
|
|
|
|
|
|
|
|
WebKit::WebFrame* CefV8ContextImpl::GetWebFrame()
|
|
|
|
{
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Context::Scope context_scope(v8_context_->GetHandle());
|
|
|
|
WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext();
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CefV8ValueHandle
|
|
|
|
|
|
|
|
// Custom destructor for a v8 value handle which gets called only on the UI
|
|
|
|
// thread.
|
|
|
|
CefV8ValueHandle::~CefV8ValueHandle()
|
|
|
|
{
|
|
|
|
if(tracker_)
|
|
|
|
TrackAdd(tracker_);
|
|
|
|
v8_handle_.MakeWeak(tracker_, TrackDestructor);
|
|
|
|
tracker_ = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
// CefV8Value
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateUndefined()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Undefined());
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateNull()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Null());
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateBool(bool value)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Boolean::New(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateInt(int value)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Int32::New(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateDouble(double value)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Number::New(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2010-11-22 18:49:46 +01:00
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateString(const CefString& value)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(GetV8String(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateObject(CefRefPtr<CefBase> user_data)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
|
|
|
|
// Create the new V8 object.
|
|
|
|
v8::Local<v8::Object> obj = v8::Object::New();
|
|
|
|
|
|
|
|
TrackBase *tracker = NULL;
|
2011-02-21 23:44:06 +01:00
|
|
|
if (user_data.get()) {
|
2010-10-03 23:04:50 +02:00
|
|
|
// Attach the user data to the V8 object.
|
|
|
|
v8::Local<v8::Value> data = v8::External::Wrap(user_data.get());
|
|
|
|
obj->Set(v8::String::New("Cef::UserData"), data);
|
|
|
|
|
|
|
|
// Provide a tracker object that will cause the user data reference to be
|
|
|
|
// released when the V8 object is destroyed.
|
|
|
|
tracker = new TrackBase(user_data);
|
|
|
|
}
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
return new CefV8ValueImpl(obj, tracker);
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateArray()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
return new CefV8ValueImpl(v8::Array::New());
|
|
|
|
}
|
|
|
|
|
|
|
|
// static
|
2010-11-22 18:49:46 +01:00
|
|
|
CefRefPtr<CefV8Value> CefV8Value::CreateFunction(const CefString& name,
|
2011-02-21 23:44:06 +01:00
|
|
|
CefRefPtr<CefV8Handler> handler)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_VALID_CONTEXT(NULL);
|
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
|
|
|
|
// Create a new V8 function template with one internal field.
|
|
|
|
v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New();
|
|
|
|
|
|
|
|
v8::Local<v8::Value> data = v8::External::Wrap(handler.get());
|
|
|
|
|
|
|
|
// Set the function handler callback.
|
|
|
|
tmpl->SetCallHandler(FunctionCallbackImpl, data);
|
|
|
|
|
|
|
|
// Retrieve the function object and set the name.
|
|
|
|
v8::Local<v8::Function> func = tmpl->GetFunction();
|
|
|
|
func->SetName(GetV8String(name));
|
|
|
|
|
|
|
|
// Attach the handler instance to the V8 object.
|
|
|
|
func->Set(v8::String::New("Cef::Handler"), data);
|
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
// Create the CefV8ValueImpl and provide a tracker object that will cause
|
2010-10-03 23:04:50 +02:00
|
|
|
// the handler reference to be released when the V8 object is destroyed.
|
2011-02-21 23:44:06 +01:00
|
|
|
return new CefV8ValueImpl(func, new TrackBase(handler));
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// CefV8ValueImpl
|
|
|
|
|
|
|
|
CefV8ValueImpl::CefV8ValueImpl(v8::Handle<v8::Value> value,
|
|
|
|
CefTrackObject* tracker)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
v8_value_ = new CefV8ValueHandle(value, tracker);
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CefV8ValueImpl::~CefV8ValueImpl()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsUndefined()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsUndefined();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsNull()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsNull();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsBool()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return (GetHandle()->IsBoolean() || GetHandle()->IsTrue()
|
|
|
|
|| GetHandle()->IsFalse());
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsInt()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsInt32();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsDouble()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return (GetHandle()->IsNumber() || GetHandle()->IsDate());
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsString()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsString();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsObject()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsObject();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsArray()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsArray();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsFunction()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
return GetHandle()->IsFunction();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::GetBoolValue()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if (GetHandle()->IsTrue()) {
|
|
|
|
return true;
|
|
|
|
} else if(GetHandle()->IsFalse()) {
|
|
|
|
return false;
|
|
|
|
} else {
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::Local<v8::Boolean> val = GetHandle()->ToBoolean();
|
|
|
|
return val->Value();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int CefV8ValueImpl::GetIntValue()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(0);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::Local<v8::Int32> val = GetHandle()->ToInt32();
|
|
|
|
return val->Value();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
double CefV8ValueImpl::GetDoubleValue()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(0.);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::Local<v8::Number> val = GetHandle()->ToNumber();
|
|
|
|
return val->Value();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString CefV8ValueImpl::GetStringValue()
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString rv;
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(rv);
|
2010-10-03 23:04:50 +02:00
|
|
|
v8::HandleScope handle_scope;
|
2011-02-21 23:44:06 +01:00
|
|
|
rv = GetString(GetHandle()->ToString());
|
2010-10-03 23:04:50 +02:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
bool CefV8ValueImpl::HasValue(const CefString& key)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
2010-10-03 23:04:50 +02:00
|
|
|
if(IsReservedKey(key))
|
|
|
|
return false;
|
2011-02-21 23:44:06 +01:00
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Has(GetV8String(key));
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::HasValue(int index)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Has(index);
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
bool CefV8ValueImpl::DeleteValue(const CefString& key)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
2010-10-03 23:04:50 +02:00
|
|
|
if(IsReservedKey(key))
|
|
|
|
return false;
|
2011-02-21 23:44:06 +01:00
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Delete(GetV8String(key));
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::DeleteValue(int index)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Delete(index);
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(const CefString& key)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
2010-10-03 23:04:50 +02:00
|
|
|
if(IsReservedKey(key))
|
2011-02-21 23:44:06 +01:00
|
|
|
return NULL;
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
2010-10-03 23:04:50 +02:00
|
|
|
return false;
|
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return new CefV8ValueImpl(obj->Get(GetV8String(key)));
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefV8Value> CefV8ValueImpl::GetValue(int index)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return new CefV8ValueImpl(obj->Get(v8::Number::New(index)));
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
bool CefV8ValueImpl::SetValue(const CefString& key,
|
2010-10-03 23:04:50 +02:00
|
|
|
CefRefPtr<CefV8Value> value)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
2010-10-03 23:04:50 +02:00
|
|
|
if(IsReservedKey(key))
|
|
|
|
return false;
|
2011-02-21 23:44:06 +01:00
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
|
|
|
}
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
CefV8ValueImpl *impl = static_cast<CefV8ValueImpl*>(value.get());
|
|
|
|
if(impl) {
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Set(GetV8String(key), impl->GetHandle());
|
|
|
|
} else {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::SetValue(int index, CefRefPtr<CefV8Value> value)
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CefV8ValueImpl *impl = static_cast<CefV8ValueImpl*>(value.get());
|
|
|
|
if(impl) {
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
return obj->Set(v8::Number::New(index), impl->GetHandle());
|
|
|
|
} else {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
bool CefV8ValueImpl::GetKeys(std::vector<CefString>& keys)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
v8::Local<v8::Array> arr_keys = obj->GetPropertyNames();
|
|
|
|
uint32_t len = arr_keys->Length();
|
|
|
|
for(uint32_t i = 0; i < len; ++i) {
|
|
|
|
v8::Local<v8::Value> value = arr_keys->Get(v8::Integer::New(i));
|
|
|
|
CefString str = GetString(value->ToString());
|
|
|
|
if(!IsReservedKey(str))
|
|
|
|
keys.push_back(str);
|
|
|
|
}
|
|
|
|
return true;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefBase> CefV8ValueImpl::GetUserData()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
if(!GetHandle()->IsObject()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return NULL;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
v8::Local<v8::String> key = v8::String::New("Cef::UserData");
|
|
|
|
if(obj->Has(key))
|
|
|
|
return static_cast<CefBase*>(v8::External::Unwrap(obj->Get(key)));
|
|
|
|
return NULL;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
int CefV8ValueImpl::GetArrayLength()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(0);
|
|
|
|
if(!GetHandle()->IsArray()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return 0;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
v8::Local<v8::Array> arr = v8::Local<v8::Array>::Cast(obj);
|
|
|
|
return arr->Length();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString CefV8ValueImpl::GetFunctionName()
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString rv;
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(rv);
|
|
|
|
if(!GetHandle()->IsFunction()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return rv;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(obj);
|
|
|
|
rv = GetString(v8::Handle<v8::String>::Cast(func->GetName()));
|
2010-10-03 23:04:50 +02:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
CefRefPtr<CefV8Handler> CefV8ValueImpl::GetFunctionHandler()
|
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
CEF_REQUIRE_UI_THREAD(NULL);
|
|
|
|
if(!GetHandle()->IsFunction()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return NULL;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::HandleScope handle_scope;
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
v8::Local<v8::String> key = v8::String::New("Cef::Handler");
|
|
|
|
if (obj->Has(key))
|
|
|
|
return static_cast<CefV8Handler*>(v8::External::Unwrap(obj->Get(key)));
|
|
|
|
return NULL;
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::ExecuteFunction(CefRefPtr<CefV8Value> object,
|
|
|
|
const CefV8ValueList& arguments,
|
|
|
|
CefRefPtr<CefV8Value>& retval,
|
2010-11-22 18:49:46 +01:00
|
|
|
CefString& exception)
|
2010-10-03 23:04:50 +02:00
|
|
|
{
|
2011-02-21 23:44:06 +01:00
|
|
|
// An empty context value defaults to the current context.
|
|
|
|
CefRefPtr<CefV8Context> context;
|
|
|
|
return ExecuteFunctionWithContext(context, object, arguments, retval,
|
|
|
|
exception);
|
|
|
|
}
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
bool CefV8ValueImpl::ExecuteFunctionWithContext(
|
|
|
|
CefRefPtr<CefV8Context> context,
|
|
|
|
CefRefPtr<CefV8Value> object,
|
|
|
|
const CefV8ValueList& arguments,
|
|
|
|
CefRefPtr<CefV8Value>& retval,
|
|
|
|
CefString& exception)
|
|
|
|
{
|
|
|
|
CEF_REQUIRE_UI_THREAD(false);
|
|
|
|
if(!GetHandle()->IsFunction()) {
|
|
|
|
NOTREACHED();
|
|
|
|
return false;
|
|
|
|
}
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::HandleScope handle_scope;
|
2010-10-03 23:04:50 +02:00
|
|
|
|
2011-02-21 23:44:06 +01:00
|
|
|
v8::Local<v8::Context> context_local;
|
|
|
|
if (context.get()) {
|
|
|
|
CefV8ContextImpl* context_impl =
|
|
|
|
static_cast<CefV8ContextImpl*>(context.get());
|
|
|
|
context_local = context_impl->GetContext();
|
|
|
|
} else {
|
|
|
|
context_local = v8::Context::GetCurrent();
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|
2011-02-21 23:44:06 +01:00
|
|
|
|
|
|
|
v8::Context::Scope context_scope(context_local);
|
|
|
|
|
|
|
|
v8::Local<v8::Object> obj = GetHandle()->ToObject();
|
|
|
|
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()) {
|
|
|
|
CefV8ValueImpl* recv_impl = static_cast<CefV8ValueImpl*>(object.get());
|
|
|
|
recv = v8::Handle<v8::Object>::Cast(recv_impl->GetHandle());
|
|
|
|
} 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];
|
|
|
|
for (int i = 0; i < argc; ++i)
|
|
|
|
argv[i] = static_cast<CefV8ValueImpl*>(arguments[i].get())->GetHandle();
|
|
|
|
}
|
|
|
|
|
|
|
|
v8::TryCatch try_catch;
|
|
|
|
v8::Local<v8::Value> func_rv = func->Call(recv, argc, argv);
|
|
|
|
if (try_catch.HasCaught())
|
|
|
|
exception = GetString(try_catch.Message()->Get());
|
|
|
|
else
|
|
|
|
retval = new CefV8ValueImpl(func_rv);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool CefV8ValueImpl::IsReservedKey(const CefString& key)
|
|
|
|
{
|
|
|
|
std::string str = key;
|
|
|
|
return (str.find("Cef::") == 0 || str.find("v8::") == 0);
|
2010-10-03 23:04:50 +02:00
|
|
|
}
|