Add CefThread interface (issue #1632)

This commit is contained in:
Marshall Greenblatt 2016-11-11 18:22:53 -05:00
parent 607d420baf
commit 18d56feac0
20 changed files with 1318 additions and 41 deletions

View File

@ -463,6 +463,8 @@ static_library("libcef_static") {
"libcef/common/task_runner_impl.cc",
"libcef/common/task_runner_impl.h",
"libcef/common/test/translator_test_impl.cc",
"libcef/common/thread_impl.cc",
"libcef/common/thread_impl.h",
"libcef/common/time_impl.cc",
"libcef/common/time_util.h",
"libcef/common/tracker.cc",
@ -1405,6 +1407,7 @@ cef_unittests_sources = [
"tests/unittests/test_util.h",
"tests/unittests/thread_helper.cc",
"tests/unittests/thread_helper.h",
"tests/unittests/thread_unittest.cc",
"tests/unittests/tracing_unittest.cc",
"tests/unittests/translator_unittest.cc",
"tests/unittests/urlrequest_unittest.cc",
@ -1710,6 +1713,7 @@ if (is_mac) {
"tests/unittests/test_util.h",
"tests/unittests/thread_helper.cc",
"tests/unittests/thread_helper.h",
"tests/unittests/thread_unittest.cc",
"tests/unittests/tracing_unittest.cc",
"tests/unittests/v8_unittest.cc",
]

View File

@ -65,6 +65,7 @@
'include/cef_stream.h',
'include/cef_string_visitor.h',
'include/cef_task.h',
'include/cef_thread.h',
'include/cef_trace.h',
'include/cef_urlrequest.h',
'include/cef_v8.h',
@ -149,6 +150,7 @@
'include/capi/cef_stream_capi.h',
'include/capi/cef_string_visitor_capi.h',
'include/capi/cef_task_capi.h',
'include/capi/cef_thread_capi.h',
'include/capi/cef_trace_capi.h',
'include/capi/cef_urlrequest_capi.h',
'include/capi/cef_v8_capi.h',
@ -378,6 +380,8 @@
'libcef_dll/cpptoc/views/textfield_cpptoc.h',
'libcef_dll/ctocpp/views/textfield_delegate_ctocpp.cc',
'libcef_dll/ctocpp/views/textfield_delegate_ctocpp.h',
'libcef_dll/cpptoc/thread_cpptoc.cc',
'libcef_dll/cpptoc/thread_cpptoc.h',
'libcef_dll/cpptoc/test/translator_test_cpptoc.cc',
'libcef_dll/cpptoc/test/translator_test_cpptoc.h',
'libcef_dll/ctocpp/test/translator_test_handler_ctocpp.cc',
@ -636,6 +640,8 @@
'libcef_dll/ctocpp/views/textfield_ctocpp.h',
'libcef_dll/cpptoc/views/textfield_delegate_cpptoc.cc',
'libcef_dll/cpptoc/views/textfield_delegate_cpptoc.h',
'libcef_dll/ctocpp/thread_ctocpp.cc',
'libcef_dll/ctocpp/thread_ctocpp.h',
'libcef_dll/ctocpp/test/translator_test_ctocpp.cc',
'libcef_dll/ctocpp/test/translator_test_ctocpp.h',
'libcef_dll/cpptoc/test/translator_test_handler_cpptoc.cc',

View File

@ -0,0 +1,115 @@
// Copyright (c) 2016 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
// OWNER OR 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.
//
// ---------------------------------------------------------------------------
//
// This file was generated by the CEF translator tool and should not edited
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
#ifndef CEF_INCLUDE_CAPI_CEF_THREAD_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_THREAD_CAPI_H_
#pragma once
#include "include/capi/cef_task_capi.h"
#include "include/internal/cef_thread_internal.h"
#ifdef __cplusplus
extern "C" {
#endif
///
// A simple thread abstraction that establishes a message loop on a new thread.
// The consumer uses cef_task_tRunner to execute code on the thread's message
// loop. The thread is terminated when the cef_thread_t object is destroyed or
// stop() is called. All pending tasks queued on the thread's message loop will
// run to completion before the thread is terminated. cef_thread_create() can be
// called on any valid CEF thread in either the browser or render process. This
// structure should only be used for tasks that require a dedicated thread. In
// most cases you can post tasks to an existing CEF thread instead of creating a
// new one; see cef_task.h for details.
///
typedef struct _cef_thread_t {
///
// Base structure.
///
cef_base_t base;
///
// Returns the cef_task_tRunner that will execute code on this thread's
// message loop. This function is safe to call from any thread.
///
struct _cef_task_runner_t* (CEF_CALLBACK *get_task_runner)(
struct _cef_thread_t* self);
///
// Returns the platform thread ID. It will return the same value after stop()
// is called. This function is safe to call from any thread.
///
cef_platform_thread_id_t (CEF_CALLBACK *get_platform_thread_id)(
struct _cef_thread_t* self);
///
// Stop and join the thread. This function must be called from the same thread
// that called cef_thread_create(). Do not call this function if
// cef_thread_create() was called with a |stoppable| value of false (0).
///
void (CEF_CALLBACK *stop)(struct _cef_thread_t* self);
///
// Returns true (1) if the thread is currently running. This function must be
// called from the same thread that called cef_thread_create().
///
int (CEF_CALLBACK *is_running)(struct _cef_thread_t* self);
} cef_thread_t;
///
// Create and start a new thread. This function does not block waiting for the
// thread to run initialization. |display_name| is the name that will be used to
// identify the thread. |priority| is the thread execution priority.
// |message_loop_type| indicates the set of asynchronous events that the thread
// can process. If |stoppable| is true (1) the thread will stopped and joined on
// destruction or when stop() is called; otherwise, the the thread cannot be
// stopped and will be leaked on shutdown. On Windows the |com_init_mode| value
// specifies how COM will be initialized for the thread. If |com_init_mode| is
// set to COM_INIT_MODE_STA then |message_loop_type| must be set to ML_TYPE_UI.
///
CEF_EXPORT cef_thread_t* cef_thread_create(const cef_string_t* display_name,
cef_thread_priority_t priority, cef_message_loop_type_t message_loop_type,
int stoppable, cef_com_init_mode_t com_init_mode);
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_THREAD_CAPI_H_

117
include/cef_thread.h Normal file
View File

@ -0,0 +1,117 @@
// Copyright (c) 2016 Marshall A. Greenblatt. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * 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.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
// OWNER OR 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.
//
// ---------------------------------------------------------------------------
//
// The contents of this file must follow a specific format in order to
// support the CEF translator tool. See the translator.README.txt file in the
// tools directory for more information.
//
#ifndef CEF_INCLUDE_CEF_THREAD_H_
#define CEF_INCLUDE_CEF_THREAD_H_
#pragma once
#include "include/cef_task.h"
#include "include/internal/cef_thread_internal.h"
///
// A simple thread abstraction that establishes a message loop on a new thread.
// The consumer uses CefTaskRunner to execute code on the thread's message loop.
// The thread is terminated when the CefThread object is destroyed or Stop() is
// called. All pending tasks queued on the thread's message loop will run to
// completion before the thread is terminated. CreateThread() can be called on
// any valid CEF thread in either the browser or render process. This class
// should only be used for tasks that require a dedicated thread. In most cases
// you can post tasks to an existing CEF thread instead of creating a new one;
// see cef_task.h for details.
///
/*--cef(source=library)--*/
class CefThread : public CefBase {
public:
///
// Create and start a new thread. This method does not block waiting for the
// thread to run initialization. |display_name| is the name that will be used
// to identify the thread. |priority| is the thread execution priority.
// |message_loop_type| indicates the set of asynchronous events that the
// thread can process. If |stoppable| is true the thread will stopped and
// joined on destruction or when Stop() is called; otherwise, the the thread
// cannot be stopped and will be leaked on shutdown. On Windows the
// |com_init_mode| value specifies how COM will be initialized for the thread.
// If |com_init_mode| is set to COM_INIT_MODE_STA then |message_loop_type|
// must be set to ML_TYPE_UI.
///
/*--cef(optional_param=display_name)--*/
static CefRefPtr<CefThread> CreateThread(
const CefString& display_name,
cef_thread_priority_t priority,
cef_message_loop_type_t message_loop_type,
bool stoppable,
cef_com_init_mode_t com_init_mode);
///
// Create and start a new thread with default/recommended values.
// |display_name| is the name that will be used to identify the thread.
///
static CefRefPtr<CefThread> CreateThread(const CefString& display_name) {
return CreateThread(display_name, TP_NORMAL, ML_TYPE_DEFAULT, true,
COM_INIT_MODE_NONE);
}
///
// Returns the CefTaskRunner that will execute code on this thread's message
// loop. This method is safe to call from any thread.
///
/*--cef()--*/
virtual CefRefPtr<CefTaskRunner> GetTaskRunner() =0;
///
// Returns the platform thread ID. It will return the same value after Stop()
// is called. This method is safe to call from any thread.
///
/*--cef(default_retval=kInvalidPlatformThreadId)--*/
virtual cef_platform_thread_id_t GetPlatformThreadId() =0;
///
// Stop and join the thread. This method must be called from the same thread
// that called CreateThread(). Do not call this method if CreateThread() was
// called with a |stoppable| value of false.
///
/*--cef()--*/
virtual void Stop() =0;
///
// Returns true if the thread is currently running. This method must be called
// from the same thread that called CreateThread().
///
/*--cef()--*/
virtual bool IsRunning() =0;
};
#endif // CEF_INCLUDE_CEF_THREAD_H_

View File

@ -46,8 +46,10 @@ extern "C" {
#if defined(OS_WIN)
typedef DWORD cef_platform_thread_id_t;
#define kInvalidPlatformThreadId 0U
#elif defined(OS_POSIX)
typedef pid_t cef_platform_thread_id_t;
#define kInvalidPlatformThreadId 0
#endif
///
@ -57,8 +59,10 @@ CEF_EXPORT cef_platform_thread_id_t cef_get_current_platform_thread_id();
#if defined(OS_WIN)
typedef DWORD cef_platform_thread_handle_t;
#define kInvalidPlatformThreadHandle 0U
#elif defined(OS_POSIX)
typedef pthread_t cef_platform_thread_handle_t;
#define kInvalidPlatformThreadHandle 0
#endif
///

View File

@ -1396,6 +1396,73 @@ typedef enum {
TID_RENDERER,
} cef_thread_id_t;
///
// Thread priority values listed in increasing order of importance.
///
typedef enum {
///
// Suitable for threads that shouldn't disrupt high priority work.
///
TP_BACKGROUND,
///
// Default priority level.
///
TP_NORMAL,
///
// Suitable for threads which generate data for the display (at ~60Hz).
///
TP_DISPLAY,
///
// Suitable for low-latency, glitch-resistant audio.
///
TP_REALTIME_AUDIO,
} cef_thread_priority_t;
///
// Message loop types. Indicates the set of asynchronous events that a message
// loop can process.
///
typedef enum {
///
// Supports tasks and timers.
///
ML_TYPE_DEFAULT,
///
// Supports tasks, timers and native UI events (e.g. Windows messages).
///
ML_TYPE_UI,
///
// Supports tasks, timers and asynchronous IO events.
///
ML_TYPE_IO,
} cef_message_loop_type_t;
///
// Windows COM initialization mode. Specifies how COM will be initialized for a
// new thread.
///
typedef enum {
///
// No COM initialization.
///
COM_INIT_MODE_NONE,
///
// Initialize COM using single-threaded apartments.
///
COM_INIT_MODE_STA,
///
// Initialize COM using multi-threaded apartments.
///
COM_INIT_MODE_MTA,
} cef_com_init_mode_t;
///
// Supported value types.
///

View File

@ -0,0 +1,148 @@
// Copyright 2016 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/thread_impl.h"
#include "libcef/common/task_runner_impl.h"
#include "base/bind.h"
#include "base/threading/thread_restrictions.h"
namespace {
void StopAndDestroy(base::Thread* thread) {
// Calling PlatformThread::Join() on the UI thread is otherwise disallowed.
base::ThreadRestrictions::ScopedAllowIO scoped_allow_io;
// Deleting |thread| will implicitly stop and join it.
delete thread;
}
} // namespace
// static
CefRefPtr<CefThread> CefThread::CreateThread(
const CefString& display_name,
cef_thread_priority_t priority,
cef_message_loop_type_t message_loop_type,
bool stoppable,
cef_com_init_mode_t com_init_mode) {
if (!base::MessageLoop::current()) {
NOTREACHED() << "called on invalid thread";
return nullptr;
}
CefRefPtr<CefThreadImpl> thread_impl = new CefThreadImpl();
if (!thread_impl->Create(display_name, priority, message_loop_type, stoppable,
com_init_mode)) {
return nullptr;
}
return thread_impl;
}
CefThreadImpl::CefThreadImpl()
: thread_id_(kInvalidPlatformThreadId) {
}
CefThreadImpl::~CefThreadImpl() {
if (thread_.get()) {
if (!owner_task_runner_->RunsTasksOnCurrentThread()) {
// Delete |thread_| on the correct thread.
owner_task_runner_->PostTask(FROM_HERE,
base::Bind(StopAndDestroy, base::Unretained(thread_.release())));
} else {
StopAndDestroy(thread_.release());
}
}
}
bool CefThreadImpl::Create(const CefString& display_name,
cef_thread_priority_t priority,
cef_message_loop_type_t message_loop_type,
bool stoppable,
cef_com_init_mode_t com_init_mode) {
owner_task_runner_ = CefTaskRunnerImpl::GetCurrentTaskRunner();
DCHECK(owner_task_runner_);
if (!owner_task_runner_)
return false;
thread_.reset(new base::Thread(display_name));
base::Thread::Options options;
switch (priority) {
case TP_BACKGROUND:
options.priority = base::ThreadPriority::BACKGROUND;
break;
case TP_DISPLAY:
options.priority = base::ThreadPriority::DISPLAY;
break;
case TP_REALTIME_AUDIO:
options.priority = base::ThreadPriority::REALTIME_AUDIO;
break;
default:
break;
}
switch (message_loop_type) {
case ML_TYPE_UI:
options.message_loop_type = base::MessageLoop::TYPE_UI;
break;
case ML_TYPE_IO:
options.message_loop_type = base::MessageLoop::TYPE_IO;
break;
default:
break;
}
options.joinable = stoppable;
#if defined(OS_WIN)
if (com_init_mode != COM_INIT_MODE_NONE) {
if (com_init_mode == COM_INIT_MODE_STA)
options.message_loop_type = base::MessageLoop::TYPE_UI;
thread_->init_com_with_mta(com_init_mode == COM_INIT_MODE_MTA);
}
#endif
if (!thread_->StartWithOptions(options)) {
thread_.reset();
return false;
}
thread_task_runner_ = new CefTaskRunnerImpl(thread_->task_runner());
thread_id_ = thread_->GetThreadId();
return true;
}
CefRefPtr<CefTaskRunner> CefThreadImpl::GetTaskRunner() {
return thread_task_runner_;
}
cef_platform_thread_id_t CefThreadImpl::GetPlatformThreadId() {
return thread_id_;
}
void CefThreadImpl::Stop() {
if (!owner_task_runner_)
return;
if (!owner_task_runner_->RunsTasksOnCurrentThread()) {
NOTREACHED() << "called on invalid thread";
return;
}
if (thread_)
StopAndDestroy(thread_.release());
}
bool CefThreadImpl::IsRunning() {
if (!owner_task_runner_)
return false;
if (!owner_task_runner_->RunsTasksOnCurrentThread()) {
NOTREACHED() << "called on invalid thread";
return false;
}
return thread_ && thread_->IsRunning();
}

View File

@ -0,0 +1,41 @@
// Copyright 2016 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_THREAD_IMPL_H_
#define CEF_LIBCEF_COMMON_THREAD_IMPL_H_
#pragma once
#include "include/cef_thread.h"
#include "base/threading/thread.h"
class CefThreadImpl : public CefThread {
public:
CefThreadImpl();
~CefThreadImpl();
bool Create(const CefString& display_name,
cef_thread_priority_t priority,
cef_message_loop_type_t message_loop_type,
bool stoppable,
cef_com_init_mode_t com_init_mode);
// CefThread methods:
CefRefPtr<CefTaskRunner> GetTaskRunner() override;
cef_platform_thread_id_t GetPlatformThreadId() override;
void Stop() override;
bool IsRunning() override;
private:
std::unique_ptr<base::Thread> thread_;
cef_platform_thread_id_t thread_id_;
CefRefPtr<CefTaskRunner> thread_task_runner_;
// TaskRunner for the owner thread.
scoped_refptr<base::SequencedTaskRunner> owner_task_runner_;
IMPLEMENT_REFCOUNTING(CefThreadImpl);
DISALLOW_COPY_AND_ASSIGN(CefThreadImpl);
};
#endif // CEF_LIBCEF_COMMON_THREAD_IMPL_H_

View File

@ -0,0 +1,124 @@
// Copyright (c) 2016 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/cpptoc/thread_cpptoc.h"
// GLOBAL FUNCTIONS - Body may be edited by hand.
CEF_EXPORT cef_thread_t* cef_thread_create(const cef_string_t* display_name,
cef_thread_priority_t priority, cef_message_loop_type_t message_loop_type,
int stoppable, cef_com_init_mode_t com_init_mode) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: display_name
// Execute
CefRefPtr<CefThread> _retval = CefThread::CreateThread(
CefString(display_name),
priority,
message_loop_type,
stoppable?true:false,
com_init_mode);
// Return type: refptr_same
return CefThreadCppToC::Wrap(_retval);
}
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
cef_task_runner_t* CEF_CALLBACK thread_get_task_runner(
struct _cef_thread_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return NULL;
// Execute
CefRefPtr<CefTaskRunner> _retval = CefThreadCppToC::Get(self)->GetTaskRunner(
);
// Return type: refptr_same
return CefTaskRunnerCppToC::Wrap(_retval);
}
cef_platform_thread_id_t CEF_CALLBACK thread_get_platform_thread_id(
struct _cef_thread_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return kInvalidPlatformThreadId;
// Execute
cef_platform_thread_id_t _retval = CefThreadCppToC::Get(
self)->GetPlatformThreadId();
// Return type: simple
return _retval;
}
void CEF_CALLBACK thread_stop(struct _cef_thread_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return;
// Execute
CefThreadCppToC::Get(self)->Stop();
}
int CEF_CALLBACK thread_is_running(struct _cef_thread_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self)
return 0;
// Execute
bool _retval = CefThreadCppToC::Get(self)->IsRunning();
// Return type: bool
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefThreadCppToC::CefThreadCppToC() {
GetStruct()->get_task_runner = thread_get_task_runner;
GetStruct()->get_platform_thread_id = thread_get_platform_thread_id;
GetStruct()->stop = thread_stop;
GetStruct()->is_running = thread_is_running;
}
template<> CefRefPtr<CefThread> CefCppToC<CefThreadCppToC, CefThread,
cef_thread_t>::UnwrapDerived(CefWrapperType type, cef_thread_t* s) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCppToC<CefThreadCppToC, CefThread,
cef_thread_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCppToC<CefThreadCppToC, CefThread,
cef_thread_t>::kWrapperType = WT_THREAD;

View File

@ -0,0 +1,34 @@
// Copyright (c) 2016 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_THREAD_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_THREAD_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_thread.h"
#include "include/capi/cef_thread_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 CefThreadCppToC
: public CefCppToC<CefThreadCppToC, CefThread, cef_thread_t> {
public:
CefThreadCppToC();
};
#endif // BUILDING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CPPTOC_THREAD_CPPTOC_H_

View File

@ -0,0 +1,112 @@
// Copyright (c) 2016 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/ctocpp/task_runner_ctocpp.h"
#include "libcef_dll/ctocpp/thread_ctocpp.h"
// STATIC METHODS - Body may be edited by hand.
CefRefPtr<CefThread> CefThread::CreateThread(const CefString& display_name,
cef_thread_priority_t priority, cef_message_loop_type_t message_loop_type,
bool stoppable, cef_com_init_mode_t com_init_mode) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Unverified params: display_name
// Execute
cef_thread_t* _retval = cef_thread_create(
display_name.GetStruct(),
priority,
message_loop_type,
stoppable,
com_init_mode);
// Return type: refptr_same
return CefThreadCToCpp::Wrap(_retval);
}
// VIRTUAL METHODS - Body may be edited by hand.
CefRefPtr<CefTaskRunner> CefThreadCToCpp::GetTaskRunner() {
cef_thread_t* _struct = GetStruct();
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);
}
cef_platform_thread_id_t CefThreadCToCpp::GetPlatformThreadId() {
cef_thread_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_platform_thread_id))
return kInvalidPlatformThreadId;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
cef_platform_thread_id_t _retval = _struct->get_platform_thread_id(_struct);
// Return type: simple
return _retval;
}
void CefThreadCToCpp::Stop() {
cef_thread_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, stop))
return;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->stop(_struct);
}
bool CefThreadCToCpp::IsRunning() {
cef_thread_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_running))
return false;
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->is_running(_struct);
// Return type: bool
return _retval?true:false;
}
// CONSTRUCTOR - Do not edit by hand.
CefThreadCToCpp::CefThreadCToCpp() {
}
template<> cef_thread_t* CefCToCpp<CefThreadCToCpp, CefThread,
cef_thread_t>::UnwrapDerived(CefWrapperType type, CefThread* c) {
NOTREACHED() << "Unexpected class type: " << type;
return NULL;
}
#if DCHECK_IS_ON()
template<> base::AtomicRefCount CefCToCpp<CefThreadCToCpp, CefThread,
cef_thread_t>::DebugObjCt = 0;
#endif
template<> CefWrapperType CefCToCpp<CefThreadCToCpp, CefThread,
cef_thread_t>::kWrapperType = WT_THREAD;

View File

@ -0,0 +1,40 @@
// Copyright (c) 2016 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_THREAD_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_THREAD_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_thread.h"
#include "include/capi/cef_thread_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 CefThreadCToCpp
: public CefCToCpp<CefThreadCToCpp, CefThread, cef_thread_t> {
public:
CefThreadCToCpp();
// CefThread methods.
CefRefPtr<CefTaskRunner> GetTaskRunner() OVERRIDE;
cef_platform_thread_id_t GetPlatformThreadId() OVERRIDE;
void Stop() OVERRIDE;
bool IsRunning() OVERRIDE;
};
#endif // USING_CEF_SHARED
#endif // CEF_LIBCEF_DLL_CTOCPP_THREAD_CTOCPP_H_

View File

@ -80,6 +80,7 @@
#include "libcef_dll/cpptoc/stream_writer_cpptoc.h"
#include "libcef_dll/cpptoc/task_runner_cpptoc.h"
#include "libcef_dll/cpptoc/views/textfield_cpptoc.h"
#include "libcef_dll/cpptoc/thread_cpptoc.h"
#include "libcef_dll/cpptoc/urlrequest_cpptoc.h"
#include "libcef_dll/cpptoc/v8context_cpptoc.h"
#include "libcef_dll/cpptoc/v8exception_cpptoc.h"
@ -321,6 +322,7 @@ CEF_EXPORT void cef_shutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefTextfieldCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefTextfieldDelegateCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefThreadCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCToCpp::DebugObjCt));

View File

@ -134,6 +134,7 @@
#include "libcef_dll/ctocpp/stream_writer_ctocpp.h"
#include "libcef_dll/ctocpp/task_runner_ctocpp.h"
#include "libcef_dll/ctocpp/views/textfield_ctocpp.h"
#include "libcef_dll/ctocpp/thread_ctocpp.h"
#include "libcef_dll/ctocpp/urlrequest_ctocpp.h"
#include "libcef_dll/ctocpp/v8context_ctocpp.h"
#include "libcef_dll/ctocpp/v8exception_ctocpp.h"
@ -313,6 +314,7 @@ CEF_GLOBAL void CefShutdown() {
DCHECK(base::AtomicRefCountIsZero(&CefTaskRunnerCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefTextfieldCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefTextfieldDelegateCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefThreadCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefURLRequestCToCpp::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefURLRequestClientCppToC::DebugObjCt));
DCHECK(base::AtomicRefCountIsZero(&CefV8AccessorCppToC::DebugObjCt));

View File

@ -115,6 +115,7 @@ enum CefWrapperType {
WT_TASK_RUNNER,
WT_TEXTFIELD,
WT_TEXTFIELD_DELEGATE,
WT_THREAD,
WT_TRANSLATOR_TEST,
WT_TRANSLATOR_TEST_HANDLER,
WT_TRANSLATOR_TEST_HANDLER_CHILD,

View File

@ -81,6 +81,11 @@ void CreateRenderDelegates(ClientAppRenderer::DelegateSet& delegates) {
ClientAppRenderer::DelegateSet& delegates);
CreateRoutingTestHandlerDelegate(delegates);
// Bring in the thread tests.
extern void CreateThreadRendererTests(
ClientAppRenderer::DelegateSet& delegates);
CreateThreadRendererTests(delegates);
// Bring in the URLRequest tests.
extern void CreateURLRequestRendererTests(
ClientAppRenderer::DelegateSet& delegates);

View File

@ -11,11 +11,10 @@
#undef Bool
#endif
#include "base/threading/thread.h"
#include "include/base/cef_bind.h"
#include "include/cef_app.h"
#include "include/cef_task.h"
#include "include/cef_thread.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_closure_task.h"
#include "tests/cefclient/browser/client_app_browser.h"
@ -32,6 +31,12 @@
namespace {
// Used to track state when running tests on a separate thread.
struct TestState {
CefTestSuite* test_suite_;
int retval_;
};
void QuitMessageLoop() {
client::MainMessageLoop* message_loop = client::MainMessageLoop::Get();
if (message_loop)
@ -40,38 +45,28 @@ void QuitMessageLoop() {
CefQuitMessageLoop();
}
// Thread used to run the test suite.
class CefTestThread : public base::Thread {
public:
explicit CefTestThread(CefTestSuite* test_suite)
: base::Thread("test_thread"),
test_suite_(test_suite) {
}
// Called on the test thread.
void RunTestsOnTestThread(TestState* test_state) {
CHECK(test_state);
void RunTests() {
// Run the test suite.
retval_ = test_suite_->Run();
// Run the test suite.
test_state->retval_ = test_state->test_suite_->Run();
// Wait for all browsers to exit.
while (TestHandler::HasBrowser())
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
// Wait for all browsers to exit.
while (TestHandler::HasBrowser())
base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
// Quit the CEF message loop.
CefPostTask(TID_UI, base::Bind(&QuitMessageLoop));
}
int retval() { return retval_; }
protected:
CefTestSuite* test_suite_;
int retval_;
};
// Quit the CEF message loop.
CefPostTask(TID_UI, base::Bind(&QuitMessageLoop));
}
// Called on the UI thread.
void RunTests(CefTestThread* thread) {
void ContinueOnUIThread(TestState* test_state,
CefRefPtr<CefTaskRunner> test_task_runner) {
// Run the test suite on the test thread.
thread->message_loop()->task_runner()->PostTask(FROM_HERE,
base::Bind(&CefTestThread::RunTests, base::Unretained(thread)));
test_task_runner->PostTask(
CefCreateClosureTask(base::Bind(&RunTestsOnTestThread,
base::Unretained(test_state))));
}
#if defined(OS_LINUX)
@ -189,24 +184,29 @@ int main(int argc, char* argv[]) {
// Run the test suite on the main thread.
retval = test_suite.Run();
} else {
// Create the test thread.
std::unique_ptr<CefTestThread> thread;
thread.reset(new CefTestThread(&test_suite));
if (!thread->Start())
TestState test_state = {0};
test_state.test_suite_ = &test_suite;
// Create and start the test thread.
CefRefPtr<CefThread> thread = CefThread::CreateThread("test_thread");
if (!thread)
return 1;
// Start the tests from the UI thread so that any pending UI tasks get a
// chance to execute first.
CefPostTask(TID_UI, base::Bind(&RunTests, thread.get()));
CefPostTask(TID_UI,
base::Bind(&ContinueOnUIThread, base::Unretained(&test_state),
thread->GetTaskRunner()));
// Run the CEF message loop.
message_loop->Run();
// The test suite has completed.
retval = thread->retval();
retval = test_state.retval_;
// Terminate the test thread.
thread.reset();
thread->Stop();
thread = nullptr;
}
// Shut down CEF.

View File

@ -0,0 +1,440 @@
// Copyright 2016 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/base/cef_bind.h"
#include "include/cef_task.h"
#include "include/cef_thread.h"
#include "include/wrapper/cef_closure_task.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "tests/cefclient/browser/client_app_browser.h"
#include "tests/cefclient/renderer/client_app_renderer.h"
#include "tests/unittests/test_handler.h"
using client::ClientAppBrowser;
using client::ClientAppRenderer;
namespace {
// Base class for creating and testing threads.
class ThreadTest : public base::RefCountedThreadSafe<ThreadTest> {
public:
ThreadTest() {}
virtual ~ThreadTest() {}
// Create the test thread. Should only be called one time.
void CreateTestThread() {
EXPECT_TRUE(!thread_.get());
owner_task_runner_ = CefTaskRunner::GetForCurrentThread();
EXPECT_TRUE(owner_task_runner_.get());
EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
thread_ = CefThread::CreateThread("test_thread");
EXPECT_TRUE(thread_.get());
EXPECT_TRUE(thread_->IsRunning());
thread_id_ = thread_->GetPlatformThreadId();
EXPECT_NE(thread_id_, kInvalidPlatformThreadId);
thread_task_runner_ = thread_->GetTaskRunner();
EXPECT_TRUE(thread_task_runner_.get());
AssertOwnerThread();
}
// Destroy the test thread. Should only be called one time.
void DestroyTestThread() {
EXPECT_TRUE(thread_.get());
AssertOwnerThread();
EXPECT_TRUE(thread_->IsRunning());
thread_->Stop();
EXPECT_FALSE(thread_->IsRunning());
AssertOwnerThread();
thread_ = nullptr;
}
// Execute |test_task| on the test thread. After execution |callback| will be
// posted to |callback_task_runner|.
void PostOnTestThreadAndCallback(
const base::Closure& test_task,
CefRefPtr<CefTaskRunner> callback_task_runner,
const base::Closure& callback) {
EXPECT_TRUE(thread_.get());
thread_task_runner_->PostTask(CefCreateClosureTask(
base::Bind(&ThreadTest::ExecuteOnTestThread, this, test_task,
callback_task_runner, callback)));
}
CefRefPtr<CefTaskRunner> owner_task_runner() const {
return owner_task_runner_;
}
CefRefPtr<CefTaskRunner> thread_task_runner() const {
return thread_task_runner_;
}
// Assert that we're running on the owner thread.
void AssertOwnerThread() {
EXPECT_TRUE(owner_task_runner_->BelongsToCurrentThread());
EXPECT_FALSE(thread_task_runner_->BelongsToCurrentThread());
EXPECT_TRUE(thread_task_runner_->IsSame(thread_->GetTaskRunner()));
EXPECT_EQ(thread_id_, thread_->GetPlatformThreadId());
}
// Assert that we're running on the test thread.
void AssertTestThread() {
EXPECT_FALSE(owner_task_runner_->BelongsToCurrentThread());
EXPECT_TRUE(thread_task_runner_->BelongsToCurrentThread());
EXPECT_TRUE(thread_task_runner_->IsSame(thread_->GetTaskRunner()));
EXPECT_EQ(thread_id_, thread_->GetPlatformThreadId());
}
private:
// Helper for PostOnTestThreadAndCallback().
void ExecuteOnTestThread(const base::Closure& test_task,
CefRefPtr<CefTaskRunner> callback_task_runner,
const base::Closure& callback) {
AssertTestThread();
test_task.Run();
callback_task_runner->PostTask(CefCreateClosureTask(callback));
}
CefRefPtr<CefTaskRunner> owner_task_runner_;
CefRefPtr<CefThread> thread_;
cef_platform_thread_id_t thread_id_;
CefRefPtr<CefTaskRunner> thread_task_runner_;
DISALLOW_COPY_AND_ASSIGN(ThreadTest);
};
} // namespace
// Test thread creation and destruction without any task execution.
TEST(ThreadTest, Create) {
scoped_refptr<ThreadTest> thread_test = new ThreadTest();
thread_test->CreateTestThread();
thread_test->DestroyTestThread();
thread_test = nullptr;
}
namespace {
// Simple implementation of ThreadTest that creates a thread, executes tasks
// on the thread, then destroys the thread after all tasks have completed.
class SimpleThreadTest : public ThreadTest {
public:
SimpleThreadTest(size_t expected_task_count,
const base::Closure& task_callback,
const base::Closure& done_callback)
: expected_task_count_(expected_task_count),
task_callback_(task_callback),
done_callback_(done_callback),
got_task_count_(0U),
got_done_count_(0U) {}
void RunTest() {
// Create the test thread.
CreateTestThread();
for (size_t i = 0U; i < expected_task_count_; ++i) {
// Execute Task() on the test thread and then call Done() on this thread.
PostOnTestThreadAndCallback(
base::Bind(&SimpleThreadTest::Task, this), owner_task_runner(),
base::Bind(&SimpleThreadTest::Done, this));
}
}
void DestroyTest() {
EXPECT_EQ(expected_task_count_, got_task_count_);
EXPECT_EQ(expected_task_count_, got_done_count_);
// Destroy the test thread.
DestroyTestThread();
}
private:
void Task() {
AssertTestThread();
got_task_count_++;
if (!task_callback_.is_null())
task_callback_.Run();
}
void Done() {
AssertOwnerThread();
if (++got_done_count_ == expected_task_count_ && !done_callback_.is_null())
done_callback_.Run();
}
const size_t expected_task_count_;
base::Closure task_callback_;
base::Closure done_callback_;
size_t got_task_count_;
size_t got_done_count_;
DISALLOW_COPY_AND_ASSIGN(SimpleThreadTest);
};
// Test creation/execution of threads in the browser process.
const char kBrowserThreadTestHtml[] = "http://test.com/browserthread.html";
// Browser side.
class BrowserThreadTestHandler : public TestHandler {
public:
explicit BrowserThreadTestHandler(CefThreadId owner_thread_id)
: owner_thread_id_(owner_thread_id) {}
void RunTest() override {
AddResource(kBrowserThreadTestHtml, "<html><body>Test</body></html>",
"text/html");
CreateBrowser(kBrowserThreadTestHtml);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
void RunThreadTestOnOwnerThread() {
if (!CefCurrentlyOn(owner_thread_id_)) {
// Run the test on the desired owner thread.
CefPostTask(owner_thread_id_,
base::Bind(&BrowserThreadTestHandler::RunThreadTestOnOwnerThread,
this));
return;
}
EXPECT_FALSE(thread_test_.get());
thread_test_ = new SimpleThreadTest(
3, base::Closure(),
base::Bind(&BrowserThreadTestHandler::DoneOnOwnerThread, this));
thread_test_->RunTest();
}
void DoneOnOwnerThread() {
// Let the call stack unwind before destroying |thread_test_|.
CefPostTask(owner_thread_id_,
base::Bind(&BrowserThreadTestHandler::DestroyTestOnOwnerThread, this));
}
void DestroyTestOnOwnerThread() {
EXPECT_TRUE(CefCurrentlyOn(owner_thread_id_));
EXPECT_TRUE(thread_test_.get());
if (thread_test_) {
thread_test_->DestroyTest();
thread_test_ = nullptr;
}
got_test_done_.yes();
// Call DestroyTest() on the UI thread.
CefPostTask(TID_UI,
base::Bind(&BrowserThreadTestHandler::DestroyTest, this));
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
if (!isLoading)
RunThreadTestOnOwnerThread();
}
private:
void DestroyTest() override {
EXPECT_FALSE(thread_test_.get());
EXPECT_TRUE(got_test_done_);
TestHandler::DestroyTest();
}
const CefThreadId owner_thread_id_;
scoped_refptr<SimpleThreadTest> thread_test_;
TrackCallback got_test_done_;
IMPLEMENT_REFCOUNTING(BrowserThreadTestHandler);
DISALLOW_COPY_AND_ASSIGN(BrowserThreadTestHandler);
};
} // namespace
// Test creation of new threads from the browser UI thread.
TEST(ThreadTest, CreateFromBrowserUIThread) {
CefRefPtr<BrowserThreadTestHandler> handler =
new BrowserThreadTestHandler(TID_UI);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test creation of new threads from the browser IO thread.
TEST(ThreadTest, CreateFromBrowserIOThread) {
CefRefPtr<BrowserThreadTestHandler> handler =
new BrowserThreadTestHandler(TID_IO);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Test creation of new threads from the browser FILE thread.
TEST(ThreadTest, CreateFromBrowserFILEThread) {
CefRefPtr<BrowserThreadTestHandler> handler =
new BrowserThreadTestHandler(TID_FILE);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
namespace {
// Test creation/execution of threads in the render process.
const char kRenderThreadTestHtml[] = "http://test.com/renderthread.html";
const char kRenderThreadTestMsg[] = "ThreadTest.RenderThreadTest";
// Browser side.
class RenderThreadTestHandler : public TestHandler {
public:
RenderThreadTestHandler() {}
void RunTest() override {
AddResource(kRenderThreadTestHtml, "<html><body>Test</body></html>",
"text/html");
CreateBrowser(kRenderThreadTestHtml);
// Time out the test after a reasonable period of time.
SetTestTimeout();
}
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) override {
if (!isLoading) {
// Return the test in the render process.
CefRefPtr<CefProcessMessage> msg =
CefProcessMessage::Create(kRenderThreadTestMsg);
EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, msg));
}
}
bool OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override {
EXPECT_TRUE(browser.get());
EXPECT_EQ(PID_RENDERER, source_process);
EXPECT_TRUE(message.get());
EXPECT_TRUE(message->IsReadOnly());
const std::string& message_name = message->GetName();
EXPECT_STREQ(kRenderThreadTestMsg, message_name.c_str());
got_message_.yes();
if (message->GetArgumentList()->GetBool(0))
got_success_.yes();
// Test is complete.
DestroyTest();
return true;
}
protected:
void DestroyTest() override {
EXPECT_TRUE(got_message_);
EXPECT_TRUE(got_success_);
TestHandler::DestroyTest();
}
TrackCallback got_message_;
TrackCallback got_success_;
IMPLEMENT_REFCOUNTING(RenderThreadTestHandler);
DISALLOW_COPY_AND_ASSIGN(RenderThreadTestHandler);
};
// Renderer side.
class RenderThreadRendererTest : public ClientAppRenderer::Delegate {
public:
RenderThreadRendererTest() {}
bool OnProcessMessageReceived(
CefRefPtr<ClientAppRenderer> app,
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override {
if (message->GetName().ToString() == kRenderThreadTestMsg) {
browser_ = browser;
EXPECT_FALSE(thread_test_.get());
thread_test_ = new SimpleThreadTest(
3, base::Closure(),
base::Bind(&RenderThreadRendererTest::Done, this));
thread_test_->RunTest();
return true;
}
// Message not handled.
return false;
}
private:
void Done() {
// Let the call stack unwind before destroying |thread_test_|.
CefPostTask(TID_RENDERER,
base::Bind(&RenderThreadRendererTest::DestroyTest, this));
}
void DestroyTest() {
EXPECT_TRUE(thread_test_.get());
if (thread_test_) {
thread_test_->DestroyTest();
thread_test_ = nullptr;
}
// Check if the test has failed.
bool result = !TestFailed();
// Return the result to the browser process.
CefRefPtr<CefProcessMessage> return_msg =
CefProcessMessage::Create(kRenderThreadTestMsg);
EXPECT_TRUE(return_msg->GetArgumentList()->SetBool(0, result));
EXPECT_TRUE(browser_->SendProcessMessage(PID_BROWSER, return_msg));
browser_ = nullptr;
}
CefRefPtr<CefBrowser> browser_;
scoped_refptr<SimpleThreadTest> thread_test_;
IMPLEMENT_REFCOUNTING(RenderThreadRendererTest);
DISALLOW_COPY_AND_ASSIGN(RenderThreadRendererTest);
};
} // namespace
TEST(ThreadTest, CreateFromRenderThread) {
CefRefPtr<RenderThreadTestHandler> handler = new RenderThreadTestHandler();
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Entry point for creating request handler renderer test objects.
// Called from client_app_delegates.cc.
void CreateThreadRendererTests(
ClientAppRenderer::DelegateSet& delegates) {
delegates.insert(new RenderThreadRendererTest);
}

View File

@ -694,7 +694,7 @@ class obj_header:
return obj_analysis([self], value, named)
def get_defined_structs(self):
""" Return a list of names already defined structure names. """
""" Return a list of already defined structure names. """
return ['cef_print_info_t', 'cef_window_info_t', 'cef_base_t']
def get_capi_translations(self):

View File

@ -90,24 +90,39 @@ def make_capi_header(header, filename):
classes = header.get_classes(filename)
# identify all includes and forward declarations
all_includes = set([])
translated_includes = set([])
internal_includes = set([])
all_declares = set([])
for cls in classes:
includes = cls.get_includes()
for include in includes:
all_includes.add(include)
if include.startswith('base/'):
# base/ headers are C++. They should not be included by
# translated CEF API headers.
raise Exception('Disallowed include of %s.h from %s' % (include, filename))
elif include.startswith('internal/'):
# internal/ headers may be C or C++. Include them as-is.
internal_includes.add(include)
else:
translated_includes.add(include)
declares = cls.get_forward_declares()
for declare in declares:
all_declares.add(header.get_class(declare).get_capi_name())
# output includes
if len(all_includes) > 0:
sorted_includes = sorted(all_includes)
# output translated includes
if len(translated_includes) > 0:
sorted_includes = sorted(translated_includes)
for include in sorted_includes:
result += '#include "include/capi/' + include + '_capi.h"\n'
else:
result += '#include "include/capi/cef_base_capi.h"\n'
# output internal includes
if len(internal_includes) > 0:
sorted_includes = sorted(internal_includes)
for include in sorted_includes:
result += '#include "include/' + include + '.h"\n'
result += \
"""
#ifdef __cplusplus