Support custom V8 bindings on WebWorker threads (issue #451).

- Add CefRenderProcessHandler callbacks for WebWorker context creation, release and uncaught exceptions.
- Add CefTaskRunner class that supports posting of tasks to standard threads and WebWorker threads.
- Organize V8 internal state information on a per-thread/per-Isolate basis.
- Add webkit_451.patch that provides the WebKit implementation.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@972 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2013-01-03 17:24:24 +00:00
parent f30fbb3d48
commit afe3cb1d67
44 changed files with 2434 additions and 406 deletions

View File

@ -256,6 +256,7 @@
'tests/unittests/stream_unittest.cc',
'tests/unittests/string_unittest.cc',
'tests/unittests/client_app_delegates.cc',
'tests/unittests/task_unittest.cc',
'tests/unittests/test_handler.cc',
'tests/unittests/test_handler.h',
'tests/unittests/test_suite.cc',
@ -900,6 +901,8 @@
'libcef/common/string_multimap_impl.cc',
'libcef/common/string_types_impl.cc',
'libcef/common/task_impl.cc',
'libcef/common/task_runner_impl.cc',
'libcef/common/task_runner_impl.h',
'libcef/common/time_impl.cc',
'libcef/common/time_util.h',
'libcef/common/tracker.cc',

View File

@ -224,6 +224,8 @@
'libcef_dll/ctocpp/string_visitor_ctocpp.h',
'libcef_dll/ctocpp/task_ctocpp.cc',
'libcef_dll/ctocpp/task_ctocpp.h',
'libcef_dll/cpptoc/task_runner_cpptoc.cc',
'libcef_dll/cpptoc/task_runner_cpptoc.h',
'libcef_dll/ctocpp/trace_client_ctocpp.cc',
'libcef_dll/ctocpp/trace_client_ctocpp.h',
'libcef_dll/cpptoc/urlrequest_cpptoc.cc',
@ -374,6 +376,8 @@
'libcef_dll/cpptoc/string_visitor_cpptoc.h',
'libcef_dll/cpptoc/task_cpptoc.cc',
'libcef_dll/cpptoc/task_cpptoc.h',
'libcef_dll/ctocpp/task_runner_ctocpp.cc',
'libcef_dll/ctocpp/task_runner_ctocpp.h',
'libcef_dll/cpptoc/trace_client_cpptoc.cc',
'libcef_dll/cpptoc/trace_client_cpptoc.h',
'libcef_dll/ctocpp/urlrequest_ctocpp.cc',

View File

@ -47,7 +47,8 @@ extern "C" {
///
// Structure used to implement render process callbacks. The functions of this
// structure will always be called on the render process main thread.
// structure will be called on the render process main thread (TID_RENDERER)
// unless otherwise indicated.
///
typedef struct _cef_render_process_handler_t {
///
@ -101,7 +102,10 @@ typedef struct _cef_render_process_handler_t {
///
// Called immediately after the V8 context for a frame has been created. To
// retrieve the JavaScript 'window' object use the
// cef_v8context_t::get_global() function.
// cef_v8context_t::get_global() function. V8 handles can only be accessed
// from the thread on which they are created. A task runner for posting tasks
// on the associated thread can be retrieved via the
// cef_v8context_t::get_task_runner() function.
///
void (CEF_CALLBACK *on_context_created)(
struct _cef_render_process_handler_t* self,
@ -118,8 +122,8 @@ typedef struct _cef_render_process_handler_t {
struct _cef_v8context_t* context);
///
// Called for global uncaught exceptions. Execution of this callback is
// disabled by default. To enable set
// Called for global uncaught exceptions in a frame. Execution of this
// callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0.
///
void (CEF_CALLBACK *on_uncaught_exception)(
@ -128,6 +132,39 @@ typedef struct _cef_render_process_handler_t {
struct _cef_v8context_t* context, struct _cef_v8exception_t* exception,
struct _cef_v8stack_trace_t* stackTrace);
///
// Called on the WebWorker thread immediately after the V8 context for a new
// WebWorker has been created. To retrieve the JavaScript 'self' object use
// the cef_v8context_t::get_global() function. V8 handles can only be accessed
// from the thread on which they are created. A task runner for posting tasks
// on the associated thread can be retrieved via the
// cef_v8context_t::get_task_runner() function.
///
void (CEF_CALLBACK *on_worker_context_created)(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context);
///
// Called on the WebWorker thread immediately before the V8 context for a
// WebWorker is released. No references to the context should be kept after
// this function is called. Any tasks posted or pending on the WebWorker
// thread after this function is called may not be executed.
///
void (CEF_CALLBACK *on_worker_context_released)(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context);
///
// Called on the WebWorker thread for global uncaught exceptions in a
// WebWorker. Execution of this callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0.
///
void (CEF_CALLBACK *on_worker_uncaught_exception)(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context,
struct _cef_v8exception_t* exception,
struct _cef_v8stack_trace_t* stackTrace);
///
// Called when a new node in the the browser gets focus. The |node| value may
// be NULL if no specific node has gained focus. The node object passed to

View File

@ -46,33 +46,33 @@ extern "C" {
///
// CEF maintains multiple internal threads that are used for handling different
// types of tasks in different processes. See the cef_thread_id_t definitions in
// cef_types.h for more information. This function will return true (1) if
// called on the specified thread. It is an error to request a thread from the
// wrong process.
// Returns true (1) if called on the specified thread. Equivalent to using
// cef_task_runner_t::GetForThread(threadId)->belongs_to_current_thread().
///
CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId);
///
// Post a task for execution on the specified thread. This function may be
// called on any thread. It is an error to request a thread from the wrong
// process.
// Post a task for execution on the specified thread. Equivalent to using
// cef_task_runner_t::GetForThread(threadId)->PostTask(task).
///
CEF_EXPORT int cef_post_task(cef_thread_id_t threadId,
struct _cef_task_t* task);
///
// Post a task for delayed execution on the specified thread. This function may
// be called on any thread. It is an error to request a thread from the wrong
// process.
// Post a task for delayed execution on the specified thread. Equivalent to
// using cef_task_runner_t::GetForThread(threadId)->PostDelayedTask(task,
// delay_ms).
///
CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
struct _cef_task_t* task, int64 delay_ms);
///
// Implement this structure for task execution. The functions of this structure
// may be called on any thread.
// Implement this structure for asynchronous task execution. If the task is
// posted successfully and if the associated message loop is still running then
// the execute() function will be called on the target thread. If the task fails
// to post then the task object may be destroyed on the source thread instead of
// the target thread. For this reason be cautious when performing work in the
// task object destructor.
///
typedef struct _cef_task_t {
///
@ -81,13 +81,78 @@ typedef struct _cef_task_t {
cef_base_t base;
///
// Method that will be executed. |threadId| is the thread executing the call.
// Method that will be executed on the target thread.
///
void (CEF_CALLBACK *execute)(struct _cef_task_t* self,
cef_thread_id_t threadId);
void (CEF_CALLBACK *execute)(struct _cef_task_t* self);
} cef_task_t;
///
// Structure that asynchronously executes tasks on the associated thread. It is
// safe to call the functions of this structure on any thread.
//
// CEF maintains multiple internal threads that are used for handling different
// types of tasks in different processes. The cef_thread_id_t definitions in
// cef_types.h list the common CEF threads. Task runners are also available for
// other CEF threads as appropriate (for example, V8 WebWorker threads).
///
typedef struct _cef_task_runner_t {
///
// Base structure.
///
cef_base_t base;
///
// Returns true (1) if this object is pointing to the same task runner as
// |that| object.
///
int (CEF_CALLBACK *is_same)(struct _cef_task_runner_t* self,
struct _cef_task_runner_t* that);
///
// Returns true (1) if this task runner belongs to the current thread.
///
int (CEF_CALLBACK *belongs_to_current_thread)(
struct _cef_task_runner_t* self);
///
// Returns true (1) if this task runner is for the specified CEF thread.
///
int (CEF_CALLBACK *belongs_to_thread)(struct _cef_task_runner_t* self,
cef_thread_id_t threadId);
///
// Post a task for execution on the thread associated with this task runner.
// Execution will occur asynchronously.
///
int (CEF_CALLBACK *post_task)(struct _cef_task_runner_t* self,
struct _cef_task_t* task);
///
// Post a task for delayed execution on the thread associated with this task
// runner. Execution will occur asynchronously. Delayed tasks are not
// supported on V8 WebWorker threads and will be executed without the
// specified delay.
///
int (CEF_CALLBACK *post_delayed_task)(struct _cef_task_runner_t* self,
struct _cef_task_t* task, int64 delay_ms);
} cef_task_runner_t;
///
// Returns the task runner for the current thread. Only CEF threads will have
// task runners. An NULL reference will be returned if this function is called
// on an invalid thread.
///
CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread();
///
// Returns the task runner for the specified CEF thread.
///
CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_thread(
cef_thread_id_t threadId);
#ifdef __cplusplus
}
#endif

View File

@ -105,10 +105,11 @@ CEF_EXPORT int cef_register_extension(const cef_string_t* extension_name,
const cef_string_t* javascript_code, struct _cef_v8handler_t* handler);
///
// 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.
// Structure representing a V8 context handle. V8 handles can only be accessed
// from the thread on which they are created. Valid threads for creating a V8
// handle include the render process main thread (TID_RENDERER) and WebWorker
// threads. A task runner for posting tasks on the associated thread can be
// retrieved via the cef_v8context_t::get_task_runner() function.
///
typedef struct _cef_v8context_t {
///
@ -116,6 +117,14 @@ typedef struct _cef_v8context_t {
///
cef_base_t base;
///
// Returns the task runner associated with this context. V8 handles can only
// be accessed from the thread on which they are created. This function can be
// called on any render process thread.
///
struct _cef_task_runner_t* (CEF_CALLBACK *get_task_runner)(
struct _cef_v8context_t* self);
///
// 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
@ -124,13 +133,15 @@ typedef struct _cef_v8context_t {
int (CEF_CALLBACK *is_valid)(struct _cef_v8context_t* self);
///
// Returns the browser for this context.
// Returns the browser for this context. This function will return an NULL
// reference for WebWorker contexts.
///
struct _cef_browser_t* (CEF_CALLBACK *get_browser)(
struct _cef_v8context_t* self);
///
// Returns the frame for this context.
// Returns the frame for this context. This function will return an NULL
// reference for WebWorker contexts.
///
struct _cef_frame_t* (CEF_CALLBACK *get_frame)(struct _cef_v8context_t* self);
@ -193,8 +204,8 @@ CEF_EXPORT int cef_v8context_in_context();
///
// Structure that should be implemented to handle V8 function calls. The
// functions of this structure will only be called on a render process thread
// that the handler was registered on.
// functions of this structure will be called on the thread associated with the
// V8 function.
///
typedef struct _cef_v8handler_t {
///
@ -219,8 +230,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 only be called on a render process
// thread that the accessor was registered on.
// The functions of this structure will be called on the thread associated with
// the V8 accessor.
///
typedef struct _cef_v8accessor_t {
///
@ -317,10 +328,11 @@ typedef struct _cef_v8exception_t {
///
// 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.
// Structure representing a V8 value handle. V8 handles can only be accessed
// from the thread on which they are created. Valid threads for creating a V8
// handle include the render process main thread (TID_RENDERER) and WebWorker
// threads. A task runner for posting tasks on the associated thread can be
// retrieved via the cef_v8context_t::get_task_runner() function.
///
typedef struct _cef_v8value_t {
///
@ -720,10 +732,11 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_function(const cef_string_t* name,
///
// 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.
// Structure representing a V8 stack trace handle. V8 handles can only be
// accessed from the thread on which they are created. Valid threads for
// creating a V8 handle include the render process main thread (TID_RENDERER)
// and WebWorker threads. A task runner for posting tasks on the associated
// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
///
typedef struct _cef_v8stack_trace_t {
///
@ -759,10 +772,11 @@ CEF_EXPORT cef_v8stack_trace_t* cef_v8stack_trace_get_current(int frame_limit);
///
// 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.
// Structure representing a V8 stack frame handle. V8 handles can only be
// accessed from the thread on which they are created. Valid threads for
// creating a V8 handle include the render process main thread (TID_RENDERER)
// and WebWorker threads. A task runner for posting tasks on the associated
// thread can be retrieved via the cef_v8context_t::get_task_runner() function.
///
typedef struct _cef_v8stack_frame_t {
///

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@ -48,7 +48,8 @@
///
// Class used to implement render process callbacks. The methods of this class
// will always be called on the render process main thread.
// will be called on the render process main thread (TID_RENDERER) unless
// otherwise indicated.
///
/*--cef(source=client)--*/
class CefRenderProcessHandler : public virtual CefBase {
@ -99,7 +100,9 @@ class CefRenderProcessHandler : public virtual CefBase {
///
// Called immediately after the V8 context for a frame has been created. To
// retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal()
// method.
// method. V8 handles can only be accessed from the thread on which they are
// created. A task runner for posting tasks on the associated thread can be
// retrieved via the CefV8Context::GetTaskRunner() method.
///
/*--cef()--*/
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
@ -116,8 +119,8 @@ class CefRenderProcessHandler : public virtual CefBase {
CefRefPtr<CefV8Context> context) {}
///
// Called for global uncaught exceptions. Execution of this callback is
// disabled by default. To enable set
// Called for global uncaught exceptions in a frame. Execution of this
// callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0.
///
/*--cef()--*/
@ -127,6 +130,43 @@ class CefRenderProcessHandler : public virtual CefBase {
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {}
///
// Called on the WebWorker thread immediately after the V8 context for a new
// WebWorker has been created. To retrieve the JavaScript 'self' object use
// the CefV8Context::GetGlobal() method. V8 handles can only be accessed from
// the thread on which they are created. A task runner for posting tasks on
// the associated thread can be retrieved via the
// CefV8Context::GetTaskRunner() method.
///
/*--cef()--*/
virtual void OnWorkerContextCreated(int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {}
///
// Called on the WebWorker thread immediately before the V8 context for a
// WebWorker is released. No references to the context should be kept after
// this method is called. Any tasks posted or pending on the WebWorker
// thread after this method is called may not be executed.
///
/*--cef()--*/
virtual void OnWorkerContextReleased(int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {}
///
// Called on the WebWorker thread for global uncaught exceptions in a
// WebWorker. Execution of this callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0.
///
/*--cef()--*/
virtual void OnWorkerUncaughtException(
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {}
///
// Called when a new node in the the browser gets focus. The |node| value may
// be empty if no specific node has gained focus. The node object passed to

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 Marshall A. Greenblatt. Portions Copyright (c)
// Copyright (c) 2013 Marshall A. Greenblatt. Portions Copyright (c)
// 2006-2011 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -145,7 +145,7 @@ class CefRunnableMethod : public CefTask {
traits_.ReleaseCallee(obj);
}
virtual void Execute(CefThreadId threadId) {
virtual void Execute() {
if (obj_)
DispatchToMethod(obj_, meth_, params_);
}
@ -253,7 +253,7 @@ class CefRunnableFunction : public CefTask {
~CefRunnableFunction() {
}
virtual void Execute(CefThreadId threadId) {
virtual void Execute() {
if (function_)
DispatchToFunction(function_, params_);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@ -39,50 +39,110 @@
#include "include/cef_base.h"
class CefTask;
typedef cef_thread_id_t CefThreadId;
///
// Implement this interface for asynchronous task execution. If the task is
// posted successfully and if the associated message loop is still running then
// the Execute() method will be called on the target thread. If the task fails
// to post then the task object may be destroyed on the source thread instead of
// the target thread. For this reason be cautious when performing work in the
// task object destructor.
///
/*--cef(source=client)--*/
class CefTask : public virtual CefBase {
public:
///
// Method that will be executed on the target thread.
///
/*--cef()--*/
virtual void Execute() =0;
};
///
// Class that asynchronously executes tasks on the associated thread. It is safe
// to call the methods of this class on any thread.
//
// CEF maintains multiple internal threads that are used for handling different
// types of tasks in different processes. See the cef_thread_id_t definitions in
// cef_types.h for more information. This function will return true if called on
// the specified thread. It is an error to request a thread from the wrong
// process.
// types of tasks in different processes. The cef_thread_id_t definitions in
// cef_types.h list the common CEF threads. Task runners are also available for
// other CEF threads as appropriate (for example, V8 WebWorker threads).
///
/*--cef(source=library)--*/
class CefTaskRunner : public virtual CefBase {
public:
///
// Returns the task runner for the current thread. Only CEF threads will have
// task runners. An empty reference will be returned if this method is called
// on an invalid thread.
///
/*--cef()--*/
static CefRefPtr<CefTaskRunner> GetForCurrentThread();
///
// Returns the task runner for the specified CEF thread.
///
/*--cef()--*/
static CefRefPtr<CefTaskRunner> GetForThread(CefThreadId threadId);
///
// Returns true if this object is pointing to the same task runner as |that|
// object.
///
/*--cef()--*/
virtual bool IsSame(CefRefPtr<CefTaskRunner> that) =0;
///
// Returns true if this task runner belongs to the current thread.
///
/*--cef()--*/
virtual bool BelongsToCurrentThread() =0;
///
// Returns true if this task runner is for the specified CEF thread.
///
/*--cef()--*/
virtual bool BelongsToThread(CefThreadId threadId) =0;
///
// Post a task for execution on the thread associated with this task runner.
// Execution will occur asynchronously.
///
/*--cef()--*/
virtual bool PostTask(CefRefPtr<CefTask> task) =0;
///
// Post a task for delayed execution on the thread associated with this task
// runner. Execution will occur asynchronously. Delayed tasks are not
// supported on V8 WebWorker threads and will be executed without the
// specified delay.
///
/*--cef()--*/
virtual bool PostDelayedTask(CefRefPtr<CefTask> task, int64 delay_ms) =0;
};
///
// Returns true if called on the specified thread. Equivalent to using
// CefTaskRunner::GetForThread(threadId)->BelongsToCurrentThread().
///
/*--cef()--*/
bool CefCurrentlyOn(CefThreadId threadId);
///
// Post a task for execution on the specified thread. This function may be
// called on any thread. It is an error to request a thread from the wrong
// process.
// Post a task for execution on the specified thread. Equivalent to
// using CefTaskRunner::GetForThread(threadId)->PostTask(task).
///
/*--cef()--*/
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task);
///
// Post a task for delayed execution on the specified thread. This function may
// be called on any thread. It is an error to request a thread from the wrong
// process.
// Post a task for delayed execution on the specified thread. Equivalent to
// using CefTaskRunner::GetForThread(threadId)->PostDelayedTask(task, delay_ms).
///
/*--cef()--*/
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
int64 delay_ms);
///
// Implement this interface for task execution. The methods of this class may
// be called on any thread.
///
/*--cef(source=client)--*/
class CefTask : public virtual CefBase {
public:
///
// Method that will be executed. |threadId| is the thread executing the call.
///
/*--cef()--*/
virtual void Execute(CefThreadId threadId) =0;
};
#endif // CEF_INCLUDE_CEF_TASK_H_

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved.
// Copyright (c) 2013 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@ -42,6 +42,7 @@
#include "include/cef_base.h"
#include "include/cef_browser.h"
#include "include/cef_frame.h"
#include "include/cef_task.h"
#include <vector>
class CefV8Exception;
@ -116,10 +117,11 @@ bool CefRegisterExtension(const CefString& extension_name,
///
// 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.
// Class representing a V8 context handle. V8 handles can only be accessed from
// the thread on which they are created. Valid threads for creating a V8 handle
// include the render process main thread (TID_RENDERER) and WebWorker threads.
// A task runner for posting tasks on the associated thread can be retrieved via
// the CefV8Context::GetTaskRunner() method.
///
/*--cef(source=library)--*/
class CefV8Context : public virtual CefBase {
@ -142,6 +144,14 @@ class CefV8Context : public virtual CefBase {
/*--cef()--*/
static bool InContext();
///
// Returns the task runner associated with this context. V8 handles can only
// be accessed from the thread on which they are created. This method can be
// called on any render process thread.
///
/*--cef()--*/
virtual CefRefPtr<CefTaskRunner> GetTaskRunner() =0;
///
// 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
@ -151,13 +161,15 @@ class CefV8Context : public virtual CefBase {
virtual bool IsValid() =0;
///
// Returns the browser for this context.
// Returns the browser for this context. This method will return an empty
// reference for WebWorker contexts.
///
/*--cef()--*/
virtual CefRefPtr<CefBrowser> GetBrowser() =0;
///
// Returns the frame for this context.
// Returns the frame for this context. This method will return an empty
// reference for WebWorker contexts.
///
/*--cef()--*/
virtual CefRefPtr<CefFrame> GetFrame() =0;
@ -210,8 +222,7 @@ typedef std::vector<CefRefPtr<CefV8Value> > CefV8ValueList;
///
// Interface that should be implemented to handle V8 function calls. The methods
// of this class will only be called on a render process thread that the handler
// was registered on.
// of this class will be called on the thread associated with the V8 function.
///
/*--cef(source=client)--*/
class CefV8Handler : public virtual CefBase {
@ -234,8 +245,7 @@ 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 only be called on a render process thread that the
// accessor was registered on.
// of this class will be called on the thread associated with the V8 accessor.
///
/*--cef(source=client)--*/
class CefV8Accessor : public virtual CefBase {
@ -330,10 +340,11 @@ class CefV8Exception : public virtual CefBase {
};
///
// 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.
// Class representing a V8 value handle. V8 handles can only be accessed from
// the thread on which they are created. Valid threads for creating a V8 handle
// include the render process main thread (TID_RENDERER) and WebWorker threads.
// A task runner for posting tasks on the associated thread can be retrieved via
// the CefV8Context::GetTaskRunner() method.
///
/*--cef(source=library)--*/
class CefV8Value : public virtual CefBase {
@ -764,10 +775,11 @@ class CefV8Value : public virtual CefBase {
};
///
// 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.
// Class representing a V8 stack trace handle. V8 handles can only be accessed
// from the thread on which they are created. Valid threads for creating a V8
// handle include the render process main thread (TID_RENDERER) and WebWorker
// threads. A task runner for posting tasks on the associated thread can be
// retrieved via the CefV8Context::GetTaskRunner() method.
///
/*--cef(source=library)--*/
class CefV8StackTrace : public virtual CefBase {
@ -801,10 +813,11 @@ class CefV8StackTrace : public virtual CefBase {
};
///
// 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.
// Class representing a V8 stack frame handle. V8 handles can only be accessed
// from the thread on which they are created. Valid threads for creating a V8
// handle include the render process main thread (TID_RENDERER) and WebWorker
// threads. A task runner for posting tasks on the associated thread can be
// retrieved via the CefV8Context::GetTaskRunner() method.
///
/*--cef(source=library)--*/
class CefV8StackFrame : public virtual CefBase {

View File

@ -1,108 +1,38 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
#include "include/cef_task.h"
#include "libcef/browser/thread_util.h"
#include "libcef/renderer/thread_util.h"
#include "libcef/common/task_runner_impl.h"
#include "base/bind.h"
using content::BrowserThread;
namespace {
const int kRenderThreadId = -1;
const int kInvalidThreadId = -10;
int GetThreadId(CefThreadId threadId) {
int id = kInvalidThreadId;
switch (threadId) {
case TID_UI:
id = BrowserThread::UI;
break;
case TID_DB:
id = BrowserThread::DB;
break;
case TID_FILE:
id = BrowserThread::FILE;
break;
case TID_FILE_USER_BLOCKING:
id = BrowserThread::FILE_USER_BLOCKING;
break;
case TID_PROCESS_LAUNCHER:
id = BrowserThread::PROCESS_LAUNCHER;
break;
case TID_CACHE:
id = BrowserThread::CACHE;
break;
case TID_IO:
id = BrowserThread::IO;
break;
case TID_RENDERER:
id = kRenderThreadId;
break;
default:
NOTREACHED() << "invalid thread id " << threadId;
return kInvalidThreadId;
};
if (id >= 0) {
// Verify that we're on the browser process.
if (content::GetContentClient()->browser())
return id;
NOTREACHED() << "called on invalid process";
} else if (id == kRenderThreadId) {
// Verify that we're on the renderer process.
if (content::GetContentClient()->renderer())
return id;
NOTREACHED() << "called on invalid process";
}
return kInvalidThreadId;
}
} // namespace
#include "base/location.h"
bool CefCurrentlyOn(CefThreadId threadId) {
int id = GetThreadId(threadId);
if (id >= 0) {
// Browser process.
return CEF_CURRENTLY_ON(static_cast<BrowserThread::ID>(id));
} else if (id == kRenderThreadId) {
// Renderer process.
return CEF_CURRENTLY_ON_RT();
}
scoped_refptr<base::SequencedTaskRunner> task_runner =
CefTaskRunnerImpl::GetTaskRunner(threadId);
if (task_runner.get())
return task_runner->RunsTasksOnCurrentThread();
return false;
}
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task) {
int id = GetThreadId(threadId);
if (id >= 0) {
// Browser process.
return CEF_POST_TASK(static_cast<BrowserThread::ID>(id),
base::Bind(&CefTask::Execute, task, threadId));
} else if (id == kRenderThreadId) {
// Renderer process.
return CEF_POST_TASK_RT(base::Bind(&CefTask::Execute, task, threadId));
scoped_refptr<base::SequencedTaskRunner> task_runner =
CefTaskRunnerImpl::GetTaskRunner(threadId);
if (task_runner.get()) {
return task_runner->PostTask(FROM_HERE,
base::Bind(&CefTask::Execute, task));
}
return false;
}
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
int64 delay_ms) {
int id = GetThreadId(threadId);
if (id >= 0) {
// Browser process.
return CEF_POST_DELAYED_TASK(static_cast<BrowserThread::ID>(id),
base::Bind(&CefTask::Execute, task, threadId),
base::TimeDelta::FromMilliseconds(delay_ms));
} else if (id == kRenderThreadId) {
// Renderer process.
return CEF_POST_DELAYED_TASK_RT(
base::Bind(&CefTask::Execute, task, threadId),
base::TimeDelta::FromMilliseconds(delay_ms));
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task, int64 delay_ms) {
scoped_refptr<base::SequencedTaskRunner> task_runner =
CefTaskRunnerImpl::GetTaskRunner(threadId);
if (task_runner.get()) {
return task_runner->PostDelayedTask(FROM_HERE,
base::Bind(&CefTask::Execute, task),
base::TimeDelta::FromMilliseconds(delay_ms));
}
return false;
}

View File

@ -0,0 +1,146 @@
// Copyright (c) 2013 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.
#include "libcef/common/task_runner_impl.h"
#include "libcef/renderer/content_renderer_client.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "content/public/browser/browser_thread.h"
using content::BrowserThread;
// CefTaskRunner
// static
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForCurrentThread() {
scoped_refptr<base::SequencedTaskRunner> task_runner =
CefTaskRunnerImpl::GetCurrentTaskRunner();
if (task_runner.get())
return new CefTaskRunnerImpl(task_runner);
return NULL;
}
// static
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForThread(CefThreadId threadId) {
scoped_refptr<base::SequencedTaskRunner> task_runner =
CefTaskRunnerImpl::GetTaskRunner(threadId);
if (task_runner.get())
return new CefTaskRunnerImpl(task_runner);
DLOG(WARNING) << "Invalid thread id " << threadId;
return NULL;
}
// CefTaskRunnerImpl
CefTaskRunnerImpl::CefTaskRunnerImpl(
scoped_refptr<base::SequencedTaskRunner> task_runner)
: task_runner_(task_runner) {
DCHECK(task_runner_.get());
}
// static
scoped_refptr<base::SequencedTaskRunner>
CefTaskRunnerImpl::GetTaskRunner(CefThreadId threadId) {
// Render process.
if (threadId == TID_RENDERER) {
CefContentRendererClient* client = CefContentRendererClient::Get();
if (client)
return client->render_task_runner();
return NULL;
}
// Browser process.
int id = -1;
switch (threadId) {
case TID_UI:
id = BrowserThread::UI;
break;
case TID_DB:
id = BrowserThread::DB;
break;
case TID_FILE:
id = BrowserThread::FILE;
break;
case TID_FILE_USER_BLOCKING:
id = BrowserThread::FILE_USER_BLOCKING;
break;
case TID_PROCESS_LAUNCHER:
id = BrowserThread::PROCESS_LAUNCHER;
break;
case TID_CACHE:
id = BrowserThread::CACHE;
break;
case TID_IO:
id = BrowserThread::IO;
break;
default:
break;
};
if (id >= 0 && content::GetContentClient()->browser() &&
BrowserThread::IsMessageLoopValid(static_cast<BrowserThread::ID>(id))) {
// Don't use BrowserThread::GetMessageLoopProxyForThread because it returns
// a new MessageLoopProxy object for each call and makes pointer equality
// testing impossible.
MessageLoop* message_loop =
BrowserThread::UnsafeGetMessageLoopForThread(
static_cast<BrowserThread::ID>(id));
if (message_loop)
return message_loop->message_loop_proxy();
}
return NULL;
}
// static
scoped_refptr<base::SequencedTaskRunner>
CefTaskRunnerImpl::GetCurrentTaskRunner() {
scoped_refptr<base::SequencedTaskRunner> task_runner;
// Check for a MessageLoopProxy. This covers all of the named browser and
// render process threads, plus a few extra.
task_runner = base::MessageLoopProxy::current();
if (!task_runner.get()) {
// Check for a WebWorker thread.
CefContentRendererClient* client = CefContentRendererClient::Get();
if (client)
task_runner = client->GetCurrentTaskRunner();
}
return task_runner;
}
bool CefTaskRunnerImpl::IsSame(CefRefPtr<CefTaskRunner> that) {
CefTaskRunnerImpl* impl = static_cast<CefTaskRunnerImpl*>(that.get());
return (impl && task_runner_ == impl->task_runner_);
}
bool CefTaskRunnerImpl::BelongsToCurrentThread() {
return task_runner_->RunsTasksOnCurrentThread();
}
bool CefTaskRunnerImpl::BelongsToThread(CefThreadId threadId) {
scoped_refptr<base::SequencedTaskRunner> task_runner =
GetTaskRunner(threadId);
return (task_runner_ == task_runner);
}
bool CefTaskRunnerImpl::PostTask(CefRefPtr<CefTask> task) {
return task_runner_->PostTask(FROM_HERE,
base::Bind(&CefTask::Execute, task));
}
bool CefTaskRunnerImpl::PostDelayedTask(CefRefPtr<CefTask> task,
int64 delay_ms) {
return task_runner_->PostDelayedTask(FROM_HERE,
base::Bind(&CefTask::Execute, task),
base::TimeDelta::FromMilliseconds(delay_ms));
}

View File

@ -0,0 +1,38 @@
// Copyright (c) 2013 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.
#ifndef CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_
#define CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_
#pragma once
#include "include/cef_task.h"
#include "base/sequenced_task_runner.h"
class CefTaskRunnerImpl : public CefTaskRunner {
public:
explicit CefTaskRunnerImpl(
scoped_refptr<base::SequencedTaskRunner> task_runner);
// Returns the task runner associated with |threadId|.
static scoped_refptr<base::SequencedTaskRunner>
GetTaskRunner(CefThreadId threadId);
// Returns the current task runner.
static scoped_refptr<base::SequencedTaskRunner> GetCurrentTaskRunner();
// CefTaskRunner methods:
virtual bool IsSame(CefRefPtr<CefTaskRunner> that) OVERRIDE;
virtual bool BelongsToCurrentThread() OVERRIDE;
virtual bool BelongsToThread(CefThreadId threadId) OVERRIDE;
virtual bool PostTask(CefRefPtr<CefTask> task) OVERRIDE;
virtual bool PostDelayedTask(CefRefPtr<CefTask> task,
int64 delay_ms) OVERRIDE;
private:
scoped_refptr<base::SequencedTaskRunner> task_runner_;
IMPLEMENT_REFCOUNTING(CefTaskRunnerImpl);
DISALLOW_COPY_AND_ASSIGN(CefTaskRunnerImpl);
};
#endif // CEF_LIBCEF_COMMON_TASK_RUNNER_IMPL_H_

View File

@ -1,4 +1,5 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -41,8 +42,11 @@ MSVC_POP_WARNING();
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerRunLoop.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWorkerScriptObserver.h"
#include "v8/include/v8.h"
#include "webkit/glue/worker_task_runner.h"
namespace {
@ -73,8 +77,129 @@ class CefPrerendererClient : public content::RenderViewObserver,
virtual void willAddPrerender(WebKit::WebPrerender* prerender) OVERRIDE {}
};
// Implementation of SequencedTaskRunner for WebWorker threads.
class CefWebWorkerTaskRunner : public base::SequencedTaskRunner,
public webkit_glue::WorkerTaskRunner::Observer {
public:
CefWebWorkerTaskRunner(webkit_glue::WorkerTaskRunner* runner,
int worker_id)
: runner_(runner),
worker_id_(worker_id) {
DCHECK(runner_);
DCHECK_GT(worker_id_, 0);
DCHECK(RunsTasksOnCurrentThread());
// Adds an observer for the current thread.
runner_->AddStopObserver(this);
}
// SequencedTaskRunner methods:
virtual bool PostNonNestableDelayedTask(
const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) OVERRIDE {
return PostDelayedTask(from_here, task, delay);
}
// TaskRunner methods:
virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) OVERRIDE {
if (delay != base::TimeDelta())
DLOG(WARNING) << "Delayed tasks are not supported on WebWorker threads";
runner_->PostTask(worker_id_, task);
return true;
}
virtual bool RunsTasksOnCurrentThread() const OVERRIDE {
return (runner_->CurrentWorkerId() == worker_id_);
}
// WorkerTaskRunner::Observer methods:
virtual void OnWorkerRunLoopStopped() OVERRIDE {
CefContentRendererClient::Get()->RemoveWorkerTaskRunner(worker_id_);
}
private:
webkit_glue::WorkerTaskRunner* runner_;
int worker_id_;
};
} // namespace
class CefWebWorkerScriptObserver : public WebKit::WebWorkerScriptObserver {
public:
CefWebWorkerScriptObserver() {
}
virtual void didCreateWorkerScriptContext(
const WebKit::WebWorkerRunLoop& run_loop,
const WebKit::WebURL& url,
v8::Handle<v8::Context> context) OVERRIDE {
// Create global objects associated with the WebWorker Isolate.
CefV8IsolateCreated();
int stack_size =
CefContentRendererClient::Get()->uncaught_exception_stack_size();
if (stack_size > 0)
CefV8SetUncaughtExceptionStackSize(stack_size);
webkit_glue::WorkerTaskRunner* worker_runner =
webkit_glue::WorkerTaskRunner::Instance();
int worker_id = worker_runner->CurrentWorkerId();
DCHECK_GT(worker_id, 0);
GURL gurl = GURL(url);
CefV8SetWorkerAttributes(worker_id, gurl);
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get()) {
v8::HandleScope handle_scope;
v8::Context::Scope scope(context);
CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(context));
handler->OnWorkerContextCreated(worker_id, gurl.spec(), contextPtr);
}
}
}
virtual void willReleaseWorkerScriptContext(
const WebKit::WebWorkerRunLoop& run_loop,
const WebKit::WebURL& url,
v8::Handle<v8::Context> context) OVERRIDE {
v8::HandleScope handle_scope;
v8::Context::Scope scope(context);
// Notify the render process handler.
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (application.get()) {
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (handler.get()) {
webkit_glue::WorkerTaskRunner* worker_runner =
webkit_glue::WorkerTaskRunner::Instance();
int worker_id = worker_runner->CurrentWorkerId();
DCHECK_GT(worker_id, 0);
CefRefPtr<CefV8Context> contextPtr(new CefV8ContextImpl(context));
GURL gurl = GURL(url);
handler->OnWorkerContextReleased(worker_id, gurl.spec(), contextPtr);
}
}
CefV8ReleaseContext(context);
// Destroy global objects associated with the WebWorker Isolate.
CefV8IsolateDestroyed();
}
};
struct CefContentRendererClient::SchemeInfo {
std::string scheme_name;
bool is_local;
@ -149,6 +274,9 @@ void CefContentRendererClient::WebKitInitialized() {
// TODO(cef): Enable these once the implementation supports it.
WebKit::WebRuntimeFeatures::enableNotifications(false);
worker_script_observer_.reset(new CefWebWorkerScriptObserver());
WebKit::WebWorkerInfo::addScriptObserver(worker_script_observer_.get());
if (!scheme_info_list_.empty()) {
// Register the custom schemes.
SchemeInfoList::const_iterator it = scheme_info_list_.begin();
@ -189,11 +317,8 @@ void CefContentRendererClient::WebKitInitialized() {
&uncaught_exception_stack_size);
if (uncaught_exception_stack_size > 0) {
CefContentRendererClient::Get()->SetUncaughtExceptionStackSize(
uncaught_exception_stack_size);
v8::V8::AddMessageListener(&CefV8MessageHandler);
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
uncaught_exception_stack_size, v8::StackTrace::kDetailed);
uncaught_exception_stack_size_ = uncaught_exception_stack_size;
CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
}
}
@ -207,6 +332,11 @@ void CefContentRendererClient::WebKitInitialized() {
}
}
void CefContentRendererClient::OnRenderProcessShutdown() {
// Destroy global objects associated with the default Isolate.
CefV8IsolateDestroyed();
}
void CefContentRendererClient::DevToolsAgentAttached() {
CEF_REQUIRE_RT();
++devtools_agent_count_;
@ -218,17 +348,71 @@ void CefContentRendererClient::DevToolsAgentDetached() {
if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
// When the last DevToolsAgent is detached the stack size is set to 0.
// Restore the user-specified stack size here.
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
uncaught_exception_stack_size_, v8::StackTrace::kDetailed);
CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
// And do the same for any WebWorker threads.
WorkerTaskRunnerMap map_copy;
{
base::AutoLock lock_scope(worker_task_runner_lock_);
map_copy = worker_task_runner_map_;
}
WorkerTaskRunnerMap::const_iterator it = map_copy.begin();
for (; it != map_copy.end(); ++it) {
it->second->PostTask(FROM_HERE,
base::Bind(CefV8SetUncaughtExceptionStackSize,
uncaught_exception_stack_size_));
}
}
}
void CefContentRendererClient::SetUncaughtExceptionStackSize(int stackSize) {
uncaught_exception_stack_size_ = stackSize;
scoped_refptr<base::SequencedTaskRunner>
CefContentRendererClient::GetCurrentTaskRunner() {
// Check if currently on the render thread.
if (CEF_CURRENTLY_ON_RT())
return render_task_runner_;
// Check if a WebWorker exists for the current thread.
webkit_glue::WorkerTaskRunner* worker_runner =
webkit_glue::WorkerTaskRunner::Instance();
int worker_id = worker_runner->CurrentWorkerId();
if (worker_id > 0) {
base::AutoLock lock_scope(worker_task_runner_lock_);
WorkerTaskRunnerMap::const_iterator it =
worker_task_runner_map_.find(worker_id);
if (it != worker_task_runner_map_.end())
return it->second;
scoped_refptr<base::SequencedTaskRunner> task_runner =
new CefWebWorkerTaskRunner(worker_runner, worker_id);
worker_task_runner_map_[worker_id] = task_runner;
return task_runner;
}
return NULL;
}
scoped_refptr<base::SequencedTaskRunner>
CefContentRendererClient::GetWorkerTaskRunner(int worker_id) {
base::AutoLock lock_scope(worker_task_runner_lock_);
WorkerTaskRunnerMap::const_iterator it =
worker_task_runner_map_.find(worker_id);
if (it != worker_task_runner_map_.end())
return it->second;
return NULL;
}
void CefContentRendererClient::RemoveWorkerTaskRunner(int worker_id) {
base::AutoLock lock_scope(worker_task_runner_lock_);
WorkerTaskRunnerMap::iterator it = worker_task_runner_map_.find(worker_id);
if (it != worker_task_runner_map_.end())
worker_task_runner_map_.erase(it);
}
void CefContentRendererClient::RenderThreadStarted() {
render_loop_ = base::MessageLoopProxy::current();
render_task_runner_ = base::MessageLoopProxy::current();
observer_.reset(new CefRenderProcessObserver());
content::RenderThread* thread = content::RenderThread::Get();
@ -244,6 +428,9 @@ void CefContentRendererClient::RenderThreadStarted() {
WebKit::WebPrerenderingSupport::initialize(new CefPrerenderingSupport());
// Create global objects associated with the default Isolate.
CefV8IsolateCreated();
// Retrieve the new render thread information synchronously.
CefProcessHostMsg_GetNewRenderThreadInfo_Params params;
thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(&params));

View File

@ -1,4 +1,5 @@
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -15,10 +16,11 @@
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/sequenced_task_runner.h"
#include "content/public/renderer/content_renderer_client.h"
class CefRenderProcessObserver;
class CefWebWorkerScriptObserver;
struct Cef_CrossOriginWhiteListEntry_Params;
class CefContentRendererClient : public content::ContentRendererClient {
@ -43,14 +45,32 @@ class CefContentRendererClient : public content::ContentRendererClient {
bool is_local,
bool is_display_isolated);
// Render thread message loop proxy.
base::MessageLoopProxy* render_loop() const { return render_loop_.get(); }
// Render thread task runner.
base::SequencedTaskRunner* render_task_runner() const {
return render_task_runner_.get();
}
int uncaught_exception_stack_size() const {
return uncaught_exception_stack_size_;
}
void WebKitInitialized();
void OnRenderProcessShutdown();
void DevToolsAgentAttached();
void DevToolsAgentDetached();
void SetUncaughtExceptionStackSize(int stackSize);
// Returns the task runner for the current thread. If this is a WebWorker
// thread and the task runner does not already exist it will be created.
// Returns NULL if the current thread is not a valid render process thread.
scoped_refptr<base::SequencedTaskRunner> GetCurrentTaskRunner();
// Returns the task runner for the specified worker ID or NULL if the
// specified worker ID is not valid.
scoped_refptr<base::SequencedTaskRunner> GetWorkerTaskRunner(int worker_id);
// Remove the task runner associated with the specified worker ID.
void RemoveWorkerTaskRunner(int worker_id);
private:
// ContentRendererClient implementation.
@ -69,8 +89,9 @@ class CefContentRendererClient : public content::ContentRendererClient {
v8::Handle<v8::Context> context,
int world_id) OVERRIDE;
scoped_refptr<base::MessageLoopProxy> render_loop_;
scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
scoped_ptr<CefRenderProcessObserver> observer_;
scoped_ptr<CefWebWorkerScriptObserver> worker_script_observer_;
// Map of RenderView pointers to CefBrowserImpl references.
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;
@ -87,6 +108,13 @@ class CefContentRendererClient : public content::ContentRendererClient {
int devtools_agent_count_;
int uncaught_exception_stack_size_;
// Map of worker thread IDs to task runners. Access must be protected by
// |worker_task_runner_lock_|.
typedef std::map<int, scoped_refptr<base::SequencedTaskRunner> >
WorkerTaskRunnerMap;
WorkerTaskRunnerMap worker_task_runner_map_;
base::Lock worker_task_runner_lock_;
};
#endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_

View File

@ -1,4 +1,4 @@
/// Copyright (c) 2012 The Chromium Embedded Framework Authors.
/// Copyright (c) 2013 The Chromium Embedded Framework Authors.
// Portions (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -34,6 +34,10 @@ void CefRenderProcessObserver::WebKitInitialized() {
CefContentRendererClient::Get()->WebKitInitialized();
}
void CefRenderProcessObserver::OnRenderProcessShutdown() {
CefContentRendererClient::Get()->OnRenderProcessShutdown();
}
void CefRenderProcessObserver::OnModifyCrossOriginWhitelistEntry(
bool add,
const Cef_CrossOriginWhiteListEntry_Params& params) {

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Copyright (c) 2013 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@ -20,6 +20,7 @@ class CefRenderProcessObserver : public content::RenderProcessObserver {
// RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void WebKitInitialized() OVERRIDE;
virtual void OnRenderProcessShutdown() OVERRIDE;
private:
// Message handlers called on the render thread.

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -28,7 +28,8 @@
return; \
}
#define CEF_RENDER_LOOP() (CefContentRendererClient::Get()->render_loop())
#define CEF_RENDER_LOOP() \
(CefContentRendererClient::Get()->render_task_runner())
#define CEF_POST_TASK_RT(task) \
CEF_RENDER_LOOP()->PostTask(FROM_HERE, task)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -15,6 +15,8 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "ScriptControllerBase.h" // NOLINT(build/include)
#include "V8Binding.h" // NOLINT(build/include)
#include "V8RecursionScope.h" // NOLINT(build/include)
#include "WorkerContext.h" // NOLINT(build/include)
#include "WorkerScriptController.h" // NOLINT(build/include)
MSVC_POP_WARNING();
#undef LOG
@ -22,6 +24,7 @@ MSVC_POP_WARNING();
#include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h"
#include "libcef/common/task_runner_impl.h"
#include "libcef/common/tracker.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/thread_util.h"
@ -29,6 +32,8 @@ MSVC_POP_WARNING();
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/string_number_conversions.h"
#include "base/threading/thread_local.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.h"
@ -38,12 +43,21 @@ namespace {
static const char kCefTrackObject[] = "Cef::TrackObject";
static const char kCefContextState[] = "Cef::ContextState";
// Memory manager.
void MessageListenerCallbackImpl(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data);
class CefV8TrackManager {
// Manages memory and state information associated with a single Isolate.
class CefV8IsolateManager {
public:
CefV8TrackManager()
: context_safety_impl_(IMPL_HASH) {
CefV8IsolateManager()
: isolate_(v8::Isolate::GetCurrent()),
task_runner_(CefContentRendererClient::Get()->GetCurrentTaskRunner()),
context_safety_impl_(IMPL_HASH),
message_listener_registered_(false),
worker_id_(0) {
DCHECK(isolate_);
DCHECK(task_runner_.get());
const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kContextSafetyImplementation)) {
std::string value = command_line.GetSwitchValueASCII(
@ -57,9 +71,15 @@ class CefV8TrackManager {
}
}
}
~CefV8IsolateManager() {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
DCHECK(context_map_.empty());
}
scoped_refptr<CefV8ContextState> GetContextState(
v8::Handle<v8::Context> context) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
if (context_safety_impl_ == IMPL_DISABLED)
return scoped_refptr<CefV8ContextState>();
@ -105,6 +125,8 @@ class CefV8TrackManager {
}
void ReleaseContext(v8::Handle<v8::Context> context) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
if (context_safety_impl_ == IMPL_DISABLED)
return;
@ -135,14 +157,49 @@ class CefV8TrackManager {
}
void AddGlobalTrackObject(CefTrackNode* object) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
global_manager_.Add(object);
}
void DeleteGlobalTrackObject(CefTrackNode* object) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
global_manager_.Delete(object);
}
void SetUncaughtExceptionStackSize(int stack_size) {
if (stack_size <= 0)
return;
if (!message_listener_registered_) {
v8::V8::AddMessageListener(&MessageListenerCallbackImpl);
message_listener_registered_ = true;
}
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
stack_size, v8::StackTrace::kDetailed);
}
void SetWorkerAttributes(int worker_id, const GURL& worker_url) {
worker_id_ = worker_id;
worker_url_ = worker_url;
}
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
return task_runner_;
}
int worker_id() const {
return worker_id_;
}
const GURL& worker_url() const {
return worker_url_;
}
private:
v8::Isolate* isolate_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
enum ContextSafetyImpl {
IMPL_DISABLED,
IMPL_HASH,
@ -160,9 +217,51 @@ class CefV8TrackManager {
// Used for globally tracked objects that are not associated with a particular
// context.
CefTrackManager global_manager_;
// True if the message listener has been registered.
bool message_listener_registered_;
// Attributes associated with WebWorker threads.
int worker_id_;
GURL worker_url_;
};
base::LazyInstance<CefV8TrackManager> g_v8_tracker = LAZY_INSTANCE_INITIALIZER;
// Chromium uses the default Isolate for the main render process thread and a
// new Isolate for each WebWorker thread. Continue this pattern by tracking
// Isolate information on a per-thread basis. This implementation will need to
// be re-worked (perhaps using a map keyed on v8::Isolate::GetCurrent()) if
// in the future Chromium begins using the same Isolate across multiple threads.
class CefV8StateManager {
public:
CefV8StateManager() {
}
void CreateIsolateManager() {
DCHECK(!current_tls_.Get());
current_tls_.Set(new CefV8IsolateManager());
}
void DestroyIsolateManager() {
DCHECK(current_tls_.Get());
delete current_tls_.Get();
current_tls_.Set(NULL);
}
CefV8IsolateManager* GetIsolateManager() {
CefV8IsolateManager* manager = current_tls_.Get();
DCHECK(manager);
return manager;
}
private:
base::ThreadLocalPointer<CefV8IsolateManager> current_tls_;
};
base::LazyInstance<CefV8StateManager> g_v8_state = LAZY_INSTANCE_INITIALIZER;
CefV8IsolateManager* GetIsolateManager() {
return g_v8_state.Pointer()->GetIsolateManager();
}
class V8TrackObject : public CefTrackNode {
public:
@ -275,7 +374,7 @@ class CefV8MakeWeakParam {
// |object_| will be deleted when:
// A. The process shuts down, or
// B. TrackDestructor is called for the weak handle.
g_v8_tracker.Pointer()->AddGlobalTrackObject(object_);
GetIsolateManager()->AddGlobalTrackObject(object_);
}
}
~CefV8MakeWeakParam() {
@ -285,7 +384,7 @@ class CefV8MakeWeakParam {
if (context_state_->IsValid())
context_state_->DeleteTrackObject(object_);
} else {
g_v8_tracker.Pointer()->DeleteGlobalTrackObject(object_);
GetIsolateManager()->DeleteGlobalTrackObject(object_);
}
v8::V8::AdjustAmountOfExternalAllocatedMemory(
@ -474,6 +573,37 @@ void AccessorSetterCallbackImpl(v8::Local<v8::String> property,
}
}
v8::Local<v8::Value> CallV8Function(v8::Handle<v8::Context> context,
v8::Handle<v8::Function> function,
v8::Handle<v8::Object> receiver,
int argc,
v8::Handle<v8::Value> args[]) {
v8::Local<v8::Value> func_rv;
// Execute the function call using the ScriptController so that inspector
// instrumentation works.
if (CEF_CURRENTLY_ON_RT()) {
RefPtr<WebCore::Frame> frame = WebCore::toFrameIfNotDetached(context);
DCHECK(frame);
if (frame &&
frame->script()->canExecuteScripts(WebCore::AboutToExecuteScript)) {
func_rv = frame->script()->callFunction(function, receiver, argc, args);
}
} else {
WebCore::WorkerScriptController* controller =
WebCore::WorkerScriptController::controllerForContext();
DCHECK(controller);
if (controller) {
func_rv = WebCore::ScriptController::callFunctionWithInstrumentation(
controller->workerContext()->scriptExecutionContext(),
function, receiver, argc, args);
}
}
return func_rv;
}
// V8 extension registration.
class ExtensionWrapper : public v8::Extension {
@ -486,7 +616,7 @@ class ExtensionWrapper : public v8::Extension {
// The reference will be released when the process exits.
V8TrackObject* object = new V8TrackObject;
object->SetHandler(handler);
g_v8_tracker.Pointer()->AddGlobalTrackObject(object);
GetIsolateManager()->AddGlobalTrackObject(object);
}
}
@ -549,13 +679,58 @@ class CefV8ExceptionImpl : public CefV8Exception {
IMPLEMENT_REFCOUNTING(CefV8ExceptionImpl);
};
void MessageListenerCallbackImpl(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data) {
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (!application.get())
return;
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (!handler.get())
return;
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
v8::Handle<v8::StackTrace> v8Stack = message->GetStackTrace();
DCHECK(!v8Stack.IsEmpty());
CefRefPtr<CefV8StackTrace> stackTrace = new CefV8StackTraceImpl(v8Stack);
CefRefPtr<CefV8Exception> exception = new CefV8ExceptionImpl(message);
if (CEF_CURRENTLY_ON_RT()) {
handler->OnUncaughtException(context->GetBrowser(), context->GetFrame(),
context, exception, stackTrace);
} else {
CefV8IsolateManager* manager = GetIsolateManager();
DCHECK_GT(manager->worker_id(), 0);
handler->OnWorkerUncaughtException(manager->worker_id(),
manager->worker_url().spec(), context, exception, stackTrace);
}
}
} // namespace
// Global functions.
void CefV8IsolateCreated() {
g_v8_state.Pointer()->CreateIsolateManager();
}
void CefV8IsolateDestroyed() {
g_v8_state.Pointer()->DestroyIsolateManager();
}
void CefV8ReleaseContext(v8::Handle<v8::Context> context) {
g_v8_tracker.Pointer()->ReleaseContext(context);
GetIsolateManager()->ReleaseContext(context);
}
void CefV8SetUncaughtExceptionStackSize(int stack_size) {
GetIsolateManager()->SetUncaughtExceptionStackSize(stack_size);
}
void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url) {
GetIsolateManager()->SetWorkerAttributes(worker_id, worker_url);
}
bool CefRegisterExtension(const CefString& extension_name,
@ -565,9 +740,9 @@ bool CefRegisterExtension(const CefString& extension_name,
CEF_REQUIRE_RT_RETURN(false);
V8TrackString* name = new V8TrackString(extension_name);
g_v8_tracker.Pointer()->AddGlobalTrackObject(name);
GetIsolateManager()->AddGlobalTrackObject(name);
V8TrackString* code = new V8TrackString(javascript_code);
g_v8_tracker.Pointer()->AddGlobalTrackObject(code);
GetIsolateManager()->AddGlobalTrackObject(code);
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
code->GetString(), handler.get());
@ -579,7 +754,7 @@ bool CefRegisterExtension(const CefString& extension_name,
// Helper macros
#define CEF_V8_HAS_ISOLATE() (!!v8::Isolate::GetCurrent())
#define CEF_V8_HAS_ISOLATE() (!!GetIsolateManager())
#define CEF_V8_REQUIRE_ISOLATE_RETURN(var) \
if (!CEF_V8_HAS_ISOLATE()) { \
NOTREACHED() << "V8 isolate is not valid"; \
@ -636,13 +811,14 @@ CefV8HandleBase::~CefV8HandleBase() {
}
bool CefV8HandleBase::BelongsToCurrentThread() const {
return message_loop_proxy_->BelongsToCurrentThread();
return task_runner_->RunsTasksOnCurrentThread();
}
CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context)
: message_loop_proxy_(base::MessageLoopProxy::current()) {
DCHECK(message_loop_proxy_.get());
context_state_ = g_v8_tracker.Pointer()->GetContextState(context);
CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context) {
CefV8IsolateManager* manager = GetIsolateManager();
DCHECK(manager);
task_runner_ = manager->task_runner();
context_state_ = manager->GetContextState(context);
}
@ -691,6 +867,10 @@ CefV8ContextImpl::~CefV8ContextImpl() {
DLOG_ASSERT(0 == enter_count_);
}
CefRefPtr<CefTaskRunner> CefV8ContextImpl::GetTaskRunner() {
return new CefTaskRunnerImpl(handle_->task_runner());
}
bool CefV8ContextImpl::IsValid() {
return CEF_V8_IS_VALID();
}
@ -699,6 +879,10 @@ CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser() {
CefRefPtr<CefBrowser> browser;
CEF_V8_REQUIRE_VALID_RETURN(browser);
// Return NULL for WebWorkers.
if (!CEF_CURRENTLY_ON_RT())
return browser;
WebKit::WebFrame* webframe = GetWebFrame();
if (webframe)
browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->top());
@ -710,6 +894,10 @@ CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
CefRefPtr<CefFrame> frame;
CEF_V8_REQUIRE_VALID_RETURN(frame);
// Return NULL for WebWorkers.
if (!CEF_CURRENTLY_ON_RT())
return frame;
WebKit::WebFrame* webframe = GetWebFrame();
if (webframe) {
CefRefPtr<CefBrowserImpl> browser =
@ -777,8 +965,9 @@ bool CefV8ContextImpl::Eval(const CefString& code,
}
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(GetHandle());
v8::Local<v8::Object> obj = GetHandle()->Global();
v8::Local<v8::Context> context = GetContext();
v8::Context::Scope context_scope(context);
v8::Local<v8::Object> obj = context->Global();
// Retrieve the eval function.
v8::Local<v8::Value> val = obj->Get(v8::String::New("eval"));
@ -790,19 +979,12 @@ bool CefV8ContextImpl::Eval(const CefString& code,
v8::TryCatch try_catch;
try_catch.SetVerbose(true);
v8::Local<v8::Value> func_rv;
retval = NULL;
exception = NULL;
// Execute the function call using the ScriptController so that inspector
// instrumentation works.
RefPtr<WebCore::Frame> frame = WebCore::toFrameIfNotDetached(GetHandle());
DCHECK(frame);
if (frame &&
frame->script()->canExecuteScripts(WebCore::AboutToExecuteScript)) {
func_rv = frame->script()->callFunction(func, obj, 1, &code_val);
}
v8::Local<v8::Value> func_rv =
CallV8Function(context, func, obj, 1, &code_val);
if (try_catch.HasCaught()) {
exception = new CefV8ExceptionImpl(try_catch.Message());
@ -818,6 +1000,7 @@ v8::Local<v8::Context> CefV8ContextImpl::GetContext() {
}
WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() {
CEF_REQUIRE_RT();
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(GetHandle());
WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext();
@ -1020,7 +1203,6 @@ CefV8ValueImpl::CefV8ValueImpl(v8::Handle<v8::Value> value,
CefV8ValueImpl::~CefV8ValueImpl() {
}
bool CefV8ValueImpl::IsValid() {
return CEF_V8_IS_VALID();
}
@ -1519,16 +1701,9 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
{
v8::TryCatch try_catch;
try_catch.SetVerbose(true);
v8::Local<v8::Value> func_rv;
// Execute the function call using the ScriptController so that inspector
// instrumentation works.
RefPtr<WebCore::Frame> frame = WebCore::toFrameIfNotDetached(context_local);
DCHECK(frame);
if (frame &&
frame->script()->canExecuteScripts(WebCore::AboutToExecuteScript)) {
func_rv = frame->script()->callFunction(func, recv, argc, argv);
}
v8::Local<v8::Value> func_rv =
CallV8Function(context_local, func, recv, argc, argv);
if (!HasCaught(try_catch) && !func_rv.IsEmpty())
retval = new CefV8ValueImpl(func_rv);
@ -1662,26 +1837,3 @@ bool CefV8StackFrameImpl::IsConstructor() {
v8::HandleScope handle_scope;
return GetHandle()->IsConstructor();
}
void CefV8MessageHandler(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data) {
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
CefRefPtr<CefBrowser> browser = context->GetBrowser();
CefRefPtr<CefFrame> frame = context->GetFrame();
v8::Handle<v8::StackTrace> v8Stack = message->GetStackTrace();
DCHECK(!v8Stack.IsEmpty());
CefRefPtr<CefV8StackTrace> stackTrace = new CefV8StackTraceImpl(v8Stack);
CefRefPtr<CefApp> application = CefContentClient::Get()->application();
if (!application.get())
return;
CefRefPtr<CefRenderProcessHandler> handler =
application->GetRenderProcessHandler();
if (!handler.get())
return;
CefRefPtr<CefV8Exception> exception = new CefV8ExceptionImpl(message);
handler->OnUncaughtException(browser, frame, context, exception, stackTrace);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -15,17 +15,30 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop_proxy.h"
#include "base/sequenced_task_runner.h"
class CefTrackNode;
class GURL;
namespace WebKit {
class WebFrame;
};
// Call to detach all handles associated with the specified contxt.
// Call after a V8 Isolate has been created and entered for the first time.
void CefV8IsolateCreated();
// Call before a V8 Isolate is exited and destroyed.
void CefV8IsolateDestroyed();
// Call to detach all handles associated with the specified context.
void CefV8ReleaseContext(v8::Handle<v8::Context> context);
// Set the stack size for uncaught exceptions.
void CefV8SetUncaughtExceptionStackSize(int stack_size);
// Set attributes associated with a WebWorker thread.
void CefV8SetWorkerAttributes(int worker_id, const GURL& worker_url);
// Used to detach handles when the associated context is released.
class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
public:
@ -60,10 +73,10 @@ class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
struct CefV8DeleteOnMessageLoopThread {
template<typename T>
static void Destruct(const T* x) {
if (x->message_loop_proxy_->BelongsToCurrentThread()) {
if (x->task_runner()->RunsTasksOnCurrentThread()) {
delete x;
} else {
if (!x->message_loop_proxy_->DeleteSoon(FROM_HERE, x)) {
if (!x->task_runner()->DeleteSoon(FROM_HERE, x)) {
#if defined(UNIT_TEST)
// Only logged under unit testing because leaks at shutdown
// are acceptable under normal circumstances.
@ -89,15 +102,17 @@ class CefV8HandleBase :
bool BelongsToCurrentThread() const;
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
return task_runner_;
}
protected:
// |context| is the context that owns this handle. If empty the current
// context will be used.
explicit CefV8HandleBase(v8::Handle<v8::Context> context);
protected:
friend struct CefV8DeleteOnMessageLoopThread;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_refptr<CefV8ContextState> context_state_;
};
@ -141,6 +156,7 @@ class CefV8ContextImpl : public CefV8Context {
explicit CefV8ContextImpl(v8::Handle<v8::Context> context);
virtual ~CefV8ContextImpl();
virtual CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
virtual bool IsValid() OVERRIDE;
virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
virtual CefRefPtr<CefFrame> GetFrame() OVERRIDE;
@ -320,7 +336,4 @@ class CefV8StackFrameImpl : public CefV8StackFrame {
DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
};
void CefV8MessageHandler(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data);
#endif // CEF_LIBCEF_RENDERER_V8_IMPL_H_

View File

@ -218,6 +218,90 @@ void CEF_CALLBACK render_process_handler_on_uncaught_exception(
CefV8StackTraceCToCpp::Wrap(stackTrace));
}
void CEF_CALLBACK render_process_handler_on_worker_context_created(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: url; type: string_byref_const
DCHECK(url);
if (!url)
return;
// Verify param: context; type: refptr_diff
DCHECK(context);
if (!context)
return;
// Execute
CefRenderProcessHandlerCppToC::Get(self)->OnWorkerContextCreated(
worker_id,
CefString(url),
CefV8ContextCToCpp::Wrap(context));
}
void CEF_CALLBACK render_process_handler_on_worker_context_released(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: url; type: string_byref_const
DCHECK(url);
if (!url)
return;
// Verify param: context; type: refptr_diff
DCHECK(context);
if (!context)
return;
// Execute
CefRenderProcessHandlerCppToC::Get(self)->OnWorkerContextReleased(
worker_id,
CefString(url),
CefV8ContextCToCpp::Wrap(context));
}
void CEF_CALLBACK render_process_handler_on_worker_uncaught_exception(
struct _cef_render_process_handler_t* self, int worker_id,
const cef_string_t* url, struct _cef_v8context_t* context,
struct _cef_v8exception_t* exception,
struct _cef_v8stack_trace_t* stackTrace) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Verify param: url; type: string_byref_const
DCHECK(url);
if (!url)
return;
// Verify param: context; type: refptr_diff
DCHECK(context);
if (!context)
return;
// Verify param: exception; type: refptr_diff
DCHECK(exception);
if (!exception)
return;
// Verify param: stackTrace; type: refptr_diff
DCHECK(stackTrace);
if (!stackTrace)
return;
// Execute
CefRenderProcessHandlerCppToC::Get(self)->OnWorkerUncaughtException(
worker_id,
CefString(url),
CefV8ContextCToCpp::Wrap(context),
CefV8ExceptionCToCpp::Wrap(exception),
CefV8StackTraceCToCpp::Wrap(stackTrace));
}
void CEF_CALLBACK render_process_handler_on_focused_node_changed(
struct _cef_render_process_handler_t* self, cef_browser_t* browser,
cef_frame_t* frame, cef_domnode_t* node) {
@ -290,6 +374,12 @@ CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC(
render_process_handler_on_context_released;
struct_.struct_.on_uncaught_exception =
render_process_handler_on_uncaught_exception;
struct_.struct_.on_worker_context_created =
render_process_handler_on_worker_context_created;
struct_.struct_.on_worker_context_released =
render_process_handler_on_worker_context_released;
struct_.struct_.on_worker_uncaught_exception =
render_process_handler_on_worker_uncaught_exception;
struct_.struct_.on_focused_node_changed =
render_process_handler_on_focused_node_changed;
struct_.struct_.on_process_message_received =

View File

@ -15,8 +15,7 @@
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK task_execute(struct _cef_task_t* self,
cef_thread_id_t threadId) {
void CEF_CALLBACK task_execute(struct _cef_task_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
@ -24,8 +23,7 @@ void CEF_CALLBACK task_execute(struct _cef_task_t* self,
return;
// Execute
CefTaskCppToC::Get(self)->Execute(
threadId);
CefTaskCppToC::Get(self)->Execute();
}

View File

@ -0,0 +1,153 @@
// Copyright (c) 2013 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. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/task_runner_cpptoc.h"
#include "libcef_dll/ctocpp/task_ctocpp.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_current_thread() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
CefRefPtr<CefTaskRunner> _retval = CefTaskRunner::GetForCurrentThread();
// Return type: refptr_same
return CefTaskRunnerCppToC::Wrap(_retval);
}
CEF_EXPORT cef_task_runner_t* cef_task_runner_get_for_thread(
cef_thread_id_t threadId) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
CefRefPtr<CefTaskRunner> _retval = CefTaskRunner::GetForThread(
threadId);
// Return type: refptr_same
return CefTaskRunnerCppToC::Wrap(_retval);
}
// MEMBER FUNCTIONS - Body may be edited by hand.
int CEF_CALLBACK task_runner_is_same(struct _cef_task_runner_t* self,
struct _cef_task_runner_t* that) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: that; type: refptr_same
DCHECK(that);
if (!that)
return 0;
// Execute
bool _retval = CefTaskRunnerCppToC::Get(self)->IsSame(
CefTaskRunnerCppToC::Unwrap(that));
// Return type: bool
return _retval;
}
int CEF_CALLBACK task_runner_belongs_to_current_thread(
struct _cef_task_runner_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToCurrentThread();
// Return type: bool
return _retval;
}
int CEF_CALLBACK task_runner_belongs_to_thread(struct _cef_task_runner_t* self,
cef_thread_id_t threadId) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefTaskRunnerCppToC::Get(self)->BelongsToThread(
threadId);
// Return type: bool
return _retval;
}
int CEF_CALLBACK task_runner_post_task(struct _cef_task_runner_t* self,
cef_task_t* task) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: task; type: refptr_diff
DCHECK(task);
if (!task)
return 0;
// Execute
bool _retval = CefTaskRunnerCppToC::Get(self)->PostTask(
CefTaskCToCpp::Wrap(task));
// Return type: bool
return _retval;
}
int CEF_CALLBACK task_runner_post_delayed_task(struct _cef_task_runner_t* self,
cef_task_t* task, int64 delay_ms) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Verify param: task; type: refptr_diff
DCHECK(task);
if (!task)
return 0;
// Execute
bool _retval = CefTaskRunnerCppToC::Get(self)->PostDelayedTask(
CefTaskCToCpp::Wrap(task),
delay_ms);
// Return type: bool
return _retval;
}
// CONSTRUCTOR - Do not edit by hand.
CefTaskRunnerCppToC::CefTaskRunnerCppToC(CefTaskRunner* cls)
: CefCppToC<CefTaskRunnerCppToC, CefTaskRunner, cef_task_runner_t>(cls) {
struct_.struct_.is_same = task_runner_is_same;
struct_.struct_.belongs_to_current_thread =
task_runner_belongs_to_current_thread;
struct_.struct_.belongs_to_thread = task_runner_belongs_to_thread;
struct_.struct_.post_task = task_runner_post_task;
struct_.struct_.post_delayed_task = task_runner_post_delayed_task;
}
#ifndef NDEBUG
template<> long CefCppToC<CefTaskRunnerCppToC, CefTaskRunner,
cef_task_runner_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,36 @@
// Copyright (c) 2013 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. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_
#pragma once
#ifndef BUILDING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
#else // BUILDING_CEF_SHARED
#include "include/cef_task.h"
#include "include/capi/cef_task_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 CefTaskRunnerCppToC
: public CefCppToC<CefTaskRunnerCppToC, CefTaskRunner, cef_task_runner_t> {
public:
explicit CefTaskRunnerCppToC(CefTaskRunner* cls);
virtual ~CefTaskRunnerCppToC() {}
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_TASK_RUNNER_CPPTOC_H_

View File

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_cpptoc.h"
#include "libcef_dll/cpptoc/task_runner_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
@ -52,6 +53,22 @@ CEF_EXPORT int cef_v8context_in_context() {
// MEMBER FUNCTIONS - Body may be edited by hand.
cef_task_runner_t* CEF_CALLBACK v8context_get_task_runner(
struct _cef_v8context_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefTaskRunner> _retval = CefV8ContextCppToC::Get(
self)->GetTaskRunner();
// Return type: refptr_same
return CefTaskRunnerCppToC::Wrap(_retval);
}
int CEF_CALLBACK v8context_is_valid(struct _cef_v8context_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -226,6 +243,7 @@ int CEF_CALLBACK v8context_eval(struct _cef_v8context_t* self,
CefV8ContextCppToC::CefV8ContextCppToC(CefV8Context* cls)
: CefCppToC<CefV8ContextCppToC, CefV8Context, cef_v8context_t>(cls) {
struct_.struct_.get_task_runner = v8context_get_task_runner;
struct_.struct_.is_valid = v8context_is_valid;
struct_.struct_.get_browser = v8context_get_browser;
struct_.struct_.get_frame = v8context_get_frame;

View File

@ -214,6 +214,87 @@ void CefRenderProcessHandlerCToCpp::OnUncaughtException(
CefV8StackTraceCppToC::Wrap(stackTrace));
}
void CefRenderProcessHandlerCToCpp::OnWorkerContextCreated(int worker_id,
const CefString& url, CefRefPtr<CefV8Context> context) {
if (CEF_MEMBER_MISSING(struct_, on_worker_context_created))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: url; type: string_byref_const
DCHECK(!url.empty());
if (url.empty())
return;
// Verify param: context; type: refptr_diff
DCHECK(context.get());
if (!context.get())
return;
// Execute
struct_->on_worker_context_created(struct_,
worker_id,
url.GetStruct(),
CefV8ContextCppToC::Wrap(context));
}
void CefRenderProcessHandlerCToCpp::OnWorkerContextReleased(int worker_id,
const CefString& url, CefRefPtr<CefV8Context> context) {
if (CEF_MEMBER_MISSING(struct_, on_worker_context_released))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: url; type: string_byref_const
DCHECK(!url.empty());
if (url.empty())
return;
// Verify param: context; type: refptr_diff
DCHECK(context.get());
if (!context.get())
return;
// Execute
struct_->on_worker_context_released(struct_,
worker_id,
url.GetStruct(),
CefV8ContextCppToC::Wrap(context));
}
void CefRenderProcessHandlerCToCpp::OnWorkerUncaughtException(int worker_id,
const CefString& url, CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
if (CEF_MEMBER_MISSING(struct_, on_worker_uncaught_exception))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: url; type: string_byref_const
DCHECK(!url.empty());
if (url.empty())
return;
// Verify param: context; type: refptr_diff
DCHECK(context.get());
if (!context.get())
return;
// Verify param: exception; type: refptr_diff
DCHECK(exception.get());
if (!exception.get())
return;
// Verify param: stackTrace; type: refptr_diff
DCHECK(stackTrace.get());
if (!stackTrace.get())
return;
// Execute
struct_->on_worker_uncaught_exception(struct_,
worker_id,
url.GetStruct(),
CefV8ContextCppToC::Wrap(context),
CefV8ExceptionCppToC::Wrap(exception),
CefV8StackTraceCppToC::Wrap(stackTrace));
}
void CefRenderProcessHandlerCToCpp::OnFocusedNodeChanged(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {

View File

@ -50,6 +50,13 @@ class CefRenderProcessHandlerCToCpp
CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
virtual void OnWorkerContextCreated(int worker_id, const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnWorkerContextReleased(int worker_id, const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnWorkerUncaughtException(int worker_id, const CefString& url,
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE;
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefDOMNode> node) OVERRIDE;
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,

View File

@ -15,15 +15,14 @@
// VIRTUAL METHODS - Body may be edited by hand.
void CefTaskCToCpp::Execute(CefThreadId threadId) {
void CefTaskCToCpp::Execute() {
if (CEF_MEMBER_MISSING(struct_, execute))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
struct_->execute(struct_,
threadId);
struct_->execute(struct_);
}

View File

@ -32,7 +32,7 @@ class CefTaskCToCpp
virtual ~CefTaskCToCpp() {}
// CefTask methods
virtual void Execute(CefThreadId threadId) OVERRIDE;
virtual void Execute() OVERRIDE;
};
#endif // BUILDING_CEF_SHARED

View File

@ -0,0 +1,134 @@
// Copyright (c) 2013 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. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#include "libcef_dll/cpptoc/task_cpptoc.h"
#include "libcef_dll/ctocpp/task_runner_ctocpp.h"
// STATIC METHODS - Body may be edited by hand.
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForCurrentThread() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_task_runner_t* _retval = cef_task_runner_get_for_current_thread();
// Return type: refptr_same
return CefTaskRunnerCToCpp::Wrap(_retval);
}
CefRefPtr<CefTaskRunner> CefTaskRunner::GetForThread(CefThreadId threadId) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_task_runner_t* _retval = cef_task_runner_get_for_thread(
threadId);
// Return type: refptr_same
return CefTaskRunnerCToCpp::Wrap(_retval);
}
// VIRTUAL METHODS - Body may be edited by hand.
bool CefTaskRunnerCToCpp::IsSame(CefRefPtr<CefTaskRunner> that) {
if (CEF_MEMBER_MISSING(struct_, is_same))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: that; type: refptr_same
DCHECK(that.get());
if (!that.get())
return false;
// Execute
int _retval = struct_->is_same(struct_,
CefTaskRunnerCToCpp::Unwrap(that));
// Return type: bool
return _retval?true:false;
}
bool CefTaskRunnerCToCpp::BelongsToCurrentThread() {
if (CEF_MEMBER_MISSING(struct_, belongs_to_current_thread))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->belongs_to_current_thread(struct_);
// Return type: bool
return _retval?true:false;
}
bool CefTaskRunnerCToCpp::BelongsToThread(CefThreadId threadId) {
if (CEF_MEMBER_MISSING(struct_, belongs_to_thread))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = struct_->belongs_to_thread(struct_,
threadId);
// Return type: bool
return _retval?true:false;
}
bool CefTaskRunnerCToCpp::PostTask(CefRefPtr<CefTask> task) {
if (CEF_MEMBER_MISSING(struct_, post_task))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: task; type: refptr_diff
DCHECK(task.get());
if (!task.get())
return false;
// Execute
int _retval = struct_->post_task(struct_,
CefTaskCppToC::Wrap(task));
// Return type: bool
return _retval?true:false;
}
bool CefTaskRunnerCToCpp::PostDelayedTask(CefRefPtr<CefTask> task,
int64 delay_ms) {
if (CEF_MEMBER_MISSING(struct_, post_delayed_task))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: task; type: refptr_diff
DCHECK(task.get());
if (!task.get())
return false;
// Execute
int _retval = struct_->post_delayed_task(struct_,
CefTaskCppToC::Wrap(task),
delay_ms);
// Return type: bool
return _retval?true:false;
}
#ifndef NDEBUG
template<> long CefCToCpp<CefTaskRunnerCToCpp, CefTaskRunner,
cef_task_runner_t>::DebugObjCt = 0;
#endif

View File

@ -0,0 +1,45 @@
// Copyright (c) 2013 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. If making changes by
// hand only do so within the body of existing method and function
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_
#pragma once
#ifndef USING_CEF_SHARED
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
#else // USING_CEF_SHARED
#include "include/cef_task.h"
#include "include/capi/cef_task_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 CefTaskRunnerCToCpp
: public CefCToCpp<CefTaskRunnerCToCpp, CefTaskRunner, cef_task_runner_t> {
public:
explicit CefTaskRunnerCToCpp(cef_task_runner_t* str)
: CefCToCpp<CefTaskRunnerCToCpp, CefTaskRunner, cef_task_runner_t>(str) {}
virtual ~CefTaskRunnerCToCpp() {}
// CefTaskRunner methods
virtual bool IsSame(CefRefPtr<CefTaskRunner> that) OVERRIDE;
virtual bool BelongsToCurrentThread() OVERRIDE;
virtual bool BelongsToThread(CefThreadId threadId) OVERRIDE;
virtual bool PostTask(CefRefPtr<CefTask> task) OVERRIDE;
virtual bool PostDelayedTask(CefRefPtr<CefTask> task,
int64 delay_ms) OVERRIDE;
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_TASK_RUNNER_CTOCPP_H_

View File

@ -12,6 +12,7 @@
#include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_ctocpp.h"
#include "libcef_dll/ctocpp/task_runner_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
@ -52,6 +53,19 @@ bool CefV8Context::InContext() {
// VIRTUAL METHODS - Body may be edited by hand.
CefRefPtr<CefTaskRunner> CefV8ContextCToCpp::GetTaskRunner() {
if (CEF_MEMBER_MISSING(struct_, get_task_runner))
return NULL;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_task_runner_t* _retval = struct_->get_task_runner(struct_);
// Return type: refptr_same
return CefTaskRunnerCToCpp::Wrap(_retval);
}
bool CefV8ContextCToCpp::IsValid() {
if (CEF_MEMBER_MISSING(struct_, is_valid))
return false;

View File

@ -32,6 +32,7 @@ class CefV8ContextCToCpp
virtual ~CefV8ContextCToCpp() {}
// CefV8Context methods
virtual CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
virtual bool IsValid() OVERRIDE;
virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
virtual CefRefPtr<CefFrame> GetFrame() OVERRIDE;

View File

@ -58,6 +58,7 @@
#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
#include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
#include "libcef_dll/cpptoc/task_runner_cpptoc.h"
#include "libcef_dll/cpptoc/urlrequest_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
@ -221,6 +222,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK_EQ(CefStreamWriterCppToC::DebugObjCt, 0);
DCHECK_EQ(CefStringVisitorCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTaskCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTaskRunnerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefTraceClientCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestClientCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestCppToC::DebugObjCt, 0);

View File

@ -93,6 +93,7 @@
#include "libcef_dll/ctocpp/scheme_registrar_ctocpp.h"
#include "libcef_dll/ctocpp/stream_reader_ctocpp.h"
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/ctocpp/task_runner_ctocpp.h"
#include "libcef_dll/ctocpp/urlrequest_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
@ -213,6 +214,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK_EQ(CefStreamWriterCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefStringVisitorCppToC::DebugObjCt, 0);
DCHECK_EQ(CefTaskCppToC::DebugObjCt, 0);
DCHECK_EQ(CefTaskRunnerCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTraceClientCppToC::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestClientCppToC::DebugObjCt, 0);

View File

@ -26,6 +26,11 @@ patches = [
'name': 'zlib',
'path': '../third_party/zlib/',
},
{
# http://code.google.com/p/chromiumembedded/issues/detail?id=451
'name': 'webkit_451',
'path': '../third_party/WebKit/Source/',
},
{
# http://code.google.com/p/chromiumembedded/issues/detail?id=364
'name': 'spi_webcore_364',

View File

@ -0,0 +1,263 @@
Index: Platform/chromium/public/WebWorkerScriptObserver.h
===================================================================
--- Platform/chromium/public/WebWorkerScriptObserver.h (revision 0)
+++ Platform/chromium/public/WebWorkerScriptObserver.h (revision 0)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WebWorkerScriptObserver_h
+#define WebWorkerScriptObserver_h
+
+#include <v8.h>
+
+namespace WebKit {
+
+ class WebURL;
+ class WebWorkerRunLoop;
+
+ class WebWorkerScriptObserver {
+ public:
+ // Notifies that a new script context has been created for a worker.
+ // This will be called only once per worker context.
+ virtual void didCreateWorkerScriptContext(const WebWorkerRunLoop&, const WebURL&, v8::Handle<v8::Context>) { }
+
+ // WebKit is about to release its reference to a v8 context for a worker.
+ virtual void willReleaseWorkerScriptContext(const WebWorkerRunLoop&, const WebURL&, v8::Handle<v8::Context>) { }
+
+ protected:
+ virtual ~WebWorkerScriptObserver() { }
+ };
+
+} // namespace WebKit
+
+#endif
Property changes on: Platform\chromium\public\WebWorkerScriptObserver.h
___________________________________________________________________
Added: svn:eol-style
+ LF
Index: WebCore/bindings/v8/WorkerScriptController.cpp
===================================================================
--- WebCore/bindings/v8/WorkerScriptController.cpp (revision 136040)
+++ WebCore/bindings/v8/WorkerScriptController.cpp (working copy)
@@ -50,11 +50,23 @@
#if PLATFORM(CHROMIUM)
#include <public/Platform.h>
+#include <public/WebURL.h>
#include <public/WebWorkerRunLoop.h>
+#include <public/WebWorkerScriptObserver.h>
#endif
namespace WebCore {
+namespace {
+
+static Vector<WebKit::WebWorkerScriptObserver*>& observerVector()
+{
+ AtomicallyInitializedStatic(Vector<WebKit::WebWorkerScriptObserver*>&, observers = *new Vector<WebKit::WebWorkerScriptObserver*>);
+ return observers;
+}
+
+} // namespace
+
WorkerScriptController::WorkerScriptController(WorkerContext* workerContext)
: m_workerContext(workerContext)
, m_isolate(v8::Isolate::New())
@@ -72,6 +84,8 @@
WorkerScriptController::~WorkerScriptController()
{
m_domDataStore.clear();
+ if (!m_context.isEmpty())
+ notifyWillReleaseWorkerScriptContext();
#if PLATFORM(CHROMIUM)
// The corresponding call to didStartWorkerRunLoop is in
// WorkerThread::workerThread().
@@ -133,6 +147,8 @@
v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype());
globalObject->SetPrototype(jsWorkerContext);
+ notifyDidCreateWorkerScriptContext();
+
return true;
}
@@ -256,6 +272,39 @@
return workerContext->script();
}
+void WorkerScriptController::addObserver(WebKit::WebWorkerScriptObserver* observer)
+{
+ if (WebCore::WorkerThread::workerThreadCount() > 0)
+ return;
+
+ observerVector().append(observer);
+}
+
+void WorkerScriptController::removeObserver(WebKit::WebWorkerScriptObserver* observer)
+{
+ if (WebCore::WorkerThread::workerThreadCount() > 0)
+ return;
+
+ Vector<WebKit::WebWorkerScriptObserver*>& observers = observerVector();
+ size_t pos = observers.find(observer);
+ if (pos != notFound)
+ observers.remove(pos);
+}
+
+void WorkerScriptController::notifyDidCreateWorkerScriptContext()
+{
+ const Vector<WebKit::WebWorkerScriptObserver*>& observers = observerVector();
+ for (Vector<WebKit::WebWorkerScriptObserver*>::const_iterator i = observers.begin(); i != observers.end(); ++i)
+ (*i)->didCreateWorkerScriptContext(WebKit::WebWorkerRunLoop(&m_workerContext->thread()->runLoop()), m_workerContext->url(), m_context.get());
+}
+
+void WorkerScriptController::notifyWillReleaseWorkerScriptContext()
+{
+ const Vector<WebKit::WebWorkerScriptObserver*>& observers = observerVector();
+ for (Vector<WebKit::WebWorkerScriptObserver*>::const_iterator i = observers.begin(); i != observers.end(); ++i)
+ (*i)->willReleaseWorkerScriptContext(WebKit::WebWorkerRunLoop(&m_workerContext->thread()->runLoop()), m_workerContext->url(), m_context.get());
+}
+
} // namespace WebCore
#endif // ENABLE(WORKERS)
Index: WebCore/bindings/v8/WorkerScriptController.h
===================================================================
--- WebCore/bindings/v8/WorkerScriptController.h (revision 136040)
+++ WebCore/bindings/v8/WorkerScriptController.h (working copy)
@@ -40,6 +40,10 @@
#include <wtf/Threading.h>
#include <wtf/text/TextPosition.h>
+namespace WebKit {
+class WebWorkerScriptObserver;
+}
+
namespace WebCore {
class ScriptSourceCode;
@@ -95,10 +99,17 @@
// Returns a local handle of the context.
v8::Local<v8::Context> context() { return v8::Local<v8::Context>::New(m_context.get()); }
+ // Add or remove an observer. Can only be called while no WebWorkers exist.
+ static void addObserver(WebKit::WebWorkerScriptObserver*);
+ static void removeObserver(WebKit::WebWorkerScriptObserver*);
+
private:
bool initializeContextIfNeeded();
void disposeContext();
+ void notifyDidCreateWorkerScriptContext();
+ void notifyWillReleaseWorkerScriptContext();
+
WorkerContext* m_workerContext;
v8::Isolate* m_isolate;
ScopedPersistent<v8::Context> m_context;
Index: WebKit/chromium/public/WebWorkerInfo.h
===================================================================
--- WebKit/chromium/public/WebWorkerInfo.h (revision 136040)
+++ WebKit/chromium/public/WebWorkerInfo.h (working copy)
@@ -35,9 +35,15 @@
namespace WebKit {
+class WebWorkerScriptObserver;
+
class WebWorkerInfo {
public:
WEBKIT_EXPORT static unsigned dedicatedWorkerCount();
+
+ // Add or remove an observer. Can only be called while no WebWorkers exist.
+ WEBKIT_EXPORT static void addScriptObserver(WebWorkerScriptObserver*);
+ WEBKIT_EXPORT static void removeScriptObserver(WebWorkerScriptObserver*);
};
}
Index: WebKit/chromium/public/WebWorkerScriptObserver.h
===================================================================
--- WebKit/chromium/public/WebWorkerScriptObserver.h (revision 0)
+++ WebKit/chromium/public/WebWorkerScriptObserver.h (revision 0)
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "../../../Platform/chromium/public/WebWorkerScriptObserver.h"
Property changes on: WebKit\chromium\public\WebWorkerScriptObserver.h
___________________________________________________________________
Added: svn:eol-style
+ LF
Index: WebKit/chromium/src/WebWorkerInfo.cpp
===================================================================
--- WebKit/chromium/src/WebWorkerInfo.cpp (revision 136040)
+++ WebKit/chromium/src/WebWorkerInfo.cpp (working copy)
@@ -31,6 +31,7 @@
#include "config.h"
#include "WebWorkerInfo.h"
+#include "WorkerScriptController.h"
#include "WorkerThread.h"
namespace WebKit {
@@ -40,4 +41,14 @@
return WebCore::WorkerThread::workerThreadCount();
}
+void WebWorkerInfo::addScriptObserver(WebWorkerScriptObserver* observer)
+{
+ WebCore::WorkerScriptController::addObserver(observer);
}
+
+void WebWorkerInfo::removeScriptObserver(WebWorkerScriptObserver* observer)
+{
+ WebCore::WorkerScriptController::removeObserver(observer);
+}
+
+}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -215,7 +215,6 @@ void ClientApp::OnContextInitialized() {
ASSERT(manager.get());
manager->SetSupportedSchemes(cookieable_schemes_);
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it)
(*it)->OnContextInitialized(this);
@ -223,7 +222,6 @@ void ClientApp::OnContextInitialized() {
void ClientApp::OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it)
(*it)->OnBeforeChildProcessLaunch(this, command_line);
@ -231,7 +229,6 @@ void ClientApp::OnBeforeChildProcessLaunch(
void ClientApp::OnRenderProcessThreadCreated(
CefRefPtr<CefListValue> extra_info) {
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it)
(*it)->OnRenderProcessThreadCreated(this, extra_info);
@ -245,7 +242,6 @@ void ClientApp::GetProxyForUrl(const CefString& url,
}
void ClientApp::OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnRenderThreadCreated(this, extra_info);
@ -274,21 +270,18 @@ void ClientApp::OnWebKitInitialized() {
CefRegisterExtension("v8/app", app_code,
new ClientAppExtensionHandler(this));
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnWebKitInitialized(this);
}
void ClientApp::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnBrowserCreated(this, browser);
}
void ClientApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnBrowserDestroyed(this, browser);
@ -299,7 +292,6 @@ bool ClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefRequest> request,
NavigationType navigation_type,
bool is_redirect) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) {
if ((*it)->OnBeforeNavigation(this, browser, frame, request,
@ -312,18 +304,16 @@ bool ClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
}
void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
// Execute delegate callbacks.
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnContextCreated(this, browser, frame, context);
}
void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
// Execute delegate callbacks.
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnContextReleased(this, browser, frame, context);
@ -342,11 +332,10 @@ void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
}
void ClientApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
// Execute delegate callbacks.
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) {
(*it)->OnUncaughtException(this, browser, frame, context, exception,
@ -354,10 +343,38 @@ void ClientApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
}
}
void ClientApp::OnWorkerContextCreated(int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnWorkerContextCreated(this, worker_id, url, context);
}
void ClientApp::OnWorkerContextReleased(int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnWorkerContextReleased(this, worker_id, url, context);
}
void ClientApp::OnWorkerUncaughtException(
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) {
(*it)->OnWorkerUncaughtException(this, worker_id, url, context, exception,
stackTrace);
}
}
void ClientApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnFocusedNodeChanged(this, browser, frame, node);
@ -371,7 +388,6 @@ bool ClientApp::OnProcessMessageReceived(
bool handled = false;
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end() && !handled; ++it) {
handled = (*it)->OnProcessMessageReceived(this, browser, source_process,

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -20,62 +20,38 @@ class ClientApp : public CefApp,
public:
// Interface for browser delegates. All BrowserDelegates must be returned via
// CreateBrowserDelegates. Do not perform work in the BrowserDelegate
// constructor.
// constructor. See CefBrowserProcessHandler for documentation.
class BrowserDelegate : public virtual CefBase {
public:
// Called on the browser process UI thread immediately after the CEF context
// has been initialized.
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {
}
virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {}
// Called on the browser process IO thread before a child process is
// launched. Provides an opportunity to modify the child process command
// line. Do not keep a reference to |command_line| outside of this method.
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<ClientApp> app,
CefRefPtr<CefCommandLine> command_line) {
}
CefRefPtr<CefCommandLine> command_line) {}
// Called on the browser process IO thread after the main thread has been
// created for a new render process. Provides an opportunity to specify
// extra information that will be passed to
// CefRenderProcessHandler::OnRenderThreadCreated() in the render process.
// Do not keep a reference to |extra_info| outside of this method.
virtual void OnRenderProcessThreadCreated(
CefRefPtr<ClientApp> app,
CefRefPtr<CefListValue> extra_info) {
}
CefRefPtr<CefListValue> extra_info) {}
};
typedef std::set<CefRefPtr<BrowserDelegate> > BrowserDelegateSet;
// Interface for renderer delegates. All RenderDelegates must be returned via
// CreateRenderDelegates. Do not perform work in the RenderDelegate
// constructor.
// constructor. See CefRenderProcessHandler for documentation.
class RenderDelegate : public virtual CefBase {
public:
// Called after the render process main thread has been created.
virtual void OnRenderThreadCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefListValue> extra_info) {
}
CefRefPtr<CefListValue> extra_info) {}
// Called when WebKit is initialized. Used to register V8 extensions.
virtual void OnWebKitInitialized(CefRefPtr<ClientApp> app) {
}
virtual void OnWebKitInitialized(CefRefPtr<ClientApp> app) {}
// Called after a browser has been created.
virtual void OnBrowserCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser) {
}
CefRefPtr<CefBrowser> browser) {}
// Called before a browser is destroyed.
virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser) {
}
CefRefPtr<CefBrowser> browser) {}
// Called before browser navigation. Return true to cancel the navigation or
// false to allow the navigation to proceed. The |request| object cannot be
// modified in this callback.
virtual bool OnBeforeNavigation(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@ -85,40 +61,45 @@ class ClientApp : public CefApp,
return false;
}
// Called when a V8 context is created. Used to create V8 window bindings
// and set message callbacks. RenderDelegates should check for unique URLs
// to avoid interfering with each other.
virtual void OnContextCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
}
CefRefPtr<CefV8Context> context) {}
// Called when a V8 context is released. Used to clean up V8 window
// bindings. RenderDelegates should check for unique URLs to avoid
// interfering with each other.
virtual void OnContextReleased(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) {
}
CefRefPtr<CefV8Context> context) {}
// Global V8 exception handler, disabled by default, to enable set
// CefSettings.uncaught_exception_stack_size > 0.
virtual void OnUncaughtException(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {
}
CefRefPtr<CefV8StackTrace> stackTrace) {}
virtual void OnWorkerContextCreated(CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {}
virtual void OnWorkerContextReleased(CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) {}
virtual void OnWorkerUncaughtException(
CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {}
// Called when the focused node in a frame has changed.
virtual void OnFocusedNodeChanged(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {
}
CefRefPtr<CefDOMNode> node) {}
// Called when a process message is received. Return true if the message was
// handled and should not be passed on to other handlers. RenderDelegates
@ -218,6 +199,21 @@ class ClientApp : public CefApp,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace)
OVERRIDE;
virtual void OnWorkerContextCreated(
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnWorkerContextReleased(
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnWorkerUncaughtException(
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace)
OVERRIDE;
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE;

View File

@ -0,0 +1,202 @@
// Copyright (c) 2013 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.
#include "include/cef_runnable.h"
#include "include/cef_task.h"
#include "tests/unittests/test_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
void GetForCurrentThread(bool* ran_test) {
// Currently on the UI thread.
CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForCurrentThread();
EXPECT_TRUE(runner.get());
EXPECT_TRUE(runner->BelongsToCurrentThread());
EXPECT_TRUE(runner->BelongsToThread(TID_UI));
EXPECT_FALSE(runner->BelongsToThread(TID_IO));
EXPECT_TRUE(runner->IsSame(runner));
CefRefPtr<CefTaskRunner> runner2 = CefTaskRunner::GetForCurrentThread();
EXPECT_TRUE(runner2.get());
EXPECT_TRUE(runner->IsSame(runner2));
EXPECT_TRUE(runner2->IsSame(runner));
// Not on the IO thread.
CefRefPtr<CefTaskRunner> runner3 = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner3.get());
EXPECT_FALSE(runner->IsSame(runner3));
EXPECT_FALSE(runner3->IsSame(runner));
*ran_test = true;
}
void GetForThread(bool* ran_test) {
// Currently on the UI thread.
CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner.get());
EXPECT_FALSE(runner->BelongsToCurrentThread());
EXPECT_TRUE(runner->BelongsToThread(TID_IO));
EXPECT_FALSE(runner->BelongsToThread(TID_UI));
EXPECT_TRUE(runner->IsSame(runner));
CefRefPtr<CefTaskRunner> runner2 = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner2.get());
EXPECT_TRUE(runner->IsSame(runner2));
EXPECT_TRUE(runner2->IsSame(runner));
CefRefPtr<CefTaskRunner> runner3 = CefTaskRunner::GetForThread(TID_UI);
EXPECT_TRUE(runner3.get());
EXPECT_FALSE(runner->IsSame(runner3));
EXPECT_FALSE(runner3->IsSame(runner));
*ran_test = true;
}
void PostTaskEvent1(bool* got_it, CefRefPtr<CefTaskRunner> runner) {
// Currently on the IO thread.
EXPECT_TRUE(runner->BelongsToCurrentThread());
EXPECT_TRUE(runner->BelongsToThread(TID_IO));
EXPECT_FALSE(runner->BelongsToThread(TID_UI));
// Current thread should be the IO thread.
CefRefPtr<CefTaskRunner> runner2 = CefTaskRunner::GetForCurrentThread();
EXPECT_TRUE(runner2.get());
EXPECT_TRUE(runner2->BelongsToCurrentThread());
EXPECT_TRUE(runner2->BelongsToThread(TID_IO));
EXPECT_FALSE(runner2->BelongsToThread(TID_UI));
EXPECT_TRUE(runner->IsSame(runner2));
EXPECT_TRUE(runner2->IsSame(runner));
// Current thread should be the IO thread.
CefRefPtr<CefTaskRunner> runner3 = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner3.get());
EXPECT_TRUE(runner3->BelongsToCurrentThread());
EXPECT_TRUE(runner3->BelongsToThread(TID_IO));
EXPECT_FALSE(runner3->BelongsToThread(TID_UI));
EXPECT_TRUE(runner->IsSame(runner3));
EXPECT_TRUE(runner3->IsSame(runner));
// Current thread should not be the UI thread.
CefRefPtr<CefTaskRunner> runner4 = CefTaskRunner::GetForThread(TID_UI);
EXPECT_TRUE(runner4.get());
EXPECT_FALSE(runner4->BelongsToCurrentThread());
EXPECT_FALSE(runner4->BelongsToThread(TID_IO));
EXPECT_TRUE(runner4->BelongsToThread(TID_UI));
EXPECT_FALSE(runner->IsSame(runner4));
EXPECT_FALSE(runner4->IsSame(runner));
*got_it = true;
}
void PostTask1(bool* ran_test) {
// Currently on the UI thread.
CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner.get());
EXPECT_FALSE(runner->BelongsToCurrentThread());
EXPECT_TRUE(runner->BelongsToThread(TID_IO));
bool got_it = false;
runner->PostTask(NewCefRunnableFunction(&PostTaskEvent1, &got_it, runner));
WaitForThread(runner);
EXPECT_TRUE(got_it);
*ran_test = true;
}
void PostDelayedTask1(bool* ran_test) {
// Currently on the UI thread.
CefRefPtr<CefTaskRunner> runner = CefTaskRunner::GetForThread(TID_IO);
EXPECT_TRUE(runner.get());
EXPECT_FALSE(runner->BelongsToCurrentThread());
EXPECT_TRUE(runner->BelongsToThread(TID_IO));
bool got_it = false;
runner->PostDelayedTask(
NewCefRunnableFunction(&PostTaskEvent1, &got_it, runner), 0);
WaitForThread(runner);
EXPECT_TRUE(got_it);
*ran_test = true;
}
void PostTaskEvent2(bool* got_it) {
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
EXPECT_FALSE(CefCurrentlyOn(TID_UI));
*got_it = true;
}
void PostTask2(bool* ran_test) {
// Currently on the UI thread.
EXPECT_FALSE(CefCurrentlyOn(TID_IO));
bool got_it = false;
CefPostTask(TID_IO, NewCefRunnableFunction(&PostTaskEvent2, &got_it));
WaitForThread(TID_IO);
EXPECT_TRUE(got_it);
*ran_test = true;
}
void PostDelayedTask2(bool* ran_test) {
// Currently on the UI thread.
EXPECT_FALSE(CefCurrentlyOn(TID_IO));
bool got_it = false;
CefPostDelayedTask(TID_IO,
NewCefRunnableFunction(&PostTaskEvent2, &got_it), 0);
WaitForThread(TID_IO);
EXPECT_TRUE(got_it);
*ran_test = true;
}
} // namespace
TEST(TaskTest, GetForCurrentThread) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&GetForCurrentThread, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}
TEST(TaskTest, GetForThread) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&GetForThread, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}
TEST(TaskTest, PostTask1) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&PostTask1, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}
TEST(TaskTest, PostDelayedTask1) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&PostDelayedTask2, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}
TEST(TaskTest, PostTask2) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&PostTask2, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}
TEST(TaskTest, PostDelayedTask2) {
bool ran_test = false;
CefPostTask(TID_UI, NewCefRunnableFunction(&PostDelayedTask2, &ran_test));
WaitForThread(TID_UI);
EXPECT_TRUE(ran_test);
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -130,6 +130,12 @@ void WaitForThread(CefThreadId thread_id) {
event.Wait();
}
void WaitForThread(CefRefPtr<CefTaskRunner> task_runner) {
base::WaitableEvent event(true, false);
task_runner->PostTask(NewCefRunnableFunction(&NotifyEvent, &event));
event.Wait();
}
bool TestFailed() {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();

View File

@ -1,4 +1,4 @@
// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -123,6 +123,7 @@ class TestHandler : public CefClient,
// Post a task to the specified thread and wait for the task to execute as
// indication that all previously pending tasks on that thread have completed.
void WaitForThread(CefThreadId thread_id);
void WaitForThread(CefRefPtr<CefTaskRunner> task_runner);
#define WaitForIOThread() WaitForThread(TID_IO)
#define WaitForUIThread() WaitForThread(TID_UI)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -69,7 +69,7 @@ class BeginTracingTask : public CefTask {
: client_(client) {
}
virtual void Execute(CefThreadId threadId) OVERRIDE {
virtual void Execute() OVERRIDE {
EXPECT_TRUE(CefBeginTracing(client_, kTraceTestCategory));
}
@ -86,7 +86,7 @@ class EndTracingTask : public CefTask {
public:
EndTracingTask() {}
virtual void Execute(CefThreadId threadId) OVERRIDE {
virtual void Execute() OVERRIDE {
EXPECT_TRUE(CefEndTracingAsync());
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -27,6 +27,8 @@ const char kV8ContextChildTestUrl[] = "http://tests/V8Test.ContextChildTest";
const char kV8NavTestUrl[] = "http://tests/V8Test.NavTest";
const char kV8OnUncaughtExceptionTestUrl[] =
"http://tests/V8Test.OnUncaughtException";
const char kV8WorkerParentTestUrl[] = "http://tests/V8Test.WorkerParent";
const char kV8WorkerTestUrl[] = "http://tests/V8Test.Worker.js";
const char kV8TestMsg[] = "V8Test.Test";
const char kV8TestCmdArg[] = "v8-test";
const char kV8DevToolsURLMsg[] = "V8Test.DevToolsURL";
@ -68,9 +70,12 @@ enum V8TestMode {
V8TEST_CONTEXT_INVALID,
V8TEST_BINDING,
V8TEST_STACK_TRACE,
V8TEST_EXTENSION,
V8TEST_ON_UNCAUGHT_EXCEPTION,
V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS,
V8TEST_EXTENSION,
V8TEST_WORKER_BINDING,
V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION,
V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS,
};
// Set to the current test being run in the browser process. Will always be
@ -214,11 +219,16 @@ class V8RendererTest : public ClientApp::RenderDelegate {
RunStackTraceTest();
break;
case V8TEST_ON_UNCAUGHT_EXCEPTION:
case V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION:
RunOnUncaughtExceptionTest();
break;
case V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS:
case V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS:
RunOnUncaughtExceptionDevToolsTest();
break;
case V8TEST_WORKER_BINDING:
// The test is triggered in OnWorkerContextCreated().
break;
default:
// Was a startup test.
EXPECT_TRUE(startup_test_success_);
@ -1588,32 +1598,6 @@ class V8RendererTest : public ClientApp::RenderDelegate {
"window.open('" + devtools_url_ + "');", "about:blank", 0);
}
void OnUncaughtException(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
EXPECT_TRUE(test_context_->IsSame(context));
EXPECT_STREQ("Uncaught ReferenceError: asd is not defined",
exception->GetMessage().ToString().c_str());
std::ostringstream stackFormatted;
for (int i = 0; i < stackTrace->GetFrameCount(); ++i) {
stackFormatted << "at "
<< stackTrace->GetFrame(i)->GetFunctionName().ToString()
<< "() in " << stackTrace->GetFrame(i)->GetScriptName().ToString()
<< " on line " << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
}
const char* stackFormattedShouldBe =
"at test2() in http://tests/V8Test.OnUncaughtException on line 3\n"
"at test() in http://tests/V8Test.OnUncaughtException on line 2\n";
EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
DestroyTest();
}
}
// Test execution of a native function when the extension is loaded.
void RunExtensionTest() {
std::string code = "native function v8_extension_test();"
@ -1665,7 +1649,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
if (test_mode_ == V8TEST_NONE)
return;
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (browser_.get() == NULL) {
app_ = app;
browser_ = browser;
@ -1758,12 +1743,217 @@ class V8RendererTest : public ClientApp::RenderDelegate {
}
}
void OnUncaughtException(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE {
if (test_mode_ == V8TEST_NONE)
return;
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION ||
test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
EXPECT_TRUE(test_context_->IsSame(context));
EXPECT_STREQ("Uncaught ReferenceError: asd is not defined",
exception->GetMessage().ToString().c_str());
std::ostringstream stackFormatted;
for (int i = 0; i < stackTrace->GetFrameCount(); ++i) {
stackFormatted << "at "
<< stackTrace->GetFrame(i)->GetFunctionName().ToString()
<< "() in " << stackTrace->GetFrame(i)->GetScriptName().ToString()
<< " on line " << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
}
const char* stackFormattedShouldBe =
"at test2() in http://tests/V8Test.OnUncaughtException on line 3\n"
"at test() in http://tests/V8Test.OnUncaughtException on line 2\n";
EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
DestroyTest();
}
}
virtual void OnWorkerContextCreated(
CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE {
if (test_mode_ == V8TEST_NONE)
return;
EXPECT_STREQ(kV8WorkerTestUrl, url.ToString().c_str());
EXPECT_TRUE(context.get());
EXPECT_TRUE(context->IsValid());
test_context_worker_ = context;
CefRefPtr<CefTaskRunner> task_runner = context->GetTaskRunner();
EXPECT_TRUE(task_runner.get());
EXPECT_TRUE(task_runner->BelongsToCurrentThread());
test_task_runner_worker_ = task_runner;
EXPECT_FALSE(context->GetBrowser().get());
EXPECT_FALSE(context->GetFrame().get());
if (test_mode_ == V8TEST_WORKER_BINDING) {
static const char test_func[] = "run_async";
class Handler : public CefV8Handler {
public:
Handler() {}
virtual bool Execute(const CefString& name,
CefRefPtr<CefV8Value> object,
const CefV8ValueList& arguments,
CefRefPtr<CefV8Value>& retval,
CefString& exception) OVERRIDE {
EXPECT_STREQ(test_func, name.ToString().c_str());
EXPECT_EQ((size_t)1, arguments.size());
callback_ = arguments[0];
EXPECT_TRUE(callback_->IsFunction());
EXPECT_TRUE(context_->IsValid());
CefRefPtr<CefV8Context> current_context =
CefV8Context::GetCurrentContext();
EXPECT_TRUE(current_context->IsSame(context_));
CefRefPtr<CefTaskRunner> task_runner =
current_context->GetTaskRunner();
EXPECT_TRUE(task_runner.get());
EXPECT_TRUE(task_runner->BelongsToCurrentThread());
EXPECT_TRUE(task_runner->IsSame(task_runner_));
// Execute the callback asynchronously.
task_runner->PostTask(
NewCefRunnableMethod(this, &Handler::ExecCallback));
retval = CefV8Value::CreateBool(true);
return true;
}
void ExecCallback() {
EXPECT_TRUE(callback_->IsValid());
EXPECT_TRUE(context_->IsValid());
CefRefPtr<CefTaskRunner> task_runner = context_->GetTaskRunner();
EXPECT_TRUE(task_runner.get());
EXPECT_TRUE(task_runner->BelongsToCurrentThread());
EXPECT_TRUE(task_runner->IsSame(task_runner_));
CefRefPtr<CefV8Value> retval =
callback_->ExecuteFunctionWithContext(context_, NULL,
CefV8ValueList());
EXPECT_TRUE(retval.get());
EXPECT_TRUE(retval->IsValid());
EXPECT_TRUE(retval->IsBool());
EXPECT_EQ(true, retval->GetBoolValue());
callback_ = NULL;
context_ = NULL;
task_runner_ = NULL;
}
CefRefPtr<CefV8Value> callback_;
CefRefPtr<CefV8Context> context_;
CefRefPtr<CefTaskRunner> task_runner_;
IMPLEMENT_REFCOUNTING(Handler);
};
Handler* handler = new Handler();
CefRefPtr<CefV8Handler> handlerPtr(handler);
handler->context_ = context;
handler->task_runner_ = task_runner;
CefRefPtr<CefV8Value> global = context->GetGlobal();
EXPECT_TRUE(global.get());
global->SetValue(test_func,
CefV8Value::CreateFunction(test_func, handlerPtr),
V8_PROPERTY_ATTRIBUTE_NONE);
}
}
virtual void OnWorkerContextReleased(
CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context) OVERRIDE {
if (test_mode_ == V8TEST_NONE)
return;
EXPECT_STREQ(kV8WorkerTestUrl, url.ToString().c_str());
EXPECT_TRUE(context.get());
EXPECT_TRUE(context->IsValid());
CefRefPtr<CefTaskRunner> task_runner = context->GetTaskRunner();
EXPECT_TRUE(task_runner.get());
EXPECT_TRUE(task_runner->BelongsToCurrentThread());
EXPECT_TRUE(task_runner->IsSame(test_task_runner_worker_));
EXPECT_TRUE(context->IsSame(test_context_worker_));
test_context_worker_ = NULL;
test_task_runner_worker_ = NULL;
if (test_mode_ == V8TEST_WORKER_BINDING) {
// Destroy the test on the renderer thread.
CefPostTask(TID_RENDERER,
NewCefRunnableMethod(this, &V8RendererTest::DestroyTest));
}
}
void OnWorkerUncaughtException(
CefRefPtr<ClientApp> app,
int worker_id,
const CefString& url,
CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE {
if (test_mode_ == V8TEST_NONE)
return;
EXPECT_TRUE(context.get());
EXPECT_TRUE(context->IsValid());
CefRefPtr<CefTaskRunner> task_runner = context->GetTaskRunner();
EXPECT_TRUE(task_runner.get());
EXPECT_TRUE(task_runner->BelongsToCurrentThread());
EXPECT_TRUE(task_runner->IsSame(test_task_runner_worker_));
EXPECT_TRUE(context->IsSame(test_context_worker_));
if (test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
EXPECT_STREQ("Uncaught ReferenceError: asd is not defined",
exception->GetMessage().ToString().c_str());
std::ostringstream stackFormatted;
for (int i = 0; i < stackTrace->GetFrameCount(); ++i) {
stackFormatted << "at "
<< stackTrace->GetFrame(i)->GetFunctionName().ToString()
<< "() in " << stackTrace->GetFrame(i)->GetScriptName().ToString()
<< " on line " << stackTrace->GetFrame(i)->GetLineNumber() << "\n";
}
const char* stackFormattedShouldBe =
"at test2() in http://tests/V8Test.Worker.js on line 2\n"
"at test() in http://tests/V8Test.Worker.js on line 1\n";
EXPECT_STREQ(stackFormattedShouldBe, stackFormatted.str().c_str());
// Destroy the test on the renderer thread.
CefPostTask(TID_RENDERER,
NewCefRunnableMethod(this, &V8RendererTest::DestroyTest));
}
}
virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser) OVERRIDE {
if (test_mode_ == V8TEST_NONE)
return;
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (browser->IsPopup()) {
// After window destruction there is still a call to
// ScriptController::setCaptureCallStackForUncaughtExceptions(0),
@ -1782,7 +1972,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
if (test_mode_ == V8TEST_NONE)
return false;
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
EXPECT_TRUE(browser.get());
EXPECT_EQ(PID_BROWSER, source_process);
EXPECT_TRUE(message.get());
@ -1883,6 +2074,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
protected:
// Return from the test.
void DestroyTest() {
EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
if (test_mode_ == V8TEST_CONTEXT_INVALID) {
// Verify that objects related to a particular context are not valid after
// OnContextReleased is called for that context.
@ -1921,6 +2114,9 @@ class V8RendererTest : public ClientApp::RenderDelegate {
CefRefPtr<CefV8Context> test_context_;
CefRefPtr<CefV8Value> test_object_;
CefRefPtr<CefV8Context> test_context_worker_;
CefRefPtr<CefTaskRunner> test_task_runner_worker_;
// Used by startup tests to indicate success.
TrackCallback startup_test_success_;
@ -1957,6 +2153,28 @@ class V8TestHandler : public TestHandler {
"</body></html>\n",
"text/html");
CreateBrowser(kV8OnUncaughtExceptionTestUrl);
} else if (test_mode_ == V8TEST_WORKER_BINDING) {
AddResource(kV8WorkerParentTestUrl, "<html><body>"
"<script>var worker = new Worker('V8Test.Worker.js');</script>"
"</body></html>", "text/html");
AddResource(kV8WorkerTestUrl,
"function cb() { self.close(); return true; }\n"
"self.run_async(cb);",
"application/javascript");
CreateBrowser(kV8WorkerParentTestUrl);
} else if (test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
AddResource(kV8WorkerParentTestUrl, "<html><body>"
"<script>var worker = new Worker('V8Test.Worker.js');\n"
"function test() { worker.postMessage('test'); }\n"
"</script>"
"</body></html>", "text/html");
AddResource(kV8WorkerTestUrl,
"function test(){ test2(); }\n"
"function test2(){ asd(); }\n"
"self.onmessage = function(event) { self.setTimeout(test, 0); }",
"application/javascript");
CreateBrowser(kV8WorkerParentTestUrl);
} else {
EXPECT_TRUE(test_url_ != NULL);
AddResource(test_url_, "<html><body>"
@ -1968,7 +2186,8 @@ class V8TestHandler : public TestHandler {
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (test_mode_ == V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS ||
test_mode_ == V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS) {
if (browser->IsPopup()) {
EXPECT_STREQ(
GetBrowser()->GetHost()->GetDevToolsURL(true).ToString().c_str(),
@ -2083,3 +2302,7 @@ V8_TEST(StackTrace, V8TEST_STACK_TRACE);
V8_TEST(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION);
V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS);
V8_TEST(Extension, V8TEST_EXTENSION);
V8_TEST(WorkerBinding, V8TEST_WORKER_BINDING);
V8_TEST(WorkerOnUncaughtException, V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION);
V8_TEST(WorkerOnUncaughtExceptionDevTools,
V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS);

View File

@ -1,4 +1,4 @@
// Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
// Copyright (c) 2013 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.
@ -88,7 +88,7 @@ class BinaryTask : public CefTask {
data_(data),
data_size_(data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE {
virtual void Execute() OVERRIDE {
TestBinary(value_, data_, data_size_);
}
@ -295,7 +295,7 @@ class DictionaryTask : public CefTask {
binary_data_(binary_data),
binary_data_size_(binary_data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE {
virtual void Execute() OVERRIDE {
TestDictionary(value_, binary_data_, binary_data_size_);
}
@ -554,7 +554,7 @@ class ListTask : public CefTask {
binary_data_(binary_data),
binary_data_size_(binary_data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE {
virtual void Execute() OVERRIDE {
TestList(value_, binary_data_, binary_data_size_);
}