- Add a CefV8Context object and CefV8Value::ExecuteFunctionWithContext method to support asynchronous V8 ExecuteFunction callbacks.
- Add a CefFrame::GetBrowser() method.
- Ensure that V8 types are only referenced on the UI thread.
- Accept a empty |object| parameter to CefV8Value::ExecuteFunction.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@188 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-02-21 22:44:06 +00:00
parent 42846e6e31
commit 06a6f0ce7c
20 changed files with 1337 additions and 336 deletions

View File

@ -316,6 +316,8 @@
'libcef_dll/cpptoc/stream_reader_cpptoc.h',
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
'libcef_dll/cpptoc/stream_writer_cpptoc.h',
'libcef_dll/cpptoc/v8context_cpptoc.cc',
'libcef_dll/cpptoc/v8context_cpptoc.h',
'libcef_dll/cpptoc/v8value_cpptoc.cc',
'libcef_dll/cpptoc/v8value_cpptoc.h',
'libcef_dll/cpptoc/web_urlrequest_cpptoc.cc',
@ -423,6 +425,8 @@
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
'libcef_dll/ctocpp/stream_writer_ctocpp.h',
'libcef_dll/ctocpp/v8context_ctocpp.cc',
'libcef_dll/ctocpp/v8context_ctocpp.h',
'libcef_dll/ctocpp/v8value_ctocpp.cc',
'libcef_dll/ctocpp/v8value_ctocpp.h',
'libcef_dll/ctocpp/web_urlrequest_ctocpp.cc',

View File

@ -61,6 +61,7 @@ class CefStreamReader;
class CefStreamWriter;
class CefTask;
class CefURLParts;
class CefV8Context;
class CefV8Handler;
class CefV8Value;
class CefWebURLRequest;
@ -565,10 +566,14 @@ public:
/*--cef()--*/
virtual CefString GetName() =0;
// Return the URL currently loaded in this frame. This method should only be
// Returns the URL currently loaded in this frame. This method should only be
// called on the UI thread.
/*--cef()--*/
virtual CefString GetURL() =0;
// Returns the browser that this frame belongs to.
/*--cef()--*/
virtual CefRefPtr<CefBrowser> GetBrowser() =0;
};
@ -1190,6 +1195,33 @@ public:
};
// Class that encapsulates a V8 context handle.
/*--cef(source=library)--*/
class CefV8Context : public CefBase
{
public:
// Returns the current (top) context object in the V8 context stack.
/*--cef()--*/
static CefRefPtr<CefV8Context> GetCurrentContext();
// Returns the entered (bottom) context object in the V8 context stack.
/*--cef()--*/
static CefRefPtr<CefV8Context> GetEnteredContext();
// Returns the browser for this context.
/*--cef()--*/
virtual CefRefPtr<CefBrowser> GetBrowser() =0;
// Returns the frame for this context.
/*--cef()--*/
virtual CefRefPtr<CefFrame> GetFrame() =0;
// Returns the global object for this context.
/*--cef()--*/
virtual CefRefPtr<CefV8Value> GetGlobal() =0;
};
typedef std::vector<CefRefPtr<CefV8Value> > CefV8ValueList;
// Interface that should be implemented to handle V8 function calls. The methods
@ -1198,8 +1230,10 @@ typedef std::vector<CefRefPtr<CefV8Value> > CefV8ValueList;
class CefV8Handler : public CefBase
{
public:
// Execute with the specified argument list and return value. Return true if
// the method was handled.
// Execute with the specified argument list and return value. Return true if
// the method was handled. To invoke V8 callback functions outside the scope
// of this method you need to keep references to the current V8 context
// (CefV8Context) along with any necessary callback objects.
/*--cef()--*/
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
@ -1215,10 +1249,7 @@ public:
class CefV8Value : public CefBase
{
public:
// Create a new CefV8Value object of the specified type. These methods
// should only be called from within the JavaScript context -- either in a
// CefV8Handler::Execute() callback or a CefHandler::HandleJSBinding()
// callback.
// Create a new CefV8Value object of the specified type.
/*--cef()--*/
static CefRefPtr<CefV8Value> CreateUndefined();
/*--cef()--*/
@ -1327,12 +1358,21 @@ public:
/*--cef()--*/
virtual CefRefPtr<CefV8Handler> GetFunctionHandler() =0;
// Execute the function.
// Execute the function using the current V8 context.
/*--cef()--*/
virtual bool ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
// Execute the function using the specified V8 context.
/*--cef()--*/
virtual bool ExecuteFunctionWithContext(CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) =0;
};

View File

@ -390,11 +390,14 @@ typedef struct _cef_frame_t
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_name)(struct _cef_frame_t* self);
// Return the URL currently loaded in this frame. This function should only be
// called on the UI thread.
// Returns the URL currently loaded in this frame. This function should only
// be called on the UI thread.
// The resulting string must be freed by calling cef_string_userfree_free().
cef_string_userfree_t (CEF_CALLBACK *get_url)(struct _cef_frame_t* self);
// Returns the browser that this frame belongs to.
struct _cef_browser_t* (CEF_CALLBACK *get_browser)(struct _cef_frame_t* self);
} cef_frame_t;
@ -949,6 +952,33 @@ CEF_EXPORT cef_stream_writer_t* cef_stream_writer_create_for_handler(
cef_write_handler_t* handler);
// Structure that encapsulates a V8 context handle.
typedef struct _cef_v8context_t
{
// Base structure.
cef_base_t base;
// Returns the browser for this context.
struct _cef_browser_t* (CEF_CALLBACK *get_browser)(
struct _cef_v8context_t* self);
// Returns the frame for this context.
struct _cef_frame_t* (CEF_CALLBACK *get_frame)(struct _cef_v8context_t* self);
// Returns the global object for this context.
struct _cef_v8value_t* (CEF_CALLBACK *get_global)(
struct _cef_v8context_t* self);
} cef_v8context_t;
// Returns the current (top) context object in the V8 context stack.
CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context();
// Returns the entered (bottom) context object in the V8 context stack.
CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context();
// Structure that should be implemented to handle V8 function calls. The
// functions of this structure will always be called on the UI thread.
typedef struct _cef_v8handler_t
@ -956,8 +986,10 @@ typedef struct _cef_v8handler_t
// Base structure.
cef_base_t base;
// Execute with the specified argument list and return value. Return true (1)
// if the function was handled.
// Execute with the specified argument list and return value. Return true (1)
// if the function was handled. To invoke V8 callback functions outside the
// scope of this function you need to keep references to the current V8
// context (cef_v8context_t) along with any necessary callback objects.
int (CEF_CALLBACK *execute)(struct _cef_v8handler_t* self,
const cef_string_t* name, struct _cef_v8value_t* object,
size_t argumentCount, struct _cef_v8value_t* const* arguments,
@ -1049,19 +1081,22 @@ typedef struct _cef_v8value_t
struct _cef_v8handler_t* (CEF_CALLBACK *get_function_handler)(
struct _cef_v8value_t* self);
// Execute the function.
// Execute the function using the current V8 context.
int (CEF_CALLBACK *execute_function)(struct _cef_v8value_t* self,
struct _cef_v8value_t* object, size_t argumentCount,
struct _cef_v8value_t* const* arguments, struct _cef_v8value_t** retval,
cef_string_t* exception);
// Execute the function using the specified V8 context.
int (CEF_CALLBACK *execute_function_with_context)(struct _cef_v8value_t* self,
struct _cef_v8context_t* context, struct _cef_v8value_t* object,
size_t argumentCount, struct _cef_v8value_t* const* arguments,
struct _cef_v8value_t** retval, cef_string_t* exception);
} cef_v8value_t;
// Create a new cef_v8value_t object of the specified type. These functions
// should only be called from within the JavaScript context -- either in a
// cef_v8handler_t::execute() callback or a cef_handler_t::handle_jsbinding()
// callback.
// Create a new cef_v8value_t object of the specified type.
CEF_EXPORT cef_v8value_t* cef_v8value_create_undefined();
CEF_EXPORT cef_v8value_t* cef_v8value_create_null();
CEF_EXPORT cef_v8value_t* cef_v8value_create_bool(int value);

View File

@ -349,6 +349,7 @@ public:
virtual bool IsFocused();
virtual CefString GetName() { return name_; }
virtual CefString GetURL() { return browser_->GetURL(this); }
virtual CefRefPtr<CefBrowser> GetBrowser() { return browser_.get(); }
private:
CefRefPtr<CefBrowserImpl> browser_;

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
@ -10,18 +10,96 @@
class CefTrackObject;
namespace WebKit {
class WebFrame;
};
// Template for V8 Handle types. This class is used to ensure that V8 objects
// are only released on the UI thread.
template <class v8class>
class CefReleaseV8HandleOnUIThread:
public base::RefCountedThreadSafe<CefReleaseV8HandleOnUIThread<v8class>,
CefThread::DeleteOnUIThread>
{
public:
typedef v8::Handle<v8class> handleType;
typedef v8::Persistent<v8class> persistentType;
typedef CefReleaseV8HandleOnUIThread<v8class> superType;
CefReleaseV8HandleOnUIThread(handleType v)
{
v8_handle_ = persistentType::New(v);
}
virtual ~CefReleaseV8HandleOnUIThread()
{
}
handleType GetHandle()
{
return v8_handle_;
}
persistentType v8_handle_;
};
// Special class for a v8::Context to ensure that it is deleted from the UI
// thread.
class CefV8ContextHandle : public CefReleaseV8HandleOnUIThread<v8::Context>
{
public:
CefV8ContextHandle(handleType context): superType(context)
{
}
// Context handles are disposed rather than makeweak.
~CefV8ContextHandle()
{
v8_handle_.Dispose();
v8_handle_.Clear();
}
};
class CefV8ContextImpl : public CefThreadSafeBase<CefV8Context>
{
public:
CefV8ContextImpl(v8::Handle<v8::Context> context);
virtual ~CefV8ContextImpl();
virtual CefRefPtr<CefBrowser> GetBrowser();
virtual CefRefPtr<CefFrame> GetFrame();
virtual CefRefPtr<CefV8Value> GetGlobal();
v8::Local<v8::Context> GetContext();
WebKit::WebFrame* GetWebFrame();
protected:
scoped_refptr<CefV8ContextHandle> v8_context_;
};
// Special class for a v8::Value to ensure that it is deleted from the UI
// thread.
class CefV8ValueHandle: public CefReleaseV8HandleOnUIThread<v8::Value>
{
public:
CefV8ValueHandle(handleType value, CefTrackObject* tracker)
: superType(value), tracker_(tracker)
{
}
// Destructor implementation is provided in v8_impl.cc.
~CefV8ValueHandle();
private:
// For Object and Function types, we need to hold on to a reference to their
// internal data or function handler objects that are reference counted.
CefTrackObject *tracker_;
};
class CefV8ValueImpl : public CefThreadSafeBase<CefV8Value>
{
public:
CefV8ValueImpl();
CefV8ValueImpl(v8::Handle<v8::Value> value, CefTrackObject* tracker = NULL);
virtual ~CefV8ValueImpl();
bool Attach(v8::Handle<v8::Value> value, CefTrackObject* tracker = NULL);
void Detach();
v8::Handle<v8::Value> GetValue();
bool IsReservedKey(const CefString& key);
virtual bool IsUndefined();
virtual bool IsNull();
virtual bool IsBool();
@ -52,10 +130,23 @@ public:
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception);
virtual bool ExecuteFunctionWithContext(
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception);
inline v8::Handle<v8::Value> GetHandle()
{
DCHECK(v8_value_.get());
return v8_value_->GetHandle();
}
bool IsReservedKey(const CefString& key);
protected:
v8::Persistent<v8::Value> v8_value_;
CefTrackObject* tracker_;
scoped_refptr<CefV8ValueHandle> v8_value_;
};
#endif //_V8_IMPL_H

View File

@ -10,6 +10,7 @@
// for more information.
//
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/request_cpptoc.h"
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
@ -211,6 +212,19 @@ cef_string_userfree_t CEF_CALLBACK frame_get_url(struct _cef_frame_t* self)
return urlStr.DetachToUserFree();
}
cef_browser_t* CEF_CALLBACK frame_get_browser(struct _cef_frame_t* self)
{
DCHECK(self);
if(!self)
return NULL;
CefRefPtr<CefBrowser> browserPtr =
CefFrameCppToC::Get(self)->GetBrowser();
if(browserPtr.get())
return CefBrowserCppToC::Wrap(browserPtr);
return NULL;
}
// CONSTRUCTOR - Do not edit by hand.
@ -237,6 +251,7 @@ CefFrameCppToC::CefFrameCppToC(CefFrame* cls)
struct_.struct_.is_focused = frame_is_focused;
struct_.struct_.get_name = frame_get_name;
struct_.struct_.get_url = frame_get_url;
struct_.struct_.get_browser = frame_get_browser;
}
#ifdef _DEBUG

View File

@ -0,0 +1,97 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
CEF_EXPORT cef_v8context_t* cef_v8context_get_current_context()
{
CefRefPtr<CefV8Context>
contextPtr( CefV8Context::GetCurrentContext() );
if(contextPtr.get())
return CefV8ContextCppToC::Wrap(contextPtr);
return NULL;
}
CEF_EXPORT cef_v8context_t* cef_v8context_get_entered_context()
{
CefRefPtr<CefV8Context>
contextPtr( CefV8Context::GetEnteredContext() );
if(contextPtr.get())
return CefV8ContextCppToC::Wrap(contextPtr);
return NULL;
}
// MEMBER FUNCTIONS - Body may be edited by hand.
cef_browser_t* CEF_CALLBACK v8context_get_browser(struct _cef_v8context_t* self)
{
DCHECK(self);
if(!self)
return NULL;
CefRefPtr<CefV8Context> contextPtr = CefV8ContextCppToC::Get(self);
CefRefPtr<CefBrowser> browserPtr = contextPtr->GetBrowser();
if(browserPtr.get())
return CefBrowserCppToC::Wrap(browserPtr);
return NULL;
}
cef_frame_t* CEF_CALLBACK v8context_get_frame(struct _cef_v8context_t* self)
{
DCHECK(self);
if(!self)
return NULL;
CefRefPtr<CefV8Context> contextPtr = CefV8ContextCppToC::Get(self);
CefRefPtr<CefFrame> framePtr = contextPtr->GetFrame();
if(framePtr.get())
return CefFrameCppToC::Wrap(framePtr);
return NULL;
}
struct _cef_v8value_t* CEF_CALLBACK v8context_get_global(
struct _cef_v8context_t* self)
{
DCHECK(self);
if(!self)
return NULL;
CefRefPtr<CefV8Context> contextPtr = CefV8ContextCppToC::Get(self);
CefRefPtr<CefV8Value> globalPtr = contextPtr->GetGlobal();
if(globalPtr.get())
return CefV8ValueCppToC::Wrap(globalPtr);
return NULL;
}
// CONSTRUCTOR - Do not edit by hand.
CefV8ContextCppToC::CefV8ContextCppToC(CefV8Context* cls)
: CefCppToC<CefV8ContextCppToC, CefV8Context, cef_v8context_t>(cls)
{
struct_.struct_.get_browser = v8context_get_browser;
struct_.struct_.get_frame = v8context_get_frame;
struct_.struct_.get_global = v8context_get_global;
}
#ifdef _DEBUG
template<> long CefCppToC<CefV8ContextCppToC, CefV8Context,
cef_v8context_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,34 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _V8CONTEXT_CPPTOC_H
#define _V8CONTEXT_CPPTOC_H
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/cpptoc/cpptoc.h"
// Wrap a C++ class with a C structure.
// This class may be instantiated and accessed DLL-side only.
class CefV8ContextCppToC
: public CefCppToC<CefV8ContextCppToC, CefV8Context, cef_v8context_t>
{
public:
CefV8ContextCppToC(CefV8Context* cls);
virtual ~CefV8ContextCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // _V8CONTEXT_CPPTOC_H

View File

@ -10,6 +10,7 @@
// for more information.
//
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
#include "libcef_dll/ctocpp/base_ctocpp.h"
#include "libcef_dll/ctocpp/v8handler_ctocpp.h"
@ -374,11 +375,12 @@ int CEF_CALLBACK v8value_execute_function(struct _cef_v8value_t* self,
cef_string_t* exception)
{
DCHECK(self);
DCHECK(object);
if(!self || !object)
if(!self)
return 0;
CefRefPtr<CefV8Value> objectPtr = CefV8ValueCppToC::Unwrap(object);
CefRefPtr<CefV8Value> objectPtr;
if(object)
objectPtr = CefV8ValueCppToC::Unwrap(object);
CefV8ValueList argsList;
for(size_t i = 0; i < argumentCount; i++) {
argsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i]));
@ -394,6 +396,37 @@ int CEF_CALLBACK v8value_execute_function(struct _cef_v8value_t* self,
return rv;
}
int CEF_CALLBACK v8value_execute_function_with_context(
struct _cef_v8value_t* self, cef_v8context_t* context,
struct _cef_v8value_t* object, size_t argumentCount,
struct _cef_v8value_t* const* arguments, struct _cef_v8value_t** retval,
cef_string_t* exception)
{
DCHECK(self);
if(!self)
return 0;
CefRefPtr<CefV8Context> contextPtr;
if(context)
contextPtr = CefV8ContextCppToC::Unwrap(context);
CefRefPtr<CefV8Value> objectPtr;
if(object)
objectPtr = CefV8ValueCppToC::Unwrap(object);
CefV8ValueList argsList;
for(size_t i = 0; i < argumentCount; i++) {
argsList.push_back(CefV8ValueCppToC::Unwrap(arguments[i]));
}
CefRefPtr<CefV8Value> retvalPtr;
CefString exceptionStr(exception);
bool rv = CefV8ValueCppToC::Get(self)->ExecuteFunctionWithContext(
contextPtr, objectPtr, argsList, retvalPtr, exceptionStr);
if(retvalPtr.get() && retval)
*retval = CefV8ValueCppToC::Wrap(retvalPtr);
return rv;
}
// CONSTRUCTOR - Do not edit by hand.
@ -427,6 +460,8 @@ CefV8ValueCppToC::CefV8ValueCppToC(CefV8Value* cls)
struct_.struct_.get_function_name = v8value_get_function_name;
struct_.struct_.get_function_handler = v8value_get_function_handler;
struct_.struct_.execute_function = v8value_execute_function;
struct_.struct_.execute_function_with_context =
v8value_execute_function_with_context;
}
#ifdef _DEBUG

View File

@ -10,6 +10,7 @@
// tools directory for more information.
//
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/request_ctocpp.h"
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
@ -193,6 +194,19 @@ CefString CefFrameCToCpp::GetURL()
return str;
}
CefRefPtr<CefBrowser> CefFrameCToCpp::GetBrowser()
{
CefRefPtr<CefBrowser> browser;
if(CEF_MEMBER_MISSING(struct_, get_browser))
return browser;
cef_browser_t* browserStruct = struct_->get_browser(struct_);
if(browserStruct)
return CefBrowserCToCpp::Wrap(browserStruct);
return browser;
}
#ifdef _DEBUG
template<> long CefCToCpp<CefFrameCToCpp, CefFrame, cef_frame_t>::DebugObjCt =

View File

@ -53,6 +53,7 @@ public:
virtual bool IsFocused();
virtual CefString GetName();
virtual CefString GetURL();
virtual CefRefPtr<CefBrowser> GetBrowser();
};
#endif // USING_CEF_SHARED

View File

@ -0,0 +1,81 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// A portion of this file was generated by the CEF translator tool. When
// making changes by hand only do so within the body of existing static and
// virtual method implementations. See the translator.README.txt file in the
// tools directory for more information.
//
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
// STATIC METHODS - Body may be edited by hand.
CefRefPtr<CefV8Context> CefV8Context::GetCurrentContext()
{
cef_v8context_t* impl = cef_v8context_get_current_context();
if(impl)
return CefV8ContextCToCpp::Wrap(impl);
return NULL;
}
CefRefPtr<CefV8Context> CefV8Context::GetEnteredContext()
{
cef_v8context_t* impl = cef_v8context_get_entered_context();
if(impl)
return CefV8ContextCToCpp::Wrap(impl);
return NULL;
}
// VIRTUAL METHODS - Body may be edited by hand.
CefRefPtr<CefBrowser> CefV8ContextCToCpp::GetBrowser()
{
if(CEF_MEMBER_MISSING(struct_, get_browser))
return NULL;
cef_browser_t* browserStruct = struct_->get_browser(struct_);
if(browserStruct)
return CefBrowserCToCpp::Wrap(browserStruct);
return NULL;
}
CefRefPtr<CefFrame> CefV8ContextCToCpp::GetFrame()
{
if(CEF_MEMBER_MISSING(struct_, get_frame))
return NULL;
cef_frame_t* frameStruct = struct_->get_frame(struct_);
if(frameStruct)
return CefFrameCToCpp::Wrap(frameStruct);
return NULL;
}
CefRefPtr<CefV8Value> CefV8ContextCToCpp::GetGlobal()
{
if(CEF_MEMBER_MISSING(struct_, get_global))
return NULL;
cef_v8value_t* v8valueStruct = struct_->get_global(struct_);
if(v8valueStruct)
return CefV8ValueCToCpp::Wrap(v8valueStruct);
return NULL;
}
#ifdef _DEBUG
template<> long CefCToCpp<CefV8ContextCToCpp, CefV8Context,
cef_v8context_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,41 @@
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// -------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef _V8CONTEXT_CTOCPP_H
#define _V8CONTEXT_CTOCPP_H
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef.h"
#include "include/cef_capi.h"
#include "libcef_dll/ctocpp/ctocpp.h"
// Wrap a C structure with a C++ class.
// This class may be instantiated and accessed wrapper-side only.
class CefV8ContextCToCpp
: public CefCToCpp<CefV8ContextCToCpp, CefV8Context, cef_v8context_t>
{
public:
CefV8ContextCToCpp(cef_v8context_t* str)
: CefCToCpp<CefV8ContextCToCpp, CefV8Context, cef_v8context_t>(str) {}
virtual ~CefV8ContextCToCpp() {}
// CefV8Context methods
virtual CefRefPtr<CefBrowser> GetBrowser();
virtual CefRefPtr<CefFrame> GetFrame();
virtual CefRefPtr<CefV8Value> GetGlobal();
};
#endif // USING_CEF_SHARED
#endif // _V8CONTEXT_CTOCPP_H

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/base_cpptoc.h"
#include "libcef_dll/cpptoc/v8handler_cpptoc.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
#include "libcef_dll/transfer_util.h"
@ -344,7 +345,7 @@ bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
CefString& exception)
{
if(CEF_MEMBER_MISSING(struct_, execute_function))
return RV_CONTINUE;
return false;
cef_v8value_t** argsStructPtr = NULL;
int argsSize = arguments.size();
@ -356,7 +357,8 @@ bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
cef_v8value_t* retvalStruct = NULL;
int rv = struct_->execute_function(struct_, CefV8ValueCToCpp::Unwrap(object),
int rv = struct_->execute_function(struct_,
object.get() ? CefV8ValueCToCpp::Unwrap(object): NULL,
argsSize, argsStructPtr, &retvalStruct, exception.GetWritableStruct());
if(retvalStruct)
retval = CefV8ValueCToCpp::Wrap(retvalStruct);
@ -367,6 +369,38 @@ bool CefV8ValueCToCpp::ExecuteFunction(CefRefPtr<CefV8Value> object,
return rv?true:false;
}
bool CefV8ValueCToCpp::ExecuteFunctionWithContext(
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,
CefString& exception)
{
if(CEF_MEMBER_MISSING(struct_, execute_function_with_context))
return false;
cef_v8value_t** argsStructPtr = NULL;
int argsSize = arguments.size();
if(argsSize > 0) {
argsStructPtr = new cef_v8value_t*[argsSize];
for(int i = 0; i < argsSize; ++i)
argsStructPtr[i] = CefV8ValueCToCpp::Unwrap(arguments[i]);
}
cef_v8value_t* retvalStruct = NULL;
int rv = struct_->execute_function_with_context(struct_,
context.get() ? CefV8ContextCToCpp::Unwrap(context): NULL,
object.get() ? CefV8ValueCToCpp::Unwrap(object): NULL,
argsSize, argsStructPtr, &retvalStruct, exception.GetWritableStruct());
if(retvalStruct)
retval = CefV8ValueCToCpp::Wrap(retvalStruct);
if(argsStructPtr)
delete [] argsStructPtr;
return rv?true:false;
}
#ifdef _DEBUG
template<> long CefCToCpp<CefV8ValueCToCpp, CefV8Value,

View File

@ -60,6 +60,9 @@ public:
virtual bool ExecuteFunction(CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments, CefRefPtr<CefV8Value>& retval,
CefString& exception);
virtual bool ExecuteFunctionWithContext(CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> object, const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval, CefString& exception);
};
#endif // USING_CEF_SHARED

View File

@ -22,6 +22,7 @@
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/web_urlrequest_ctocpp.h"
#include "libcef_dll/ctocpp/xml_reader_ctocpp.h"
#include "libcef_dll/ctocpp/zip_reader_ctocpp.h"
@ -52,6 +53,7 @@ void CefShutdown()
DCHECK(CefPostDataElementCToCpp::DebugObjCt == 0);
DCHECK(CefStreamReaderCToCpp::DebugObjCt == 0);
DCHECK(CefStreamWriterCToCpp::DebugObjCt == 0);
DCHECK(CefV8ContextCToCpp::DebugObjCt == 0);
DCHECK(CefV8ValueCToCpp::DebugObjCt == 0);
DCHECK(CefWebURLRequestCToCpp::DebugObjCt == 0);
DCHECK(CefXmlReaderCToCpp::DebugObjCt == 0);

View File

@ -9,6 +9,17 @@
#include "base/synchronization/waitable_event.h"
#include "testing/gtest/include/gtest/gtest.h"
class TrackCallback
{
public:
TrackCallback(): gotit_(false) {}
void yes() { gotit_ = true; }
bool isSet() { return gotit_; }
operator bool() const { return gotit_; }
protected:
bool gotit_;
};
// Base implementation of CefHandler for unit tests.
class TestHandler : public CefThreadSafeBase<CefHandler>
{

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file.
#include "include/cef.h"
#include "include/cef_runnable.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "test_handler.h"
@ -352,3 +353,358 @@ TEST(V8Test, Extension)
ASSERT_TRUE(g_V8TestV8HandlerExecuteCalled);
ASSERT_TRUE(g_V8TestV8HandlerExecute2Called);
}
// Using a delegate so that the code below can remain inline.
class CefV8HandlerDelegate
{
public:
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) = 0;
};
// Verify context works to allow async v8 callbacks
TEST(V8Test, Context)
{
class DelegatingV8Handler : public CefThreadSafeBase<CefV8Handler>
{
public:
DelegatingV8Handler(CefV8HandlerDelegate *delegate):
delegate_(delegate) { }
~DelegatingV8Handler()
{
}
bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception)
{
return delegate_->Execute(name, object, arguments, retval, exception);
}
private:
CefV8HandlerDelegate *delegate_;
};
class TestContextHandler: public TestHandler, public CefV8HandlerDelegate
{
public:
TestContextHandler() {}
virtual void RunTest()
{
// Test Flow:
// load main.html.
// 1. main.html calls hello("main", callIFrame) in the execute handler.
// The excute handler checks that "main" was called and saves
// the callIFrame function, context, and receiver object.
// 2. iframe.html calls hello("iframe") in the execute handler.
// The execute handler checks that "iframe" was called. if both main
// and iframe were called, it calls CallIFrame()
// 3. CallIFrame calls "callIFrame" in main.html
// 4. which calls iframe.html "calledFromMain()".
// 5. which calls "fromIFrame()" in execute handler.
// The execute handler checks that the entered and current urls are
// what we expect: "main.html" and "iframe.html", respectively
// 6. It then posts a task to call AsyncTestContext
// you can validate the entered and current context are still the
// same here, but it is not checked by this test case.
// 7. AsyncTestContext tests to make sure that no context is set at
// this point and loads "begin.html"
// 8. begin.html calls "begin(func1, func2)" in the execute handler
// The execute handler posts a tasks to call both of those functions
// when no context is defined. Both should work with the specified
// context. AsyncTestException should run first, followed by
// AsyncTestNavigate() which calls the func2 to do a document.location
// based loading of "end.html".
// 9. end.html calls "end()" in the execute handler.
// which concludes the test.
std::stringstream mainHtml;
mainHtml <<
"<html><body>"
"<h1>Hello From Main Frame</h1>"
"<script language=\"JavaScript\">"
"hello(\"main\", callIFrame);"
"function callIFrame() {"
" var iframe = document.getElementById('iframe');"
" iframe.contentWindow.calledFromMain();"
"}"
"</script>"
"<iframe id=\"iframe\" src=\"http://tests/iframe.html\""
" width=\"300\" height=\"300\">"
"</iframe>"
"</body></html>";
AddResource("http://tests/main.html", mainHtml.str(), "text/html");
std::stringstream iframeHtml;
iframeHtml <<
"<html><body>"
"<h1>Hello From IFRAME</h1>"
"<script language=\"JavaScript\">"
"hello(\"iframe\");"
"function calledFromMain() { fromIFrame(); }"
"</script>"
"</body></html>";
AddResource("http://tests/iframe.html", iframeHtml.str(), "text/html");
std::stringstream beginHtml;
beginHtml <<
"<html><body>"
"<h1>V8 Context Test</h1>"
"<script language=\"JavaScript\">"
"function TestException() { throw('My Exception'); }"
"function TestNavigate(a) { document.location = a; }"
"begin(TestException, TestNavigate);"
"</script>"
"</body></html>";
AddResource("http://tests/begin.html", beginHtml.str(), "text/html");
std::stringstream endHtml;
endHtml <<
"<html><body>"
"<h1>Navigation Succeeded!</h1>"
"<script language=\"JavaScript\">"
"end();"
"</script>"
"</body></html>";
AddResource("http://tests/end.html", endHtml.str(), "text/html");
CreateBrowser("http://tests/main.html");
}
virtual RetVal HandleLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
bool isMainContent,
int httpStatusCode)
{
return RV_CONTINUE;
}
virtual RetVal HandleJSBinding(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Value> object)
{
CefRefPtr<CefV8Context> cc = CefV8Context::GetCurrentContext();
CefRefPtr<CefBrowser> currentBrowser = cc->GetBrowser();
CefRefPtr<CefFrame> currentFrame = cc->GetFrame();
CefString currentURL = currentFrame->GetURL();
CefRefPtr<CefV8Context> ec = CefV8Context::GetEnteredContext();
CefRefPtr<CefBrowser> enteredBrowser = ec->GetBrowser();
CefRefPtr<CefFrame> enteredFrame = ec->GetFrame();
CefString enteredURL = enteredFrame->GetURL();
CefRefPtr<CefV8Handler> funcHandler(new DelegatingV8Handler(this));
CefRefPtr<CefV8Value> helloFunc =
CefV8Value::CreateFunction("hello", funcHandler);
object->SetValue("hello", helloFunc);
CefRefPtr<CefV8Value> fromIFrameFunc =
CefV8Value::CreateFunction("fromIFrame", funcHandler);
object->SetValue("fromIFrame", fromIFrameFunc);
CefRefPtr<CefV8Value> goFunc =
CefV8Value::CreateFunction("begin", funcHandler);
object->SetValue("begin", goFunc);
CefRefPtr<CefV8Value> doneFunc =
CefV8Value::CreateFunction("end", funcHandler);
object->SetValue("end", doneFunc);
return RV_HANDLED;
}
void CallIFrame()
{
CefV8ValueList args;
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Value> empty;
ASSERT_TRUE(funcIFrame_->ExecuteFunctionWithContext(
contextIFrame_, empty, args, rv, exception));
}
void AsyncTestContext(CefRefPtr<CefV8Context> ec,
CefRefPtr<CefV8Context> cc)
{
// we should not be in a context in this call.
CefRefPtr<CefV8Context> noContext = CefV8Context::GetCurrentContext();
if (!noContext.get())
got_no_context_.yes();
CefRefPtr<CefBrowser> enteredBrowser = ec->GetBrowser();
CefRefPtr<CefFrame> enteredFrame = ec->GetFrame();
CefString enteredURL = enteredFrame->GetURL();
CefString enteredName = enteredFrame->GetName();
CefRefPtr<CefFrame> enteredMainFrame = enteredBrowser->GetMainFrame();
CefString enteredMainURL = enteredMainFrame->GetURL();
CefString enteredMainName = enteredMainFrame->GetName();
CefRefPtr<CefBrowser> currentBrowser = cc->GetBrowser();
CefRefPtr<CefFrame> currentFrame = cc->GetFrame();
CefString currentURL = currentFrame->GetURL();
CefString currentName = currentFrame->GetName();
CefRefPtr<CefFrame> currentMainFrame = currentBrowser->GetMainFrame();
CefString currentMainURL = currentMainFrame->GetURL();
CefString currentMainName = currentMainFrame->GetName();
CefRefPtr<CefBrowser> copyFromMainFrame =
currentMainFrame->GetBrowser();
currentMainFrame->LoadURL("http://tests/begin.html");
}
void AsyncTestException(
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> func)
{
CefV8ValueList args;
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Value> empty;
ASSERT_TRUE(func->ExecuteFunctionWithContext(
context, empty, args, rv, exception));
if(exception == "Uncaught My Exception")
got_exception_.yes();
}
void AsyncTestNavigation(
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Value> func)
{
CefV8ValueList args;
args.push_back(CefV8Value::CreateString("http://tests/end.html"));
CefRefPtr<CefV8Value> rv;
CefString exception;
CefRefPtr<CefV8Value> global = context->GetGlobal();
ASSERT_TRUE(func->ExecuteFunctionWithContext(
context, global, args, rv, exception));
if(exception.empty())
got_navigation_.yes();
}
bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception)
{
CefRefPtr<CefV8Context> cc = CefV8Context::GetCurrentContext();
CefRefPtr<CefV8Context> ec = CefV8Context::GetEnteredContext();
CefRefPtr<CefBrowser> enteredBrowser = ec->GetBrowser();
CefRefPtr<CefFrame> enteredFrame = ec->GetFrame();
CefString enteredURL = enteredFrame->GetURL();
CefString enteredName = enteredFrame->GetName();
CefRefPtr<CefFrame> enteredMainFrame = enteredBrowser->GetMainFrame();
CefString enteredMainURL = enteredMainFrame->GetURL();
CefString enteredMainName = enteredMainFrame->GetName();
CefRefPtr<CefBrowser> currentBrowser = cc->GetBrowser();
CefRefPtr<CefFrame> currentFrame = cc->GetFrame();
CefString currentURL = currentFrame->GetURL();
CefString currentName = currentFrame->GetName();
CefRefPtr<CefFrame> currentMainFrame = currentBrowser->GetMainFrame();
CefString currentMainURL = currentMainFrame->GetURL();
CefString currentMainName = currentMainFrame->GetName();
if (name == "hello") {
if(arguments.size() == 2 && arguments[0]->IsString() &&
arguments[1]->IsFunction()) {
CefString msg = arguments[0]->GetStringValue();
if(msg == "main") {
got_hello_main_.yes();
contextIFrame_ = cc;
funcIFrame_ = arguments[1];
}
} else if(arguments.size() == 1 && arguments[0]->IsString()) {
CefString msg = arguments[0]->GetStringValue();
if(msg == "iframe")
got_hello_iframe_.yes();
}
else
return false;
if(got_hello_main_ && got_hello_iframe_ && funcIFrame_->IsFunction())
{
// NB: At this point, enteredURL == http://tests/iframe.html which is
// expected since the iframe made the call on its own. The unexpected
// behavior is that in the call to fromIFrame (below) the enteredURL
// == http://tests/main.html even though the iframe.html context was
// entered first.
// -- Perhaps WebKit does something other than look at the bottom
// of stack for the entered context.
if(enteredURL == "http://tests/iframe.html")
got_iframe_as_entered_url_.yes();
CallIFrame();
}
return true;
} else if(name == "fromIFrame") {
if(enteredURL == "http://tests/main.html")
got_correct_entered_url_.yes();
if(currentURL == "http://tests/iframe.html")
got_correct_current_url_.yes();
CefPostTask(TID_UI, NewCefRunnableMethod(this,
&TestContextHandler::AsyncTestContext, ec, cc));
return true;
} else if(name == "begin") {
if(arguments.size() == 2 && arguments[0]->IsFunction() &&
arguments[1]->IsFunction()) {
CefRefPtr<CefV8Value> funcException = arguments[0];
CefRefPtr<CefV8Value> funcNavigate = arguments[1];
CefPostTask(TID_UI, NewCefRunnableMethod(this,
&TestContextHandler::AsyncTestException,
cc, funcException));
CefPostTask(TID_UI, NewCefRunnableMethod(this,
&TestContextHandler::AsyncTestNavigation,
cc, funcNavigate));
return true;
}
} else if (name == "end") {
got_testcomplete_.yes();
DestroyTest();
return true;
}
return false;
}
// This function we will be called later to make it call into the
// IFRAME, which then calls "fromIFrame" so that we can check the
// entered vs current contexts are working as expected.
CefRefPtr<CefV8Context> contextIFrame_;
CefRefPtr<CefV8Value> funcIFrame_;
TrackCallback got_hello_main_;
TrackCallback got_hello_iframe_;
TrackCallback got_correct_entered_url_;
TrackCallback got_correct_current_url_;
TrackCallback got_iframe_as_entered_url_;
TrackCallback got_no_context_;
TrackCallback got_exception_;
TrackCallback got_navigation_;
TrackCallback got_testcomplete_;
};
CefRefPtr<TestContextHandler> handler = new TestContextHandler();
handler->ExecuteTest();
EXPECT_TRUE(handler->got_hello_main_);
EXPECT_TRUE(handler->got_hello_iframe_);
EXPECT_TRUE(handler->got_no_context_);
EXPECT_TRUE(handler->got_iframe_as_entered_url_);
EXPECT_TRUE(handler->got_correct_entered_url_);
EXPECT_TRUE(handler->got_correct_current_url_);
EXPECT_TRUE(handler->got_exception_);
EXPECT_TRUE(handler->got_navigation_);
EXPECT_TRUE(handler->got_testcomplete_);
}

View File

@ -6,17 +6,6 @@
//#define WEB_URLREQUEST_DEBUG
class TrackCallback
{
public:
TrackCallback(): gotit_(false) {}
void yes() { gotit_ = true; }
bool isSet() { return gotit_; }
operator bool() const { return gotit_; }
protected:
bool gotit_;
};
class TestResults
{
public: