Support custom V8 bindings on WebWorker threads (issue ).

- 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

@ -256,6 +256,7 @@
'tests/unittests/stream_unittest.cc', 'tests/unittests/stream_unittest.cc',
'tests/unittests/string_unittest.cc', 'tests/unittests/string_unittest.cc',
'tests/unittests/client_app_delegates.cc', 'tests/unittests/client_app_delegates.cc',
'tests/unittests/task_unittest.cc',
'tests/unittests/test_handler.cc', 'tests/unittests/test_handler.cc',
'tests/unittests/test_handler.h', 'tests/unittests/test_handler.h',
'tests/unittests/test_suite.cc', 'tests/unittests/test_suite.cc',
@ -900,6 +901,8 @@
'libcef/common/string_multimap_impl.cc', 'libcef/common/string_multimap_impl.cc',
'libcef/common/string_types_impl.cc', 'libcef/common/string_types_impl.cc',
'libcef/common/task_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_impl.cc',
'libcef/common/time_util.h', 'libcef/common/time_util.h',
'libcef/common/tracker.cc', 'libcef/common/tracker.cc',

@ -224,6 +224,8 @@
'libcef_dll/ctocpp/string_visitor_ctocpp.h', 'libcef_dll/ctocpp/string_visitor_ctocpp.h',
'libcef_dll/ctocpp/task_ctocpp.cc', 'libcef_dll/ctocpp/task_ctocpp.cc',
'libcef_dll/ctocpp/task_ctocpp.h', '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.cc',
'libcef_dll/ctocpp/trace_client_ctocpp.h', 'libcef_dll/ctocpp/trace_client_ctocpp.h',
'libcef_dll/cpptoc/urlrequest_cpptoc.cc', 'libcef_dll/cpptoc/urlrequest_cpptoc.cc',
@ -374,6 +376,8 @@
'libcef_dll/cpptoc/string_visitor_cpptoc.h', 'libcef_dll/cpptoc/string_visitor_cpptoc.h',
'libcef_dll/cpptoc/task_cpptoc.cc', 'libcef_dll/cpptoc/task_cpptoc.cc',
'libcef_dll/cpptoc/task_cpptoc.h', '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.cc',
'libcef_dll/cpptoc/trace_client_cpptoc.h', 'libcef_dll/cpptoc/trace_client_cpptoc.h',
'libcef_dll/ctocpp/urlrequest_ctocpp.cc', 'libcef_dll/ctocpp/urlrequest_ctocpp.cc',

@ -47,7 +47,8 @@ extern "C" {
/// ///
// Structure used to implement render process callbacks. The functions of this // 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 { 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 // Called immediately after the V8 context for a frame has been created. To
// retrieve the JavaScript 'window' object use the // 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)( void (CEF_CALLBACK *on_context_created)(
struct _cef_render_process_handler_t* self, struct _cef_render_process_handler_t* self,
@ -118,8 +122,8 @@ typedef struct _cef_render_process_handler_t {
struct _cef_v8context_t* context); struct _cef_v8context_t* context);
/// ///
// Called for global uncaught exceptions. Execution of this callback is // Called for global uncaught exceptions in a frame. Execution of this
// disabled by default. To enable set // callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0. // CefSettings.uncaught_exception_stack_size > 0.
/// ///
void (CEF_CALLBACK *on_uncaught_exception)( 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_v8context_t* context, struct _cef_v8exception_t* exception,
struct _cef_v8stack_trace_t* stackTrace); 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 // 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 // be NULL if no specific node has gained focus. The node object passed to

@ -46,33 +46,33 @@ extern "C" {
/// ///
// CEF maintains multiple internal threads that are used for handling different // Returns true (1) if called on the specified thread. Equivalent to using
// types of tasks in different processes. See the cef_thread_id_t definitions in // cef_task_runner_t::GetForThread(threadId)->belongs_to_current_thread().
// 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.
/// ///
CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId); CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId);
/// ///
// Post a task for execution on the specified thread. This function may be // Post a task for execution on the specified thread. Equivalent to using
// called on any thread. It is an error to request a thread from the wrong // cef_task_runner_t::GetForThread(threadId)->PostTask(task).
// process.
/// ///
CEF_EXPORT int cef_post_task(cef_thread_id_t threadId, CEF_EXPORT int cef_post_task(cef_thread_id_t threadId,
struct _cef_task_t* task); struct _cef_task_t* task);
/// ///
// Post a task for delayed execution on the specified thread. This function may // Post a task for delayed execution on the specified thread. Equivalent to
// be called on any thread. It is an error to request a thread from the wrong // using cef_task_runner_t::GetForThread(threadId)->PostDelayedTask(task,
// process. // delay_ms).
/// ///
CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId, CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
struct _cef_task_t* task, int64 delay_ms); struct _cef_task_t* task, int64 delay_ms);
/// ///
// Implement this structure for task execution. The functions of this structure // Implement this structure for asynchronous task execution. If the task is
// may be called on any thread. // 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 { typedef struct _cef_task_t {
/// ///
@ -81,13 +81,78 @@ typedef struct _cef_task_t {
cef_base_t base; 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, void (CEF_CALLBACK *execute)(struct _cef_task_t* self);
cef_thread_id_t threadId);
} cef_task_t; } 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 #ifdef __cplusplus
} }
#endif #endif

@ -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); const cef_string_t* javascript_code, struct _cef_v8handler_t* handler);
/// ///
// Structure representing a V8 context handle. Static functions may only be // Structure representing a V8 context handle. V8 handles can only be accessed
// called on a render process thread that has entered a V8 isolate (usually the // from the thread on which they are created. Valid threads for creating a V8
// render process main thread). Non-static functions may only be called on the // handle include the render process main thread (TID_RENDERER) and WebWorker
// thread that initially returned the handle. // 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 { typedef struct _cef_v8context_t {
/// ///
@ -116,6 +117,14 @@ typedef struct _cef_v8context_t {
/// ///
cef_base_t base; 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 // 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 // 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); 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_browser_t* (CEF_CALLBACK *get_browser)(
struct _cef_v8context_t* self); 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); 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 // Structure that should be implemented to handle V8 function calls. The
// functions of this structure will only be called on a render process thread // functions of this structure will be called on the thread associated with the
// that the handler was registered on. // V8 function.
/// ///
typedef struct _cef_v8handler_t { 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 // Structure that should be implemented to handle V8 accessor calls. Accessor
// identifiers are registered by calling cef_v8value_t::set_value_byaccessor(). // identifiers are registered by calling cef_v8value_t::set_value_byaccessor().
// The functions of this structure will only be called on a render process // The functions of this structure will be called on the thread associated with
// thread that the accessor was registered on. // the V8 accessor.
/// ///
typedef struct _cef_v8accessor_t { 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 // Structure representing a V8 value handle. V8 handles can only be accessed
// on a render process thread that has entered a V8 isolate (usually the render // from the thread on which they are created. Valid threads for creating a V8
// process main thread). Non-static functions may only be called on the thread // handle include the render process main thread (TID_RENDERER) and WebWorker
// that initially returned the handle. // 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 { 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 // Structure representing a V8 stack trace handle. V8 handles can only be
// called on a render process thread that has entered a V8 isolate (usually the // accessed from the thread on which they are created. Valid threads for
// render process main thread). Non-static functions may only be called on the // creating a V8 handle include the render process main thread (TID_RENDERER)
// thread that initially returned the handle. // 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 { 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 // Structure representing a V8 stack frame handle. V8 handles can only be
// called on a render process thread that has entered a V8 isolate (usually the // accessed from the thread on which they are created. Valid threads for
// render process main thread). Non-static functions may only be called on the // creating a V8 handle include the render process main thread (TID_RENDERER)
// thread that initially returned the handle. // 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 { typedef struct _cef_v8stack_frame_t {
/// ///

@ -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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // 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 // 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)--*/ /*--cef(source=client)--*/
class CefRenderProcessHandler : public virtual CefBase { 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 // Called immediately after the V8 context for a frame has been created. To
// retrieve the JavaScript 'window' object use the CefV8Context::GetGlobal() // 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()--*/ /*--cef()--*/
virtual void OnContextCreated(CefRefPtr<CefBrowser> browser, virtual void OnContextCreated(CefRefPtr<CefBrowser> browser,
@ -116,8 +119,8 @@ class CefRenderProcessHandler : public virtual CefBase {
CefRefPtr<CefV8Context> context) {} CefRefPtr<CefV8Context> context) {}
/// ///
// Called for global uncaught exceptions. Execution of this callback is // Called for global uncaught exceptions in a frame. Execution of this
// disabled by default. To enable set // callback is disabled by default. To enable set
// CefSettings.uncaught_exception_stack_size > 0. // CefSettings.uncaught_exception_stack_size > 0.
/// ///
/*--cef()--*/ /*--cef()--*/
@ -127,6 +130,43 @@ class CefRenderProcessHandler : public virtual CefBase {
CefRefPtr<CefV8Exception> exception, CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) {} 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 // 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 // be empty if no specific node has gained focus. The node object passed to

@ -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. // 2006-2011 Google Inc. All rights reserved.
// //
// Redistribution and use in source and binary forms, with or without // Redistribution and use in source and binary forms, with or without
@ -145,7 +145,7 @@ class CefRunnableMethod : public CefTask {
traits_.ReleaseCallee(obj); traits_.ReleaseCallee(obj);
} }
virtual void Execute(CefThreadId threadId) { virtual void Execute() {
if (obj_) if (obj_)
DispatchToMethod(obj_, meth_, params_); DispatchToMethod(obj_, meth_, params_);
} }
@ -253,7 +253,7 @@ class CefRunnableFunction : public CefTask {
~CefRunnableFunction() { ~CefRunnableFunction() {
} }
virtual void Execute(CefThreadId threadId) { virtual void Execute() {
if (function_) if (function_)
DispatchToFunction(function_, params_); DispatchToFunction(function_, params_);
} }

@ -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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
@ -39,50 +39,110 @@
#include "include/cef_base.h" #include "include/cef_base.h"
class CefTask;
typedef cef_thread_id_t CefThreadId; 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 // 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 // types of tasks in different processes. The cef_thread_id_t definitions in
// cef_types.h for more information. This function will return true if called on // cef_types.h list the common CEF threads. Task runners are also available for
// the specified thread. It is an error to request a thread from the wrong // other CEF threads as appropriate (for example, V8 WebWorker threads).
// process. ///
/*--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()--*/ /*--cef()--*/
bool CefCurrentlyOn(CefThreadId threadId); bool CefCurrentlyOn(CefThreadId threadId);
/// ///
// Post a task for execution on the specified thread. This function may be // Post a task for execution on the specified thread. Equivalent to
// called on any thread. It is an error to request a thread from the wrong // using CefTaskRunner::GetForThread(threadId)->PostTask(task).
// process.
/// ///
/*--cef()--*/ /*--cef()--*/
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task); bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task);
/// ///
// Post a task for delayed execution on the specified thread. This function may // Post a task for delayed execution on the specified thread. Equivalent to
// be called on any thread. It is an error to request a thread from the wrong // using CefTaskRunner::GetForThread(threadId)->PostDelayedTask(task, delay_ms).
// process.
/// ///
/*--cef()--*/ /*--cef()--*/
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task, bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
int64 delay_ms); 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_ #endif // CEF_INCLUDE_CEF_TASK_H_

@ -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 // Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are // modification, are permitted provided that the following conditions are
@ -42,6 +42,7 @@
#include "include/cef_base.h" #include "include/cef_base.h"
#include "include/cef_browser.h" #include "include/cef_browser.h"
#include "include/cef_frame.h" #include "include/cef_frame.h"
#include "include/cef_task.h"
#include <vector> #include <vector>
class CefV8Exception; class CefV8Exception;
@ -116,10 +117,11 @@ bool CefRegisterExtension(const CefString& extension_name,
/// ///
// Class representing a V8 context handle. Static methods may only be called // Class representing a V8 context handle. V8 handles can only be accessed from
// on a render process thread that has entered a V8 isolate (usually the render // the thread on which they are created. Valid threads for creating a V8 handle
// process main thread). Non-static methods may only be called on the thread // include the render process main thread (TID_RENDERER) and WebWorker threads.
// that initially returned the handle. // A task runner for posting tasks on the associated thread can be retrieved via
// the CefV8Context::GetTaskRunner() method.
/// ///
/*--cef(source=library)--*/ /*--cef(source=library)--*/
class CefV8Context : public virtual CefBase { class CefV8Context : public virtual CefBase {
@ -142,6 +144,14 @@ class CefV8Context : public virtual CefBase {
/*--cef()--*/ /*--cef()--*/
static bool InContext(); 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 // 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 // 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; 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()--*/ /*--cef()--*/
virtual CefRefPtr<CefBrowser> GetBrowser() =0; 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()--*/ /*--cef()--*/
virtual CefRefPtr<CefFrame> GetFrame() =0; 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 // 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 // of this class will be called on the thread associated with the V8 function.
// was registered on.
/// ///
/*--cef(source=client)--*/ /*--cef(source=client)--*/
class CefV8Handler : public virtual CefBase { 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 // Interface that should be implemented to handle V8 accessor calls. Accessor
// identifiers are registered by calling CefV8Value::SetValue(). The methods // identifiers are registered by calling CefV8Value::SetValue(). The methods
// of this class will only be called on a render process thread that the // of this class will be called on the thread associated with the V8 accessor.
// accessor was registered on.
/// ///
/*--cef(source=client)--*/ /*--cef(source=client)--*/
class CefV8Accessor : public virtual CefBase { 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 // Class representing a V8 value handle. V8 handles can only be accessed from
// render process thread that has entered a V8 isolate (usually the render // the thread on which they are created. Valid threads for creating a V8 handle
// process main thread). Non-static methods may only be called on the thread // include the render process main thread (TID_RENDERER) and WebWorker threads.
// that initially returned the handle. // A task runner for posting tasks on the associated thread can be retrieved via
// the CefV8Context::GetTaskRunner() method.
/// ///
/*--cef(source=library)--*/ /*--cef(source=library)--*/
class CefV8Value : public virtual CefBase { 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 // Class representing a V8 stack trace handle. V8 handles can only be accessed
// on a render process thread that has entered a V8 isolate (usually the render // from the thread on which they are created. Valid threads for creating a V8
// process main thread). Non-static methods may only be called on the thread // handle include the render process main thread (TID_RENDERER) and WebWorker
// that initially returned the handle. // threads. A task runner for posting tasks on the associated thread can be
// retrieved via the CefV8Context::GetTaskRunner() method.
/// ///
/*--cef(source=library)--*/ /*--cef(source=library)--*/
class CefV8StackTrace : public virtual CefBase { 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 // Class representing a V8 stack frame handle. V8 handles can only be accessed
// on a render process thread that has entered a V8 isolate (usually the render // from the thread on which they are created. Valid threads for creating a V8
// process main thread). Non-static methods may only be called on the thread // handle include the render process main thread (TID_RENDERER) and WebWorker
// that initially returned the handle. // threads. A task runner for posting tasks on the associated thread can be
// retrieved via the CefV8Context::GetTaskRunner() method.
/// ///
/*--cef(source=library)--*/ /*--cef(source=library)--*/
class CefV8StackFrame : public virtual CefBase { class CefV8StackFrame : public virtual CefBase {

@ -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 // reserved. Use of this source code is governed by a BSD-style license that can
// be found in the LICENSE file. // be found in the LICENSE file.
#include "include/cef_task.h" #include "include/cef_task.h"
#include "libcef/browser/thread_util.h" #include "libcef/common/task_runner_impl.h"
#include "libcef/renderer/thread_util.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/location.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
bool CefCurrentlyOn(CefThreadId threadId) { bool CefCurrentlyOn(CefThreadId threadId) {
int id = GetThreadId(threadId); scoped_refptr<base::SequencedTaskRunner> task_runner =
if (id >= 0) { CefTaskRunnerImpl::GetTaskRunner(threadId);
// Browser process. if (task_runner.get())
return CEF_CURRENTLY_ON(static_cast<BrowserThread::ID>(id)); return task_runner->RunsTasksOnCurrentThread();
} else if (id == kRenderThreadId) {
// Renderer process.
return CEF_CURRENTLY_ON_RT();
}
return false; return false;
} }
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task) { bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task) {
int id = GetThreadId(threadId); scoped_refptr<base::SequencedTaskRunner> task_runner =
if (id >= 0) { CefTaskRunnerImpl::GetTaskRunner(threadId);
// Browser process. if (task_runner.get()) {
return CEF_POST_TASK(static_cast<BrowserThread::ID>(id), return task_runner->PostTask(FROM_HERE,
base::Bind(&CefTask::Execute, task, threadId)); base::Bind(&CefTask::Execute, task));
} else if (id == kRenderThreadId) {
// Renderer process.
return CEF_POST_TASK_RT(base::Bind(&CefTask::Execute, task, threadId));
} }
return false; return false;
} }
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task, bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task, int64 delay_ms) {
int64 delay_ms) { scoped_refptr<base::SequencedTaskRunner> task_runner =
int id = GetThreadId(threadId); CefTaskRunnerImpl::GetTaskRunner(threadId);
if (id >= 0) { if (task_runner.get()) {
// Browser process. return task_runner->PostDelayedTask(FROM_HERE,
return CEF_POST_DELAYED_TASK(static_cast<BrowserThread::ID>(id), base::Bind(&CefTask::Execute, task),
base::Bind(&CefTask::Execute, task, threadId), base::TimeDelta::FromMilliseconds(delay_ms));
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));
} }
return false; return false;
} }

@ -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));
}

@ -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_

@ -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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // 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/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.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/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 "v8/include/v8.h"
#include "webkit/glue/worker_task_runner.h"
namespace { namespace {
@ -73,8 +77,129 @@ class CefPrerendererClient : public content::RenderViewObserver,
virtual void willAddPrerender(WebKit::WebPrerender* prerender) OVERRIDE {} 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 } // 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 { struct CefContentRendererClient::SchemeInfo {
std::string scheme_name; std::string scheme_name;
bool is_local; bool is_local;
@ -149,6 +274,9 @@ void CefContentRendererClient::WebKitInitialized() {
// TODO(cef): Enable these once the implementation supports it. // TODO(cef): Enable these once the implementation supports it.
WebKit::WebRuntimeFeatures::enableNotifications(false); WebKit::WebRuntimeFeatures::enableNotifications(false);
worker_script_observer_.reset(new CefWebWorkerScriptObserver());
WebKit::WebWorkerInfo::addScriptObserver(worker_script_observer_.get());
if (!scheme_info_list_.empty()) { if (!scheme_info_list_.empty()) {
// Register the custom schemes. // Register the custom schemes.
SchemeInfoList::const_iterator it = scheme_info_list_.begin(); SchemeInfoList::const_iterator it = scheme_info_list_.begin();
@ -189,11 +317,8 @@ void CefContentRendererClient::WebKitInitialized() {
&uncaught_exception_stack_size); &uncaught_exception_stack_size);
if (uncaught_exception_stack_size > 0) { if (uncaught_exception_stack_size > 0) {
CefContentRendererClient::Get()->SetUncaughtExceptionStackSize( uncaught_exception_stack_size_ = uncaught_exception_stack_size;
uncaught_exception_stack_size); CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
v8::V8::AddMessageListener(&CefV8MessageHandler);
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true,
uncaught_exception_stack_size, v8::StackTrace::kDetailed);
} }
} }
@ -207,6 +332,11 @@ void CefContentRendererClient::WebKitInitialized() {
} }
} }
void CefContentRendererClient::OnRenderProcessShutdown() {
// Destroy global objects associated with the default Isolate.
CefV8IsolateDestroyed();
}
void CefContentRendererClient::DevToolsAgentAttached() { void CefContentRendererClient::DevToolsAgentAttached() {
CEF_REQUIRE_RT(); CEF_REQUIRE_RT();
++devtools_agent_count_; ++devtools_agent_count_;
@ -218,17 +348,71 @@ void CefContentRendererClient::DevToolsAgentDetached() {
if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) { if (devtools_agent_count_ == 0 && uncaught_exception_stack_size_ > 0) {
// When the last DevToolsAgent is detached the stack size is set to 0. // When the last DevToolsAgent is detached the stack size is set to 0.
// Restore the user-specified stack size here. // Restore the user-specified stack size here.
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true, CefV8SetUncaughtExceptionStackSize(uncaught_exception_stack_size_);
uncaught_exception_stack_size_, v8::StackTrace::kDetailed);
// 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) { scoped_refptr<base::SequencedTaskRunner>
uncaught_exception_stack_size_ = stackSize; 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() { void CefContentRendererClient::RenderThreadStarted() {
render_loop_ = base::MessageLoopProxy::current(); render_task_runner_ = base::MessageLoopProxy::current();
observer_.reset(new CefRenderProcessObserver()); observer_.reset(new CefRenderProcessObserver());
content::RenderThread* thread = content::RenderThread::Get(); content::RenderThread* thread = content::RenderThread::Get();
@ -244,6 +428,9 @@ void CefContentRendererClient::RenderThreadStarted() {
WebKit::WebPrerenderingSupport::initialize(new CefPrerenderingSupport()); WebKit::WebPrerenderingSupport::initialize(new CefPrerenderingSupport());
// Create global objects associated with the default Isolate.
CefV8IsolateCreated();
// Retrieve the new render thread information synchronously. // Retrieve the new render thread information synchronously.
CefProcessHostMsg_GetNewRenderThreadInfo_Params params; CefProcessHostMsg_GetNewRenderThreadInfo_Params params;
thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(&params)); thread->Send(new CefProcessHostMsg_GetNewRenderThreadInfo(&params));

@ -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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
@ -15,10 +16,11 @@
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.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" #include "content/public/renderer/content_renderer_client.h"
class CefRenderProcessObserver; class CefRenderProcessObserver;
class CefWebWorkerScriptObserver;
struct Cef_CrossOriginWhiteListEntry_Params; struct Cef_CrossOriginWhiteListEntry_Params;
class CefContentRendererClient : public content::ContentRendererClient { class CefContentRendererClient : public content::ContentRendererClient {
@ -43,14 +45,32 @@ class CefContentRendererClient : public content::ContentRendererClient {
bool is_local, bool is_local,
bool is_display_isolated); bool is_display_isolated);
// Render thread message loop proxy. // Render thread task runner.
base::MessageLoopProxy* render_loop() const { return render_loop_.get(); } 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 WebKitInitialized();
void OnRenderProcessShutdown();
void DevToolsAgentAttached(); void DevToolsAgentAttached();
void DevToolsAgentDetached(); 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: private:
// ContentRendererClient implementation. // ContentRendererClient implementation.
@ -69,8 +89,9 @@ class CefContentRendererClient : public content::ContentRendererClient {
v8::Handle<v8::Context> context, v8::Handle<v8::Context> context,
int world_id) OVERRIDE; int world_id) OVERRIDE;
scoped_refptr<base::MessageLoopProxy> render_loop_; scoped_refptr<base::SequencedTaskRunner> render_task_runner_;
scoped_ptr<CefRenderProcessObserver> observer_; scoped_ptr<CefRenderProcessObserver> observer_;
scoped_ptr<CefWebWorkerScriptObserver> worker_script_observer_;
// Map of RenderView pointers to CefBrowserImpl references. // Map of RenderView pointers to CefBrowserImpl references.
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap; typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;
@ -87,6 +108,13 @@ class CefContentRendererClient : public content::ContentRendererClient {
int devtools_agent_count_; int devtools_agent_count_;
int uncaught_exception_stack_size_; 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_ #endif // CEF_LIBCEF_RENDERER_CONTENT_RENDERER_CLIENT_H_

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

@ -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. // 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 // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
@ -20,6 +20,7 @@ class CefRenderProcessObserver : public content::RenderProcessObserver {
// RenderProcessObserver implementation. // RenderProcessObserver implementation.
virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE; virtual bool OnControlMessageReceived(const IPC::Message& message) OVERRIDE;
virtual void WebKitInitialized() OVERRIDE; virtual void WebKitInitialized() OVERRIDE;
virtual void OnRenderProcessShutdown() OVERRIDE;
private: private:
// Message handlers called on the render thread. // Message handlers called on the render thread.

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -28,7 +28,8 @@
return; \ return; \
} }
#define CEF_RENDER_LOOP() (CefContentRendererClient::Get()->render_loop()) #define CEF_RENDER_LOOP() \
(CefContentRendererClient::Get()->render_task_runner())
#define CEF_POST_TASK_RT(task) \ #define CEF_POST_TASK_RT(task) \
CEF_RENDER_LOOP()->PostTask(FROM_HERE, task) CEF_RENDER_LOOP()->PostTask(FROM_HERE, task)

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -15,6 +15,8 @@ MSVC_PUSH_WARNING_LEVEL(0);
#include "ScriptControllerBase.h" // NOLINT(build/include) #include "ScriptControllerBase.h" // NOLINT(build/include)
#include "V8Binding.h" // NOLINT(build/include) #include "V8Binding.h" // NOLINT(build/include)
#include "V8RecursionScope.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(); MSVC_POP_WARNING();
#undef LOG #undef LOG
@ -22,6 +24,7 @@ MSVC_POP_WARNING();
#include "libcef/common/cef_switches.h" #include "libcef/common/cef_switches.h"
#include "libcef/common/content_client.h" #include "libcef/common/content_client.h"
#include "libcef/common/task_runner_impl.h"
#include "libcef/common/tracker.h" #include "libcef/common/tracker.h"
#include "libcef/renderer/browser_impl.h" #include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/thread_util.h" #include "libcef/renderer/thread_util.h"
@ -29,6 +32,8 @@ MSVC_POP_WARNING();
#include "base/bind.h" #include "base/bind.h"
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
#include "base/string_number_conversions.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/WebKit.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptController.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 kCefTrackObject[] = "Cef::TrackObject";
static const char kCefContextState[] = "Cef::ContextState"; 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: public:
CefV8TrackManager() CefV8IsolateManager()
: context_safety_impl_(IMPL_HASH) { : 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(); const CommandLine& command_line = *CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kContextSafetyImplementation)) { if (command_line.HasSwitch(switches::kContextSafetyImplementation)) {
std::string value = command_line.GetSwitchValueASCII( 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( scoped_refptr<CefV8ContextState> GetContextState(
v8::Handle<v8::Context> context) { v8::Handle<v8::Context> context) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
if (context_safety_impl_ == IMPL_DISABLED) if (context_safety_impl_ == IMPL_DISABLED)
return scoped_refptr<CefV8ContextState>(); return scoped_refptr<CefV8ContextState>();
@ -105,6 +125,8 @@ class CefV8TrackManager {
} }
void ReleaseContext(v8::Handle<v8::Context> context) { void ReleaseContext(v8::Handle<v8::Context> context) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
if (context_safety_impl_ == IMPL_DISABLED) if (context_safety_impl_ == IMPL_DISABLED)
return; return;
@ -135,14 +157,49 @@ class CefV8TrackManager {
} }
void AddGlobalTrackObject(CefTrackNode* object) { void AddGlobalTrackObject(CefTrackNode* object) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
global_manager_.Add(object); global_manager_.Add(object);
} }
void DeleteGlobalTrackObject(CefTrackNode* object) { void DeleteGlobalTrackObject(CefTrackNode* object) {
DCHECK_EQ(isolate_, v8::Isolate::GetCurrent());
global_manager_.Delete(object); 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: private:
v8::Isolate* isolate_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
enum ContextSafetyImpl { enum ContextSafetyImpl {
IMPL_DISABLED, IMPL_DISABLED,
IMPL_HASH, IMPL_HASH,
@ -160,9 +217,51 @@ class CefV8TrackManager {
// Used for globally tracked objects that are not associated with a particular // Used for globally tracked objects that are not associated with a particular
// context. // context.
CefTrackManager global_manager_; 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 { class V8TrackObject : public CefTrackNode {
public: public:
@ -275,7 +374,7 @@ class CefV8MakeWeakParam {
// |object_| will be deleted when: // |object_| will be deleted when:
// A. The process shuts down, or // A. The process shuts down, or
// B. TrackDestructor is called for the weak handle. // B. TrackDestructor is called for the weak handle.
g_v8_tracker.Pointer()->AddGlobalTrackObject(object_); GetIsolateManager()->AddGlobalTrackObject(object_);
} }
} }
~CefV8MakeWeakParam() { ~CefV8MakeWeakParam() {
@ -285,7 +384,7 @@ class CefV8MakeWeakParam {
if (context_state_->IsValid()) if (context_state_->IsValid())
context_state_->DeleteTrackObject(object_); context_state_->DeleteTrackObject(object_);
} else { } else {
g_v8_tracker.Pointer()->DeleteGlobalTrackObject(object_); GetIsolateManager()->DeleteGlobalTrackObject(object_);
} }
v8::V8::AdjustAmountOfExternalAllocatedMemory( 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. // V8 extension registration.
class ExtensionWrapper : public v8::Extension { class ExtensionWrapper : public v8::Extension {
@ -486,7 +616,7 @@ class ExtensionWrapper : public v8::Extension {
// The reference will be released when the process exits. // The reference will be released when the process exits.
V8TrackObject* object = new V8TrackObject; V8TrackObject* object = new V8TrackObject;
object->SetHandler(handler); object->SetHandler(handler);
g_v8_tracker.Pointer()->AddGlobalTrackObject(object); GetIsolateManager()->AddGlobalTrackObject(object);
} }
} }
@ -549,13 +679,58 @@ class CefV8ExceptionImpl : public CefV8Exception {
IMPLEMENT_REFCOUNTING(CefV8ExceptionImpl); 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 } // namespace
// Global functions. // Global functions.
void CefV8IsolateCreated() {
g_v8_state.Pointer()->CreateIsolateManager();
}
void CefV8IsolateDestroyed() {
g_v8_state.Pointer()->DestroyIsolateManager();
}
void CefV8ReleaseContext(v8::Handle<v8::Context> context) { 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, bool CefRegisterExtension(const CefString& extension_name,
@ -565,9 +740,9 @@ bool CefRegisterExtension(const CefString& extension_name,
CEF_REQUIRE_RT_RETURN(false); CEF_REQUIRE_RT_RETURN(false);
V8TrackString* name = new V8TrackString(extension_name); V8TrackString* name = new V8TrackString(extension_name);
g_v8_tracker.Pointer()->AddGlobalTrackObject(name); GetIsolateManager()->AddGlobalTrackObject(name);
V8TrackString* code = new V8TrackString(javascript_code); V8TrackString* code = new V8TrackString(javascript_code);
g_v8_tracker.Pointer()->AddGlobalTrackObject(code); GetIsolateManager()->AddGlobalTrackObject(code);
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(), ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
code->GetString(), handler.get()); code->GetString(), handler.get());
@ -579,7 +754,7 @@ bool CefRegisterExtension(const CefString& extension_name,
// Helper macros // Helper macros
#define CEF_V8_HAS_ISOLATE() (!!v8::Isolate::GetCurrent()) #define CEF_V8_HAS_ISOLATE() (!!GetIsolateManager())
#define CEF_V8_REQUIRE_ISOLATE_RETURN(var) \ #define CEF_V8_REQUIRE_ISOLATE_RETURN(var) \
if (!CEF_V8_HAS_ISOLATE()) { \ if (!CEF_V8_HAS_ISOLATE()) { \
NOTREACHED() << "V8 isolate is not valid"; \ NOTREACHED() << "V8 isolate is not valid"; \
@ -636,13 +811,14 @@ CefV8HandleBase::~CefV8HandleBase() {
} }
bool CefV8HandleBase::BelongsToCurrentThread() const { bool CefV8HandleBase::BelongsToCurrentThread() const {
return message_loop_proxy_->BelongsToCurrentThread(); return task_runner_->RunsTasksOnCurrentThread();
} }
CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context) CefV8HandleBase::CefV8HandleBase(v8::Handle<v8::Context> context) {
: message_loop_proxy_(base::MessageLoopProxy::current()) { CefV8IsolateManager* manager = GetIsolateManager();
DCHECK(message_loop_proxy_.get()); DCHECK(manager);
context_state_ = g_v8_tracker.Pointer()->GetContextState(context); task_runner_ = manager->task_runner();
context_state_ = manager->GetContextState(context);
} }
@ -691,6 +867,10 @@ CefV8ContextImpl::~CefV8ContextImpl() {
DLOG_ASSERT(0 == enter_count_); DLOG_ASSERT(0 == enter_count_);
} }
CefRefPtr<CefTaskRunner> CefV8ContextImpl::GetTaskRunner() {
return new CefTaskRunnerImpl(handle_->task_runner());
}
bool CefV8ContextImpl::IsValid() { bool CefV8ContextImpl::IsValid() {
return CEF_V8_IS_VALID(); return CEF_V8_IS_VALID();
} }
@ -699,6 +879,10 @@ CefRefPtr<CefBrowser> CefV8ContextImpl::GetBrowser() {
CefRefPtr<CefBrowser> browser; CefRefPtr<CefBrowser> browser;
CEF_V8_REQUIRE_VALID_RETURN(browser); CEF_V8_REQUIRE_VALID_RETURN(browser);
// Return NULL for WebWorkers.
if (!CEF_CURRENTLY_ON_RT())
return browser;
WebKit::WebFrame* webframe = GetWebFrame(); WebKit::WebFrame* webframe = GetWebFrame();
if (webframe) if (webframe)
browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->top()); browser = CefBrowserImpl::GetBrowserForMainFrame(webframe->top());
@ -710,6 +894,10 @@ CefRefPtr<CefFrame> CefV8ContextImpl::GetFrame() {
CefRefPtr<CefFrame> frame; CefRefPtr<CefFrame> frame;
CEF_V8_REQUIRE_VALID_RETURN(frame); CEF_V8_REQUIRE_VALID_RETURN(frame);
// Return NULL for WebWorkers.
if (!CEF_CURRENTLY_ON_RT())
return frame;
WebKit::WebFrame* webframe = GetWebFrame(); WebKit::WebFrame* webframe = GetWebFrame();
if (webframe) { if (webframe) {
CefRefPtr<CefBrowserImpl> browser = CefRefPtr<CefBrowserImpl> browser =
@ -777,8 +965,9 @@ bool CefV8ContextImpl::Eval(const CefString& code,
} }
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
v8::Context::Scope context_scope(GetHandle()); v8::Local<v8::Context> context = GetContext();
v8::Local<v8::Object> obj = GetHandle()->Global(); v8::Context::Scope context_scope(context);
v8::Local<v8::Object> obj = context->Global();
// Retrieve the eval function. // Retrieve the eval function.
v8::Local<v8::Value> val = obj->Get(v8::String::New("eval")); 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; v8::TryCatch try_catch;
try_catch.SetVerbose(true); try_catch.SetVerbose(true);
v8::Local<v8::Value> func_rv;
retval = NULL; retval = NULL;
exception = NULL; exception = NULL;
// Execute the function call using the ScriptController so that inspector v8::Local<v8::Value> func_rv =
// instrumentation works. CallV8Function(context, func, obj, 1, &code_val);
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);
}
if (try_catch.HasCaught()) { if (try_catch.HasCaught()) {
exception = new CefV8ExceptionImpl(try_catch.Message()); exception = new CefV8ExceptionImpl(try_catch.Message());
@ -818,6 +1000,7 @@ v8::Local<v8::Context> CefV8ContextImpl::GetContext() {
} }
WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() { WebKit::WebFrame* CefV8ContextImpl::GetWebFrame() {
CEF_REQUIRE_RT();
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
v8::Context::Scope context_scope(GetHandle()); v8::Context::Scope context_scope(GetHandle());
WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext(); WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext();
@ -1020,7 +1203,6 @@ CefV8ValueImpl::CefV8ValueImpl(v8::Handle<v8::Value> value,
CefV8ValueImpl::~CefV8ValueImpl() { CefV8ValueImpl::~CefV8ValueImpl() {
} }
bool CefV8ValueImpl::IsValid() { bool CefV8ValueImpl::IsValid() {
return CEF_V8_IS_VALID(); return CEF_V8_IS_VALID();
} }
@ -1519,16 +1701,9 @@ CefRefPtr<CefV8Value> CefV8ValueImpl::ExecuteFunctionWithContext(
{ {
v8::TryCatch try_catch; v8::TryCatch try_catch;
try_catch.SetVerbose(true); try_catch.SetVerbose(true);
v8::Local<v8::Value> func_rv;
// Execute the function call using the ScriptController so that inspector v8::Local<v8::Value> func_rv =
// instrumentation works. CallV8Function(context_local, func, recv, argc, argv);
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);
}
if (!HasCaught(try_catch) && !func_rv.IsEmpty()) if (!HasCaught(try_catch) && !func_rv.IsEmpty())
retval = new CefV8ValueImpl(func_rv); retval = new CefV8ValueImpl(func_rv);
@ -1662,26 +1837,3 @@ bool CefV8StackFrameImpl::IsConstructor() {
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
return GetHandle()->IsConstructor(); 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);
}

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -15,17 +15,30 @@
#include "base/location.h" #include "base/location.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/message_loop_proxy.h" #include "base/sequenced_task_runner.h"
class CefTrackNode; class CefTrackNode;
class GURL;
namespace WebKit { namespace WebKit {
class WebFrame; 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); 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. // Used to detach handles when the associated context is released.
class CefV8ContextState : public base::RefCounted<CefV8ContextState> { class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
public: public:
@ -60,10 +73,10 @@ class CefV8ContextState : public base::RefCounted<CefV8ContextState> {
struct CefV8DeleteOnMessageLoopThread { struct CefV8DeleteOnMessageLoopThread {
template<typename T> template<typename T>
static void Destruct(const T* x) { static void Destruct(const T* x) {
if (x->message_loop_proxy_->BelongsToCurrentThread()) { if (x->task_runner()->RunsTasksOnCurrentThread()) {
delete x; delete x;
} else { } else {
if (!x->message_loop_proxy_->DeleteSoon(FROM_HERE, x)) { if (!x->task_runner()->DeleteSoon(FROM_HERE, x)) {
#if defined(UNIT_TEST) #if defined(UNIT_TEST)
// Only logged under unit testing because leaks at shutdown // Only logged under unit testing because leaks at shutdown
// are acceptable under normal circumstances. // are acceptable under normal circumstances.
@ -89,15 +102,17 @@ class CefV8HandleBase :
bool BelongsToCurrentThread() const; bool BelongsToCurrentThread() const;
scoped_refptr<base::SequencedTaskRunner> task_runner() const {
return task_runner_;
}
protected: protected:
// |context| is the context that owns this handle. If empty the current // |context| is the context that owns this handle. If empty the current
// context will be used. // context will be used.
explicit CefV8HandleBase(v8::Handle<v8::Context> context); explicit CefV8HandleBase(v8::Handle<v8::Context> context);
protected: protected:
friend struct CefV8DeleteOnMessageLoopThread; scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy_;
scoped_refptr<CefV8ContextState> context_state_; scoped_refptr<CefV8ContextState> context_state_;
}; };
@ -141,6 +156,7 @@ class CefV8ContextImpl : public CefV8Context {
explicit CefV8ContextImpl(v8::Handle<v8::Context> context); explicit CefV8ContextImpl(v8::Handle<v8::Context> context);
virtual ~CefV8ContextImpl(); virtual ~CefV8ContextImpl();
virtual CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
virtual bool IsValid() OVERRIDE; virtual bool IsValid() OVERRIDE;
virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE; virtual CefRefPtr<CefBrowser> GetBrowser() OVERRIDE;
virtual CefRefPtr<CefFrame> GetFrame() OVERRIDE; virtual CefRefPtr<CefFrame> GetFrame() OVERRIDE;
@ -320,7 +336,4 @@ class CefV8StackFrameImpl : public CefV8StackFrame {
DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl); DISALLOW_COPY_AND_ASSIGN(CefV8StackFrameImpl);
}; };
void CefV8MessageHandler(v8::Handle<v8::Message> message,
v8::Handle<v8::Value> data);
#endif // CEF_LIBCEF_RENDERER_V8_IMPL_H_ #endif // CEF_LIBCEF_RENDERER_V8_IMPL_H_

@ -218,6 +218,90 @@ void CEF_CALLBACK render_process_handler_on_uncaught_exception(
CefV8StackTraceCToCpp::Wrap(stackTrace)); 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( void CEF_CALLBACK render_process_handler_on_focused_node_changed(
struct _cef_render_process_handler_t* self, cef_browser_t* browser, struct _cef_render_process_handler_t* self, cef_browser_t* browser,
cef_frame_t* frame, cef_domnode_t* node) { cef_frame_t* frame, cef_domnode_t* node) {
@ -290,6 +374,12 @@ CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC(
render_process_handler_on_context_released; render_process_handler_on_context_released;
struct_.struct_.on_uncaught_exception = struct_.struct_.on_uncaught_exception =
render_process_handler_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 = struct_.struct_.on_focused_node_changed =
render_process_handler_on_focused_node_changed; render_process_handler_on_focused_node_changed;
struct_.struct_.on_process_message_received = struct_.struct_.on_process_message_received =

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

@ -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

@ -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_

@ -12,6 +12,7 @@
#include "libcef_dll/cpptoc/browser_cpptoc.h" #include "libcef_dll/cpptoc/browser_cpptoc.h"
#include "libcef_dll/cpptoc/frame_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/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_cpptoc.h" #include "libcef_dll/cpptoc/v8exception_cpptoc.h"
#include "libcef_dll/cpptoc/v8value_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. // 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) { int CEF_CALLBACK v8context_is_valid(struct _cef_v8context_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // 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) CefV8ContextCppToC::CefV8ContextCppToC(CefV8Context* cls)
: CefCppToC<CefV8ContextCppToC, CefV8Context, cef_v8context_t>(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_.is_valid = v8context_is_valid;
struct_.struct_.get_browser = v8context_get_browser; struct_.struct_.get_browser = v8context_get_browser;
struct_.struct_.get_frame = v8context_get_frame; struct_.struct_.get_frame = v8context_get_frame;

@ -214,6 +214,87 @@ void CefRenderProcessHandlerCToCpp::OnUncaughtException(
CefV8StackTraceCppToC::Wrap(stackTrace)); 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( void CefRenderProcessHandlerCToCpp::OnFocusedNodeChanged(
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame, CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) { CefRefPtr<CefDOMNode> node) {

@ -50,6 +50,13 @@ class CefRenderProcessHandlerCToCpp
CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context, CefRefPtr<CefFrame> frame, CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception, CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) OVERRIDE; 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, virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefDOMNode> node) OVERRIDE; CefRefPtr<CefFrame> frame, CefRefPtr<CefDOMNode> node) OVERRIDE;
virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser, virtual bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,

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

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

@ -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

@ -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_

@ -12,6 +12,7 @@
#include "libcef_dll/ctocpp/browser_ctocpp.h" #include "libcef_dll/ctocpp/browser_ctocpp.h"
#include "libcef_dll/ctocpp/frame_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/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h" #include "libcef_dll/ctocpp/v8exception_ctocpp.h"
#include "libcef_dll/ctocpp/v8value_ctocpp.h" #include "libcef_dll/ctocpp/v8value_ctocpp.h"
@ -52,6 +53,19 @@ bool CefV8Context::InContext() {
// VIRTUAL METHODS - Body may be edited by hand. // 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() { bool CefV8ContextCToCpp::IsValid() {
if (CEF_MEMBER_MISSING(struct_, is_valid)) if (CEF_MEMBER_MISSING(struct_, is_valid))
return false; return false;

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

@ -58,6 +58,7 @@
#include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h" #include "libcef_dll/cpptoc/scheme_registrar_cpptoc.h"
#include "libcef_dll/cpptoc/stream_reader_cpptoc.h" #include "libcef_dll/cpptoc/stream_reader_cpptoc.h"
#include "libcef_dll/cpptoc/stream_writer_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/urlrequest_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h" #include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_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(CefStreamWriterCppToC::DebugObjCt, 0);
DCHECK_EQ(CefStringVisitorCToCpp::DebugObjCt, 0); DCHECK_EQ(CefStringVisitorCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTaskCToCpp::DebugObjCt, 0); DCHECK_EQ(CefTaskCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefTaskRunnerCppToC::DebugObjCt, 0);
DCHECK_EQ(CefTraceClientCToCpp::DebugObjCt, 0); DCHECK_EQ(CefTraceClientCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestClientCToCpp::DebugObjCt, 0); DCHECK_EQ(CefURLRequestClientCToCpp::DebugObjCt, 0);
DCHECK_EQ(CefURLRequestCppToC::DebugObjCt, 0); DCHECK_EQ(CefURLRequestCppToC::DebugObjCt, 0);

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

@ -26,6 +26,11 @@ patches = [
'name': 'zlib', 'name': 'zlib',
'path': '../third_party/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 # http://code.google.com/p/chromiumembedded/issues/detail?id=364
'name': 'spi_webcore_364', 'name': 'spi_webcore_364',

@ -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);
+}
+
+}

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -215,7 +215,6 @@ void ClientApp::OnContextInitialized() {
ASSERT(manager.get()); ASSERT(manager.get());
manager->SetSupportedSchemes(cookieable_schemes_); manager->SetSupportedSchemes(cookieable_schemes_);
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin(); BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it) for (; it != browser_delegates_.end(); ++it)
(*it)->OnContextInitialized(this); (*it)->OnContextInitialized(this);
@ -223,7 +222,6 @@ void ClientApp::OnContextInitialized() {
void ClientApp::OnBeforeChildProcessLaunch( void ClientApp::OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) { CefRefPtr<CefCommandLine> command_line) {
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin(); BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it) for (; it != browser_delegates_.end(); ++it)
(*it)->OnBeforeChildProcessLaunch(this, command_line); (*it)->OnBeforeChildProcessLaunch(this, command_line);
@ -231,7 +229,6 @@ void ClientApp::OnBeforeChildProcessLaunch(
void ClientApp::OnRenderProcessThreadCreated( void ClientApp::OnRenderProcessThreadCreated(
CefRefPtr<CefListValue> extra_info) { CefRefPtr<CefListValue> extra_info) {
// Execute delegate callbacks.
BrowserDelegateSet::iterator it = browser_delegates_.begin(); BrowserDelegateSet::iterator it = browser_delegates_.begin();
for (; it != browser_delegates_.end(); ++it) for (; it != browser_delegates_.end(); ++it)
(*it)->OnRenderProcessThreadCreated(this, extra_info); (*it)->OnRenderProcessThreadCreated(this, extra_info);
@ -245,7 +242,6 @@ void ClientApp::GetProxyForUrl(const CefString& url,
} }
void ClientApp::OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) { void ClientApp::OnRenderThreadCreated(CefRefPtr<CefListValue> extra_info) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnRenderThreadCreated(this, extra_info); (*it)->OnRenderThreadCreated(this, extra_info);
@ -274,21 +270,18 @@ void ClientApp::OnWebKitInitialized() {
CefRegisterExtension("v8/app", app_code, CefRegisterExtension("v8/app", app_code,
new ClientAppExtensionHandler(this)); new ClientAppExtensionHandler(this));
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnWebKitInitialized(this); (*it)->OnWebKitInitialized(this);
} }
void ClientApp::OnBrowserCreated(CefRefPtr<CefBrowser> browser) { void ClientApp::OnBrowserCreated(CefRefPtr<CefBrowser> browser) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnBrowserCreated(this, browser); (*it)->OnBrowserCreated(this, browser);
} }
void ClientApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) { void ClientApp::OnBrowserDestroyed(CefRefPtr<CefBrowser> browser) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnBrowserDestroyed(this, browser); (*it)->OnBrowserDestroyed(this, browser);
@ -299,7 +292,6 @@ bool ClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefRequest> request, CefRefPtr<CefRequest> request,
NavigationType navigation_type, NavigationType navigation_type,
bool is_redirect) { bool is_redirect) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) { for (; it != render_delegates_.end(); ++it) {
if ((*it)->OnBeforeNavigation(this, browser, frame, request, if ((*it)->OnBeforeNavigation(this, browser, frame, request,
@ -312,18 +304,16 @@ bool ClientApp::OnBeforeNavigation(CefRefPtr<CefBrowser> browser,
} }
void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser, void ClientApp::OnContextCreated(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) { CefRefPtr<CefV8Context> context) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnContextCreated(this, browser, frame, context); (*it)->OnContextCreated(this, browser, frame, context);
} }
void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser, void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) { CefRefPtr<CefV8Context> context) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnContextReleased(this, browser, frame, context); (*it)->OnContextReleased(this, browser, frame, context);
@ -342,11 +332,10 @@ void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
} }
void ClientApp::OnUncaughtException(CefRefPtr<CefBrowser> browser, void ClientApp::OnUncaughtException(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception, CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) { CefRefPtr<CefV8StackTrace> stackTrace) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) { for (; it != render_delegates_.end(); ++it) {
(*it)->OnUncaughtException(this, browser, frame, context, exception, (*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, void ClientApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) { CefRefPtr<CefDOMNode> node) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it) for (; it != render_delegates_.end(); ++it)
(*it)->OnFocusedNodeChanged(this, browser, frame, node); (*it)->OnFocusedNodeChanged(this, browser, frame, node);
@ -371,7 +388,6 @@ bool ClientApp::OnProcessMessageReceived(
bool handled = false; bool handled = false;
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin(); RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end() && !handled; ++it) { for (; it != render_delegates_.end() && !handled; ++it) {
handled = (*it)->OnProcessMessageReceived(this, browser, source_process, handled = (*it)->OnProcessMessageReceived(this, browser, source_process,

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -20,62 +20,38 @@ class ClientApp : public CefApp,
public: public:
// Interface for browser delegates. All BrowserDelegates must be returned via // Interface for browser delegates. All BrowserDelegates must be returned via
// CreateBrowserDelegates. Do not perform work in the BrowserDelegate // CreateBrowserDelegates. Do not perform work in the BrowserDelegate
// constructor. // constructor. See CefBrowserProcessHandler for documentation.
class BrowserDelegate : public virtual CefBase { class BrowserDelegate : public virtual CefBase {
public: public:
// Called on the browser process UI thread immediately after the CEF context virtual void OnContextInitialized(CefRefPtr<ClientApp> app) {}
// has been initialized.
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( virtual void OnBeforeChildProcessLaunch(
CefRefPtr<ClientApp> app, 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( virtual void OnRenderProcessThreadCreated(
CefRefPtr<ClientApp> app, CefRefPtr<ClientApp> app,
CefRefPtr<CefListValue> extra_info) { CefRefPtr<CefListValue> extra_info) {}
}
}; };
typedef std::set<CefRefPtr<BrowserDelegate> > BrowserDelegateSet; typedef std::set<CefRefPtr<BrowserDelegate> > BrowserDelegateSet;
// Interface for renderer delegates. All RenderDelegates must be returned via // Interface for renderer delegates. All RenderDelegates must be returned via
// CreateRenderDelegates. Do not perform work in the RenderDelegate // CreateRenderDelegates. Do not perform work in the RenderDelegate
// constructor. // constructor. See CefRenderProcessHandler for documentation.
class RenderDelegate : public virtual CefBase { class RenderDelegate : public virtual CefBase {
public: public:
// Called after the render process main thread has been created.
virtual void OnRenderThreadCreated(CefRefPtr<ClientApp> app, 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, virtual void OnBrowserCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser) { CefRefPtr<CefBrowser> browser) {}
}
// Called before a browser is destroyed.
virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app, 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, virtual bool OnBeforeNavigation(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser, CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
@ -85,40 +61,45 @@ class ClientApp : public CefApp,
return false; 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, virtual void OnContextCreated(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser, CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, 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, virtual void OnContextReleased(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser, CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, 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, virtual void OnUncaughtException(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser, CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context, CefRefPtr<CefV8Context> context,
CefRefPtr<CefV8Exception> exception, 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, virtual void OnFocusedNodeChanged(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser, CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) { CefRefPtr<CefDOMNode> node) {}
}
// Called when a process message is received. Return true if the message was // Called when a process message is received. Return true if the message was
// handled and should not be passed on to other handlers. RenderDelegates // handled and should not be passed on to other handlers. RenderDelegates
@ -218,6 +199,21 @@ class ClientApp : public CefApp,
CefRefPtr<CefV8Exception> exception, CefRefPtr<CefV8Exception> exception,
CefRefPtr<CefV8StackTrace> stackTrace) CefRefPtr<CefV8StackTrace> stackTrace)
OVERRIDE; 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, virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE; CefRefPtr<CefDOMNode> node) OVERRIDE;

@ -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);
}

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -130,6 +130,12 @@ void WaitForThread(CefThreadId thread_id) {
event.Wait(); event.Wait();
} }
void WaitForThread(CefRefPtr<CefTaskRunner> task_runner) {
base::WaitableEvent event(true, false);
task_runner->PostTask(NewCefRunnableFunction(&NotifyEvent, &event));
event.Wait();
}
bool TestFailed() { bool TestFailed() {
CefRefPtr<CefCommandLine> command_line = CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine(); CefCommandLine::GetGlobalCommandLine();

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // 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 // 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. // indication that all previously pending tasks on that thread have completed.
void WaitForThread(CefThreadId thread_id); void WaitForThread(CefThreadId thread_id);
void WaitForThread(CefRefPtr<CefTaskRunner> task_runner);
#define WaitForIOThread() WaitForThread(TID_IO) #define WaitForIOThread() WaitForThread(TID_IO)
#define WaitForUIThread() WaitForThread(TID_UI) #define WaitForUIThread() WaitForThread(TID_UI)

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -69,7 +69,7 @@ class BeginTracingTask : public CefTask {
: client_(client) { : client_(client) {
} }
virtual void Execute(CefThreadId threadId) OVERRIDE { virtual void Execute() OVERRIDE {
EXPECT_TRUE(CefBeginTracing(client_, kTraceTestCategory)); EXPECT_TRUE(CefBeginTracing(client_, kTraceTestCategory));
} }
@ -86,7 +86,7 @@ class EndTracingTask : public CefTask {
public: public:
EndTracingTask() {} EndTracingTask() {}
virtual void Execute(CefThreadId threadId) OVERRIDE { virtual void Execute() OVERRIDE {
EXPECT_TRUE(CefEndTracingAsync()); EXPECT_TRUE(CefEndTracingAsync());
} }

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // 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 kV8NavTestUrl[] = "http://tests/V8Test.NavTest";
const char kV8OnUncaughtExceptionTestUrl[] = const char kV8OnUncaughtExceptionTestUrl[] =
"http://tests/V8Test.OnUncaughtException"; "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 kV8TestMsg[] = "V8Test.Test";
const char kV8TestCmdArg[] = "v8-test"; const char kV8TestCmdArg[] = "v8-test";
const char kV8DevToolsURLMsg[] = "V8Test.DevToolsURL"; const char kV8DevToolsURLMsg[] = "V8Test.DevToolsURL";
@ -68,9 +70,12 @@ enum V8TestMode {
V8TEST_CONTEXT_INVALID, V8TEST_CONTEXT_INVALID,
V8TEST_BINDING, V8TEST_BINDING,
V8TEST_STACK_TRACE, V8TEST_STACK_TRACE,
V8TEST_EXTENSION,
V8TEST_ON_UNCAUGHT_EXCEPTION, V8TEST_ON_UNCAUGHT_EXCEPTION,
V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS, 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 // Set to the current test being run in the browser process. Will always be
@ -214,11 +219,16 @@ class V8RendererTest : public ClientApp::RenderDelegate {
RunStackTraceTest(); RunStackTraceTest();
break; break;
case V8TEST_ON_UNCAUGHT_EXCEPTION: case V8TEST_ON_UNCAUGHT_EXCEPTION:
case V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION:
RunOnUncaughtExceptionTest(); RunOnUncaughtExceptionTest();
break; break;
case V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS: case V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS:
case V8TEST_WORKER_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS:
RunOnUncaughtExceptionDevToolsTest(); RunOnUncaughtExceptionDevToolsTest();
break; break;
case V8TEST_WORKER_BINDING:
// The test is triggered in OnWorkerContextCreated().
break;
default: default:
// Was a startup test. // Was a startup test.
EXPECT_TRUE(startup_test_success_); EXPECT_TRUE(startup_test_success_);
@ -1588,32 +1598,6 @@ class V8RendererTest : public ClientApp::RenderDelegate {
"window.open('" + devtools_url_ + "');", "about:blank", 0); "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. // Test execution of a native function when the extension is loaded.
void RunExtensionTest() { void RunExtensionTest() {
std::string code = "native function v8_extension_test();" std::string code = "native function v8_extension_test();"
@ -1665,7 +1649,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
if (test_mode_ == V8TEST_NONE) if (test_mode_ == V8TEST_NONE)
return; 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) { if (browser_.get() == NULL) {
app_ = app; app_ = app;
browser_ = browser; 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, virtual void OnBrowserDestroyed(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser) OVERRIDE { CefRefPtr<CefBrowser> browser) OVERRIDE {
if (test_mode_ == V8TEST_NONE) if (test_mode_ == V8TEST_NONE)
return; 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()) { if (browser->IsPopup()) {
// After window destruction there is still a call to // After window destruction there is still a call to
// ScriptController::setCaptureCallStackForUncaughtExceptions(0), // ScriptController::setCaptureCallStackForUncaughtExceptions(0),
@ -1782,7 +1972,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
if (test_mode_ == V8TEST_NONE) if (test_mode_ == V8TEST_NONE)
return false; 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_TRUE(browser.get());
EXPECT_EQ(PID_BROWSER, source_process); EXPECT_EQ(PID_BROWSER, source_process);
EXPECT_TRUE(message.get()); EXPECT_TRUE(message.get());
@ -1883,6 +2074,8 @@ class V8RendererTest : public ClientApp::RenderDelegate {
protected: protected:
// Return from the test. // Return from the test.
void DestroyTest() { void DestroyTest() {
EXPECT_TRUE(CefCurrentlyOn(TID_RENDERER));
if (test_mode_ == V8TEST_CONTEXT_INVALID) { if (test_mode_ == V8TEST_CONTEXT_INVALID) {
// Verify that objects related to a particular context are not valid after // Verify that objects related to a particular context are not valid after
// OnContextReleased is called for that context. // OnContextReleased is called for that context.
@ -1921,6 +2114,9 @@ class V8RendererTest : public ClientApp::RenderDelegate {
CefRefPtr<CefV8Context> test_context_; CefRefPtr<CefV8Context> test_context_;
CefRefPtr<CefV8Value> test_object_; CefRefPtr<CefV8Value> test_object_;
CefRefPtr<CefV8Context> test_context_worker_;
CefRefPtr<CefTaskRunner> test_task_runner_worker_;
// Used by startup tests to indicate success. // Used by startup tests to indicate success.
TrackCallback startup_test_success_; TrackCallback startup_test_success_;
@ -1957,6 +2153,28 @@ class V8TestHandler : public TestHandler {
"</body></html>\n", "</body></html>\n",
"text/html"); "text/html");
CreateBrowser(kV8OnUncaughtExceptionTestUrl); 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 { } else {
EXPECT_TRUE(test_url_ != NULL); EXPECT_TRUE(test_url_ != NULL);
AddResource(test_url_, "<html><body>" AddResource(test_url_, "<html><body>"
@ -1968,7 +2186,8 @@ class V8TestHandler : public TestHandler {
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser, virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame, CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE { 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()) { if (browser->IsPopup()) {
EXPECT_STREQ( EXPECT_STREQ(
GetBrowser()->GetHost()->GetDevToolsURL(true).ToString().c_str(), 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(OnUncaughtException, V8TEST_ON_UNCAUGHT_EXCEPTION);
V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS); V8_TEST(OnUncaughtExceptionDevTools, V8TEST_ON_UNCAUGHT_EXCEPTION_DEV_TOOLS);
V8_TEST(Extension, V8TEST_EXTENSION); 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);

@ -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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
@ -88,7 +88,7 @@ class BinaryTask : public CefTask {
data_(data), data_(data),
data_size_(data_size) {} data_size_(data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE { virtual void Execute() OVERRIDE {
TestBinary(value_, data_, data_size_); TestBinary(value_, data_, data_size_);
} }
@ -295,7 +295,7 @@ class DictionaryTask : public CefTask {
binary_data_(binary_data), binary_data_(binary_data),
binary_data_size_(binary_data_size) {} binary_data_size_(binary_data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE { virtual void Execute() OVERRIDE {
TestDictionary(value_, binary_data_, binary_data_size_); TestDictionary(value_, binary_data_, binary_data_size_);
} }
@ -554,7 +554,7 @@ class ListTask : public CefTask {
binary_data_(binary_data), binary_data_(binary_data),
binary_data_size_(binary_data_size) {} binary_data_size_(binary_data_size) {}
virtual void Execute(CefThreadId threadId) OVERRIDE { virtual void Execute() OVERRIDE {
TestList(value_, binary_data_, binary_data_size_); TestList(value_, binary_data_, binary_data_size_);
} }