Add CefThread interface (issue #1632)
This commit is contained in:
parent
607d420baf
commit
18d56feac0
4
BUILD.gn
4
BUILD.gn
|
@ -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",
|
||||
]
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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_
|
|
@ -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_
|
|
@ -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
|
||||
|
||||
///
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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_
|
|
@ -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;
|
|
@ -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_
|
|
@ -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;
|
|
@ -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_
|
|
@ -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));
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue