mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-03-16 12:00:13 +01:00
- Move to a unified thread model for CEF based on the CEF2 implementation.
- Add the ability to post user-defined tasks for execution on CEF threads (issue #25). - Update the CEF swap image. git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@90 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
38ded6eec6
commit
7ffa037988
19
cef.gyp
19
cef.gyp
@ -46,7 +46,6 @@
|
||||
'tests/cefclient/scheme_test.h',
|
||||
'tests/cefclient/string_util.cpp',
|
||||
'tests/cefclient/string_util.h',
|
||||
'tests/cefclient/thread_util.h',
|
||||
'tests/cefclient/uiplugin.cpp',
|
||||
'tests/cefclient/uiplugin.h',
|
||||
'tests/cefclient/uiplugin_test.cpp',
|
||||
@ -208,6 +207,8 @@
|
||||
'libcef_dll/ctocpp/scheme_handler_ctocpp.h',
|
||||
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h',
|
||||
'libcef_dll/ctocpp/task_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/task_ctocpp.h',
|
||||
'libcef_dll/ctocpp/v8handler_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/v8handler_ctocpp.h',
|
||||
'libcef_dll/ctocpp/write_handler_ctocpp.cc',
|
||||
@ -264,6 +265,8 @@
|
||||
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
|
||||
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/stream_writer_ctocpp.h',
|
||||
'libcef_dll/cpptoc/task_cpptoc.cc',
|
||||
'libcef_dll/cpptoc/task_cpptoc.h',
|
||||
'libcef_dll/ctocpp/v8value_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/v8value_ctocpp.h',
|
||||
'libcef_dll/transfer_util.cpp',
|
||||
@ -353,11 +356,21 @@
|
||||
'libcef/browser_webview_delegate.cc',
|
||||
'libcef/browser_webview_delegate.h',
|
||||
'libcef/browser_webview_delegate_win.cc',
|
||||
'libcef/cef_context.cc',
|
||||
'libcef/cef_context.h',
|
||||
'libcef/cef_process.cc',
|
||||
'libcef/cef_process.h',
|
||||
'libcef/cef_process_io_thread.cc',
|
||||
'libcef/cef_process_io_thread.h',
|
||||
'libcef/cef_process_sub_thread.cc',
|
||||
'libcef/cef_process_sub_thread.h',
|
||||
'libcef/cef_process_ui_thread.cc',
|
||||
'libcef/cef_process_ui_thread.h',
|
||||
'libcef/cef_string.c',
|
||||
'libcef/cef_string_list.cc',
|
||||
'libcef/cef_string_map.cc',
|
||||
'libcef/context.cc',
|
||||
'libcef/context.h',
|
||||
'libcef/cef_thread.cc',
|
||||
'libcef/cef_thread.h',
|
||||
'libcef/printing/print_settings.cc',
|
||||
'libcef/printing/print_settings.h',
|
||||
'libcef/printing/win_printing_context.cc',
|
||||
|
@ -54,6 +54,7 @@ class CefSchemeHandler;
|
||||
class CefSchemeHandlerFactory;
|
||||
class CefStreamReader;
|
||||
class CefStreamWriter;
|
||||
class CefTask;
|
||||
class CefV8Handler;
|
||||
class CefV8Value;
|
||||
|
||||
@ -153,6 +154,29 @@ bool CefRegisterScheme(const std::wstring& scheme_name,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory);
|
||||
|
||||
|
||||
typedef cef_thread_id_t CefThreadId;
|
||||
|
||||
// CEF maintains multiple internal threads that are used for handling different
|
||||
// types of tasks. The UI thread creates the browser window and is used for all
|
||||
// interaction with the WebKit rendering engine and V8 JavaScript engine (The
|
||||
// UI thread will be the same as the main application thread if CefInitialize()
|
||||
// was called with a |multi_threaded_message_loop| value of false.) The IO
|
||||
// thread is used for handling schema and network requests. The FILE thread is
|
||||
// used for the application cache and other miscellaneous activities. This
|
||||
// method will return true if called on the specified thread.
|
||||
/*--cef()--*/
|
||||
bool CefCurrentlyOn(CefThreadId threadId);
|
||||
|
||||
// Post a task for execution on the specified thread.
|
||||
/*--cef()--*/
|
||||
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task);
|
||||
|
||||
// Post a task for delayed execution on the specified thread.
|
||||
/*--cef()--*/
|
||||
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
||||
long delay_ms);
|
||||
|
||||
|
||||
// Interface defining the the reference count implementation methods. All
|
||||
// framework classes must implement the CefBase class.
|
||||
class CefBase
|
||||
@ -285,6 +309,16 @@ inline bool operator!=(const CefRect& a, const CefRect& b)
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
// Implement this interface for task execution.
|
||||
/*--cef(source=client)--*/
|
||||
class CefTask : public CefBase
|
||||
{
|
||||
public:
|
||||
// Method that will be executed. |threadId| is the thread executing the call.
|
||||
/*--cef()--*/
|
||||
virtual void Execute(CefThreadId threadId) =0;
|
||||
};
|
||||
|
||||
|
||||
// Class used to represent a browser window. All methods exposed by this class
|
||||
// should be thread safe.
|
||||
|
@ -133,6 +133,24 @@ CEF_EXPORT int cef_register_extension(const wchar_t* extension_name,
|
||||
CEF_EXPORT int cef_register_scheme(const wchar_t* scheme_name,
|
||||
const wchar_t* host_name, struct _cef_scheme_handler_factory_t* factory);
|
||||
|
||||
// CEF maintains multiple internal threads that are used for handling different
|
||||
// types of tasks. The UI thread creates the browser window and is used for all
|
||||
// interaction with the WebKit rendering engine and V8 JavaScript engine (The UI
|
||||
// thread will be the same as the main application thread if cef_initialize()
|
||||
// was called with a |multi_threaded_message_loop| value of false (0).) The IO
|
||||
// thread is used for handling schema and network requests. The FILE thread is
|
||||
// used for the application cache and other miscellaneous activities. This
|
||||
// function will return true (1) if called on the specified thread.
|
||||
CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId);
|
||||
|
||||
// Post a task for execution on the specified thread.
|
||||
CEF_EXPORT int cef_post_task(cef_thread_id_t threadId,
|
||||
struct _cef_task_t* task);
|
||||
|
||||
// Post a task for delayed execution on the specified thread.
|
||||
CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
|
||||
struct _cef_task_t* task, long delay_ms);
|
||||
|
||||
typedef struct _cef_base_t
|
||||
{
|
||||
// Size of the data structure.
|
||||
@ -157,6 +175,19 @@ typedef struct _cef_base_t
|
||||
#define CEF_MEMBER_MISSING(s, f) (!CEF_MEMBER_EXISTS(s, f) || !((s)->f))
|
||||
|
||||
|
||||
// Implement this structure for task execution.
|
||||
typedef struct _cef_task_t
|
||||
{
|
||||
// Base structure.
|
||||
cef_base_t base;
|
||||
|
||||
// Method that will be executed. |threadId| is the thread executing the call.
|
||||
void (CEF_CALLBACK *execute)(struct _cef_task_t* self,
|
||||
cef_thread_id_t threadId);
|
||||
|
||||
} cef_task_t;
|
||||
|
||||
|
||||
// Structure used to represent a browser window. All functions exposed by this
|
||||
// structure should be thread safe.
|
||||
typedef struct _cef_browser_t
|
||||
|
@ -229,6 +229,14 @@ typedef struct _cef_rect_t
|
||||
int height;
|
||||
} cef_rect_t;
|
||||
|
||||
// Existing thread IDs.
|
||||
enum cef_thread_id_t
|
||||
{
|
||||
TID_UI = 0,
|
||||
TID_IO = 1,
|
||||
TID_FILE = 2,
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -408,9 +408,6 @@ WebApplicationCacheHost* BrowserAppCacheSystem::CreateCacheHostForWebKit(
|
||||
|
||||
DCHECK(is_ui_thread());
|
||||
|
||||
// The IO thread needs to be running for this system to work.
|
||||
BrowserResourceLoaderBridge::EnsureIOThread();
|
||||
|
||||
if (!is_initialized())
|
||||
return NULL;
|
||||
return new WebApplicationCacheHostImpl(client, backend_proxy_.get());
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#include "request_impl.h"
|
||||
@ -54,39 +54,38 @@ CefBrowserImpl::CefBrowserImpl(CefWindowInfo& windowInfo, bool popup,
|
||||
|
||||
void CefBrowserImpl::GoBack()
|
||||
{
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleActionView, MENU_ID_NAV_BACK));
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleActionView, MENU_ID_NAV_BACK));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::GoForward()
|
||||
{
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleActionView, MENU_ID_NAV_FORWARD));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Reload()
|
||||
{
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleActionView, MENU_ID_NAV_RELOAD));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::StopLoad()
|
||||
{
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleActionView, MENU_ID_NAV_STOP));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::SetFocus(bool enable)
|
||||
{
|
||||
if (_Context->RunningOnUIThread())
|
||||
if (CefThread::CurrentlyOn(CefThread::UI))
|
||||
{
|
||||
UIT_SetFocus(GetWebViewHost(), enable);
|
||||
}
|
||||
else
|
||||
{
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_SetFocus,
|
||||
GetWebViewHost(), enable));
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_SetFocus, GetWebViewHost(), enable));
|
||||
}
|
||||
}
|
||||
|
||||
@ -142,14 +141,14 @@ void CefBrowserImpl::Find(int identifier, const std::wstring& searchText,
|
||||
options.findNext = findNext;
|
||||
|
||||
// Execute the request on the UI thread.
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_Find, identifier, searchText, options));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::StopFinding(bool clearSelection)
|
||||
{
|
||||
// Execute the request on the UI thread.
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_StopFinding, clearSelection));
|
||||
}
|
||||
|
||||
@ -209,49 +208,49 @@ WebFrame* CefBrowserImpl::GetWebFrame(CefRefPtr<CefFrame> frame)
|
||||
void CefBrowserImpl::Undo(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_UNDO, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Redo(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_REDO, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Cut(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_CUT, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Copy(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_COPY, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Paste(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PASTE, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::Delete(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_DELETE, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::SelectAll(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_SELECTALL, frame.get()));
|
||||
}
|
||||
|
||||
@ -259,14 +258,14 @@ void CefBrowserImpl::SelectAll(CefRefPtr<CefFrame> frame)
|
||||
void CefBrowserImpl::Print(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PRINT, frame.get()));
|
||||
}
|
||||
|
||||
void CefBrowserImpl::ViewSource(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_HandleAction, MENU_ID_VIEWSOURCE, frame.get()));
|
||||
}
|
||||
|
||||
@ -276,7 +275,7 @@ void CefBrowserImpl::LoadRequest(CefRefPtr<CefFrame> frame,
|
||||
DCHECK(request.get() != NULL);
|
||||
frame->AddRef();
|
||||
request->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_LoadURLForRequestRef, frame.get(), request.get()));
|
||||
}
|
||||
|
||||
@ -284,7 +283,7 @@ void CefBrowserImpl::LoadURL(CefRefPtr<CefFrame> frame,
|
||||
const std::wstring& url)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_LoadURL, frame.get(), url));
|
||||
}
|
||||
|
||||
@ -293,7 +292,7 @@ void CefBrowserImpl::LoadString(CefRefPtr<CefFrame> frame,
|
||||
const std::wstring& url)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_LoadHTML, frame.get(), string, url));
|
||||
}
|
||||
|
||||
@ -304,7 +303,7 @@ void CefBrowserImpl::LoadStream(CefRefPtr<CefFrame> frame,
|
||||
DCHECK(stream.get() != NULL);
|
||||
frame->AddRef();
|
||||
stream->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_LoadHTMLForStreamRef, frame.get(), stream.get(),
|
||||
url));
|
||||
}
|
||||
@ -315,7 +314,7 @@ void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame,
|
||||
int startLine)
|
||||
{
|
||||
frame->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_ExecuteJavaScript, frame.get(), jsCode, scriptUrl,
|
||||
startLine));
|
||||
}
|
||||
@ -351,7 +350,7 @@ bool CefBrowser::CreateBrowser(CefWindowInfo& windowInfo, bool popup,
|
||||
|
||||
CefRefPtr<CefBrowserImpl> browser(
|
||||
new CefBrowserImpl(windowInfo, popup, handler));
|
||||
PostTask(FROM_HERE, NewRunnableMethod(browser.get(),
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(browser.get(),
|
||||
&CefBrowserImpl::UIT_CreateBrowser, newUrl));
|
||||
return true;
|
||||
}
|
||||
@ -361,7 +360,7 @@ CefRefPtr<CefBrowser> CefBrowser::CreateBrowserSync(CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefHandler> handler,
|
||||
const std::wstring& url)
|
||||
{
|
||||
if(!_Context.get() || !_Context->RunningOnUIThread())
|
||||
if(!_Context.get() || !CefThread::CurrentlyOn(CefThread::UI))
|
||||
return NULL;
|
||||
|
||||
std::wstring newUrl = url;
|
||||
|
@ -7,11 +7,11 @@
|
||||
#define _BROWSER_IMPL_H
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "context.h"
|
||||
|
||||
#include "webview_host.h"
|
||||
#include "browser_webview_delegate.h"
|
||||
#include "browser_navigation_controller.h"
|
||||
#include "cef_thread.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "printing/win_printing_context.h"
|
||||
#endif
|
||||
|
@ -3,7 +3,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#include "stream_impl.h"
|
||||
@ -111,7 +111,7 @@ CefWindowHandle CefBrowserImpl::GetWindowHandle()
|
||||
|
||||
std::wstring CefBrowserImpl::GetSource(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
if(!_Context->RunningOnUIThread())
|
||||
if(!CefThread::CurrentlyOn(CefThread::UI))
|
||||
{
|
||||
// We need to send the request to the UI thread and wait for the result
|
||||
|
||||
@ -125,7 +125,7 @@ std::wstring CefBrowserImpl::GetSource(CefRefPtr<CefFrame> frame)
|
||||
// Request the data from the UI thread
|
||||
frame->AddRef();
|
||||
stream->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_GetDocumentStringNotify, frame.get(), stream.get(),
|
||||
hEvent));
|
||||
|
||||
@ -150,7 +150,7 @@ std::wstring CefBrowserImpl::GetSource(CefRefPtr<CefFrame> frame)
|
||||
|
||||
std::wstring CefBrowserImpl::GetText(CefRefPtr<CefFrame> frame)
|
||||
{
|
||||
if(!_Context->RunningOnUIThread())
|
||||
if(!CefThread::CurrentlyOn(CefThread::UI))
|
||||
{
|
||||
// We need to send the request to the UI thread and wait for the result
|
||||
|
||||
@ -164,7 +164,7 @@ std::wstring CefBrowserImpl::GetText(CefRefPtr<CefFrame> frame)
|
||||
// Request the data from the UI thread
|
||||
frame->AddRef();
|
||||
stream->AddRef();
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_GetDocumentTextNotify, frame.get(), stream.get(),
|
||||
hEvent));
|
||||
|
||||
@ -187,7 +187,7 @@ std::wstring CefBrowserImpl::GetText(CefRefPtr<CefFrame> frame)
|
||||
|
||||
bool CefBrowserImpl::CanGoBack()
|
||||
{
|
||||
if(!_Context->RunningOnUIThread())
|
||||
if(!CefThread::CurrentlyOn(CefThread::UI))
|
||||
{
|
||||
// We need to send the request to the UI thread and wait for the result
|
||||
|
||||
@ -199,7 +199,7 @@ bool CefBrowserImpl::CanGoBack()
|
||||
bool retVal = true;
|
||||
|
||||
// Request the data from the UI thread
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_CanGoBackNotify, &retVal, hEvent));
|
||||
|
||||
// Wait for the UI thread callback to tell us that the data is available
|
||||
@ -217,7 +217,7 @@ bool CefBrowserImpl::CanGoBack()
|
||||
|
||||
bool CefBrowserImpl::CanGoForward()
|
||||
{
|
||||
if(!_Context->RunningOnUIThread())
|
||||
if(!CefThread::CurrentlyOn(CefThread::UI))
|
||||
{
|
||||
// We need to send the request to the UI thread and wait for the result
|
||||
|
||||
@ -229,7 +229,7 @@ bool CefBrowserImpl::CanGoForward()
|
||||
bool retVal = true;
|
||||
|
||||
// Request the data from the UI thread
|
||||
PostTask(FROM_HERE, NewRunnableMethod(this,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
|
||||
&CefBrowserImpl::UIT_CanGoForwardNotify, &retVal, hEvent));
|
||||
|
||||
// Wait for the UI thread callback to tell us that the data is available
|
||||
@ -254,7 +254,7 @@ void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url)
|
||||
window_info_.m_windowName, window_info_.m_dwStyle,
|
||||
window_info_.m_x, window_info_.m_y, window_info_.m_nWidth,
|
||||
window_info_.m_nHeight, window_info_.m_hWndParent, window_info_.m_hMenu,
|
||||
_Context->GetInstanceHandle(), NULL);
|
||||
::GetModuleHandle(NULL), NULL);
|
||||
DCHECK(window_info_.m_hWnd != NULL);
|
||||
|
||||
// Set window user data to this object for future reference from the window
|
||||
@ -269,7 +269,7 @@ void CefBrowserImpl::UIT_CreateBrowser(const std::wstring& url)
|
||||
// Create the webview host object
|
||||
webviewhost_.reset(
|
||||
WebViewHost::Create(window_info_.m_hWnd, delegate_.get(),
|
||||
*_Context->GetWebPreferences()));
|
||||
*_Context->web_preferences()));
|
||||
delegate_->RegisterDragDrop();
|
||||
|
||||
// Size the web view window to the browser window
|
||||
|
@ -73,6 +73,13 @@ BrowserRequestContext::~BrowserRequestContext() {
|
||||
delete static_cast<net::StaticCookiePolicy*>(cookie_policy_);
|
||||
}
|
||||
|
||||
void BrowserRequestContext::SetAcceptAllCookies(bool accept_all_cookies) {
|
||||
net::StaticCookiePolicy::Type policy_type = accept_all_cookies ?
|
||||
net::StaticCookiePolicy::ALLOW_ALL_COOKIES :
|
||||
net::StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES;
|
||||
static_cast<net::StaticCookiePolicy*>(cookie_policy())->set_type(policy_type);
|
||||
}
|
||||
|
||||
const std::string& BrowserRequestContext::GetUserAgent(
|
||||
const GURL& url) const {
|
||||
return webkit_glue::GetUserAgent(url);
|
||||
|
@ -16,6 +16,7 @@ class BrowserRequestContext : public URLRequestContext {
|
||||
public:
|
||||
// Use an in-memory cache
|
||||
BrowserRequestContext();
|
||||
~BrowserRequestContext();
|
||||
|
||||
// Use an on-disk cache at the specified location. Optionally, use the cache
|
||||
// in playback or record mode.
|
||||
@ -25,9 +26,9 @@ class BrowserRequestContext : public URLRequestContext {
|
||||
|
||||
virtual const std::string& GetUserAgent(const GURL& url) const;
|
||||
|
||||
private:
|
||||
~BrowserRequestContext();
|
||||
void SetAcceptAllCookies(bool accept_all_cookies);
|
||||
|
||||
private:
|
||||
void Init(const FilePath& cache_path, net::HttpCache::Mode cache_mode,
|
||||
bool no_proxy);
|
||||
};
|
||||
|
@ -36,6 +36,9 @@
|
||||
#include "browser_request_context.h"
|
||||
#include "browser_socket_stream_bridge.h"
|
||||
#include "browser_impl.h"
|
||||
#include "cef_context.h"
|
||||
#include "cef_process.h"
|
||||
#include "cef_process_io_thread.h"
|
||||
#include "request_impl.h"
|
||||
|
||||
#include "base/file_path.h"
|
||||
@ -73,80 +76,6 @@ using net::StaticCookiePolicy;
|
||||
|
||||
namespace {
|
||||
|
||||
struct BrowserRequestContextParams {
|
||||
BrowserRequestContextParams(
|
||||
const FilePath& in_cache_path,
|
||||
net::HttpCache::Mode in_cache_mode,
|
||||
bool in_no_proxy)
|
||||
: cache_path(in_cache_path),
|
||||
cache_mode(in_cache_mode),
|
||||
no_proxy(in_no_proxy),
|
||||
accept_all_cookies(false) {}
|
||||
|
||||
FilePath cache_path;
|
||||
net::HttpCache::Mode cache_mode;
|
||||
bool no_proxy;
|
||||
bool accept_all_cookies;
|
||||
};
|
||||
|
||||
BrowserRequestContextParams* g_request_context_params = NULL;
|
||||
URLRequestContext* g_request_context = NULL;
|
||||
base::Thread* g_cache_thread = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class IOThread : public base::Thread {
|
||||
public:
|
||||
IOThread() : base::Thread("IOThread") {
|
||||
}
|
||||
|
||||
~IOThread() {
|
||||
// We cannot rely on our base class to stop the thread since we want our
|
||||
// CleanUp function to run.
|
||||
Stop();
|
||||
}
|
||||
|
||||
virtual void Init() {
|
||||
if (g_request_context_params) {
|
||||
g_request_context = new BrowserRequestContext(
|
||||
g_request_context_params->cache_path,
|
||||
g_request_context_params->cache_mode,
|
||||
g_request_context_params->no_proxy);
|
||||
SetAcceptAllCookies(g_request_context_params->accept_all_cookies);
|
||||
delete g_request_context_params;
|
||||
g_request_context_params = NULL;
|
||||
} else {
|
||||
g_request_context = new BrowserRequestContext();
|
||||
SetAcceptAllCookies(false);
|
||||
}
|
||||
|
||||
g_request_context->AddRef();
|
||||
|
||||
BrowserAppCacheSystem::InitializeOnIOThread(g_request_context);
|
||||
BrowserSocketStreamBridge::InitializeOnIOThread(g_request_context);
|
||||
}
|
||||
|
||||
virtual void CleanUp() {
|
||||
BrowserSocketStreamBridge::Cleanup();
|
||||
if (g_request_context) {
|
||||
g_request_context->Release();
|
||||
g_request_context = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void SetAcceptAllCookies(bool accept_all_cookies) {
|
||||
StaticCookiePolicy::Type policy_type = accept_all_cookies ?
|
||||
StaticCookiePolicy::ALLOW_ALL_COOKIES :
|
||||
StaticCookiePolicy::BLOCK_THIRD_PARTY_COOKIES;
|
||||
static_cast<StaticCookiePolicy*>(g_request_context->cookie_policy())->
|
||||
set_type(policy_type);
|
||||
}
|
||||
};
|
||||
|
||||
IOThread* g_io_thread = NULL;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct RequestParams {
|
||||
std::string method;
|
||||
GURL url;
|
||||
@ -185,13 +114,13 @@ class RequestProxy : public URLRequest::Delegate,
|
||||
owner_loop_ = MessageLoop::current();
|
||||
|
||||
// proxy over to the io thread
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
this, &RequestProxy::AsyncStart, params));
|
||||
}
|
||||
|
||||
void Cancel() {
|
||||
// proxy over to the io thread
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
this, &RequestProxy::AsyncCancel));
|
||||
}
|
||||
|
||||
@ -200,8 +129,7 @@ class RequestProxy : public URLRequest::Delegate,
|
||||
|
||||
virtual ~RequestProxy() {
|
||||
// If we have a request, then we'd better be on the io thread!
|
||||
DCHECK(!request_.get() ||
|
||||
MessageLoop::current() == g_io_thread->message_loop());
|
||||
DCHECK(!request_.get() || CefThread::CurrentlyOn(CefThread::IO));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@ -216,7 +144,7 @@ class RequestProxy : public URLRequest::Delegate,
|
||||
if (peer_ && peer_->OnReceivedRedirect(new_url, info,
|
||||
&has_new_first_party_for_cookies,
|
||||
&new_first_party_for_cookies)) {
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
this, &RequestProxy::AsyncFollowDeferredRedirect,
|
||||
has_new_first_party_for_cookies, new_first_party_for_cookies));
|
||||
} else {
|
||||
@ -245,7 +173,7 @@ class RequestProxy : public URLRequest::Delegate,
|
||||
// peer could generate new requests in reponse to the received data, which
|
||||
// when run on the io thread, could race against this function in doing
|
||||
// another InvokeLater. See bug 769249.
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
this, &RequestProxy::AsyncReadData));
|
||||
|
||||
peer_->OnReceivedData(buf_copy.get(), bytes_read);
|
||||
@ -349,7 +277,7 @@ class RequestProxy : public URLRequest::Delegate,
|
||||
request_->SetExtraRequestHeaders(headers);
|
||||
request_->set_load_flags(params->load_flags);
|
||||
request_->set_upload(params->upload.get());
|
||||
request_->set_context(g_request_context);
|
||||
request_->set_context(_Context->request_context());
|
||||
BrowserAppCacheSystem::SetExtraRequestInfo(
|
||||
request_.get(), params->appcache_host_id, params->request_type);
|
||||
|
||||
@ -657,7 +585,7 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
|
||||
if (proxy_) {
|
||||
proxy_->DropPeer();
|
||||
// Let the proxy die on the IO thread
|
||||
g_io_thread->message_loop()->ReleaseSoon(FROM_HERE, proxy_);
|
||||
CefThread::ReleaseSoon(CefThread::IO, FROM_HERE, proxy_);
|
||||
}
|
||||
}
|
||||
|
||||
@ -693,9 +621,6 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
|
||||
virtual bool Start(Peer* peer) {
|
||||
DCHECK(!proxy_);
|
||||
|
||||
if (!BrowserResourceLoaderBridge::EnsureIOThread())
|
||||
return false;
|
||||
|
||||
proxy_ = new RequestProxy(browser_);
|
||||
proxy_->AddRef();
|
||||
|
||||
@ -716,9 +641,6 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
|
||||
virtual void SyncLoad(SyncLoadResponse* response) {
|
||||
DCHECK(!proxy_);
|
||||
|
||||
if (!BrowserResourceLoaderBridge::EnsureIOThread())
|
||||
return;
|
||||
|
||||
// this may change as the result of a redirect
|
||||
response->url = params_->url;
|
||||
|
||||
@ -746,8 +668,8 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge {
|
||||
class CookieSetter : public base::RefCountedThreadSafe<CookieSetter> {
|
||||
public:
|
||||
void Set(const GURL& url, const std::string& cookie) {
|
||||
DCHECK(MessageLoop::current() == g_io_thread->message_loop());
|
||||
g_request_context->cookie_store()->SetCookie(url, cookie);
|
||||
REQUIRE_IOT();
|
||||
_Context->request_context()->cookie_store()->SetCookie(url, cookie);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -762,7 +684,7 @@ class CookieGetter : public base::RefCountedThreadSafe<CookieGetter> {
|
||||
}
|
||||
|
||||
void Get(const GURL& url) {
|
||||
result_ = g_request_context->cookie_store()->GetCookies(url);
|
||||
result_ = _Context->request_context()->cookie_store()->GetCookies(url);
|
||||
event_.Signal();
|
||||
}
|
||||
|
||||
@ -798,11 +720,12 @@ ResourceLoaderBridge* ResourceLoaderBridge::Create(
|
||||
// Issue the proxy resolve request on the io thread, and wait
|
||||
// for the result.
|
||||
bool FindProxyForUrl(const GURL& url, std::string* proxy_list) {
|
||||
DCHECK(g_request_context);
|
||||
DCHECK(_Context->request_context());
|
||||
|
||||
scoped_refptr<net::SyncProxyServiceHelper> sync_proxy_service(
|
||||
new net::SyncProxyServiceHelper(g_io_thread->message_loop(),
|
||||
g_request_context->proxy_service()));
|
||||
new net::SyncProxyServiceHelper(
|
||||
_Context->process()->io_thread()->message_loop(),
|
||||
_Context->request_context()->proxy_service()));
|
||||
|
||||
net::ProxyInfo proxy_info;
|
||||
int rv = sync_proxy_service->ResolveProxy(url, &proxy_info,
|
||||
@ -818,53 +741,14 @@ bool FindProxyForUrl(const GURL& url, std::string* proxy_list) {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// static
|
||||
void BrowserResourceLoaderBridge::Init(
|
||||
const FilePath& cache_path,
|
||||
net::HttpCache::Mode cache_mode,
|
||||
bool no_proxy) {
|
||||
// Make sure to stop any existing IO thread since it may be using the
|
||||
// current request context.
|
||||
Shutdown();
|
||||
|
||||
DCHECK(!g_request_context_params);
|
||||
DCHECK(!g_request_context);
|
||||
DCHECK(!g_io_thread);
|
||||
|
||||
g_request_context_params = new BrowserRequestContextParams(
|
||||
cache_path, cache_mode, no_proxy);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserResourceLoaderBridge::Shutdown() {
|
||||
if (g_io_thread) {
|
||||
delete g_io_thread;
|
||||
g_io_thread = NULL;
|
||||
|
||||
DCHECK(g_cache_thread);
|
||||
delete g_cache_thread;
|
||||
g_cache_thread = NULL;
|
||||
|
||||
DCHECK(!g_request_context) << "should have been nulled by thread dtor";
|
||||
} else {
|
||||
delete g_request_context_params;
|
||||
g_request_context_params = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserResourceLoaderBridge::SetCookie(const GURL& url,
|
||||
const GURL& first_party_for_cookies,
|
||||
const std::string& cookie) {
|
||||
// Proxy to IO thread to synchronize w/ network loading.
|
||||
|
||||
if (!EnsureIOThread()) {
|
||||
NOTREACHED();
|
||||
return;
|
||||
}
|
||||
|
||||
scoped_refptr<CookieSetter> cookie_setter = new CookieSetter();
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
cookie_setter.get(), &CookieSetter::Set, url, cookie));
|
||||
}
|
||||
|
||||
@ -873,61 +757,24 @@ std::string BrowserResourceLoaderBridge::GetCookies(
|
||||
const GURL& url, const GURL& first_party_for_cookies) {
|
||||
// Proxy to IO thread to synchronize w/ network loading
|
||||
|
||||
if (!EnsureIOThread()) {
|
||||
NOTREACHED();
|
||||
return std::string();
|
||||
}
|
||||
|
||||
scoped_refptr<CookieGetter> getter = new CookieGetter();
|
||||
|
||||
g_io_thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
getter.get(), &CookieGetter::Get, url));
|
||||
|
||||
return getter->GetResult();
|
||||
}
|
||||
|
||||
// static
|
||||
bool BrowserResourceLoaderBridge::EnsureIOThread() {
|
||||
if (g_io_thread)
|
||||
return true;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Use NSS for SSL on Windows. TODO(wtc): this should eventually be hidden
|
||||
// inside DefaultClientSocketFactory::CreateSSLClientSocket.
|
||||
net::ClientSocketFactory::SetSSLClientSocketFactory(
|
||||
net::SSLClientSocketNSSFactory);
|
||||
#endif
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
// We want to be sure to init NSPR on the main thread.
|
||||
base::EnsureNSPRInit();
|
||||
#endif
|
||||
|
||||
// Create the cache thread. We want the cache thread to outlive the IO thread,
|
||||
// so its lifetime is bonded to the IO thread lifetime.
|
||||
DCHECK(!g_cache_thread);
|
||||
g_cache_thread = new base::Thread("cache");
|
||||
CHECK(g_cache_thread->StartWithOptions(
|
||||
base::Thread::Options(MessageLoop::TYPE_IO, 0)));
|
||||
|
||||
g_io_thread = new IOThread();
|
||||
base::Thread::Options options;
|
||||
options.message_loop_type = MessageLoop::TYPE_IO;
|
||||
return g_io_thread->StartWithOptions(options);
|
||||
}
|
||||
|
||||
// static
|
||||
void BrowserResourceLoaderBridge::SetAcceptAllCookies(bool accept_all_cookies) {
|
||||
if (g_request_context_params) {
|
||||
g_request_context_params->accept_all_cookies = accept_all_cookies;
|
||||
DCHECK(!g_request_context);
|
||||
DCHECK(!g_io_thread);
|
||||
} else {
|
||||
g_io_thread->SetAcceptAllCookies(accept_all_cookies);
|
||||
}
|
||||
// Proxy to IO thread to synchronize w/ network loading
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
_Context->request_context().get(),
|
||||
&BrowserRequestContext::SetAcceptAllCookies, accept_all_cookies));
|
||||
}
|
||||
|
||||
// static
|
||||
//static
|
||||
scoped_refptr<base::MessageLoopProxy>
|
||||
BrowserResourceLoaderBridge::GetCacheThread() {
|
||||
return g_cache_thread->message_loop_proxy();
|
||||
return CefThread::GetMessageLoopProxyForThread(CefThread::FILE);
|
||||
}
|
||||
|
@ -15,29 +15,14 @@ class GURL;
|
||||
|
||||
class BrowserResourceLoaderBridge {
|
||||
public:
|
||||
// Call this function to initialize the simple resource loader bridge.
|
||||
// It is safe to call this function multiple times.
|
||||
//
|
||||
// NOTE: If this function is not called, then a default request context will
|
||||
// be initialized lazily.
|
||||
//
|
||||
static void Init(const FilePath& cache_path,
|
||||
net::HttpCache::Mode cache_mode,
|
||||
bool no_proxy);
|
||||
|
||||
// Call this function to shutdown the simple resource loader bridge.
|
||||
static void Shutdown();
|
||||
|
||||
// May only be called after Init.
|
||||
static void SetCookie(const GURL& url,
|
||||
const GURL& first_party_for_cookies,
|
||||
const std::string& cookie);
|
||||
static std::string GetCookies(const GURL& url,
|
||||
const GURL& first_party_for_cookies);
|
||||
static bool EnsureIOThread();
|
||||
static void SetAcceptAllCookies(bool accept_all_cookies);
|
||||
|
||||
// This method should only be called after Init(), and before Shutdown().
|
||||
static scoped_refptr<base::MessageLoopProxy> GetCacheThread();
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "browser_appcache_system.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_navigation_controller.h"
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
#include "request_impl.h"
|
||||
#include "v8_impl.h"
|
||||
|
||||
@ -126,13 +126,13 @@ int next_page_id_ = 1;
|
||||
// WebViewDelegate -----------------------------------------------------------
|
||||
|
||||
void BrowserWebViewDelegate::SetUserStyleSheetEnabled(bool is_enabled) {
|
||||
WebPreferences* prefs = _Context->GetWebPreferences();
|
||||
WebPreferences* prefs = _Context->web_preferences();
|
||||
prefs->user_style_sheet_enabled = is_enabled;
|
||||
prefs->Apply(browser_->GetWebView());
|
||||
}
|
||||
|
||||
void BrowserWebViewDelegate::SetUserStyleSheetLocation(const GURL& location) {
|
||||
WebPreferences* prefs = _Context->GetWebPreferences();
|
||||
WebPreferences* prefs = _Context->web_preferences();
|
||||
prefs->user_style_sheet_enabled = true;
|
||||
prefs->user_style_sheet_location = location;
|
||||
prefs->Apply(browser_->GetWebView());
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "browser_drop_delegate.h"
|
||||
#include "browser_navigation_controller.h"
|
||||
#include "browser_impl.h"
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
|
||||
#include <objidl.h>
|
||||
#include <shlobj.h>
|
||||
|
322
libcef/cef_context.cc
Normal file
322
libcef/cef_context.cc
Normal file
@ -0,0 +1,322 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that can
|
||||
// be found in the LICENSE file.
|
||||
|
||||
#include "cef_context.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#include "cef_thread.h"
|
||||
#include "cef_process.h"
|
||||
#include "../include/cef_nplugin.h"
|
||||
|
||||
#include "base/file_util.h"
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
#include "base/nss_util.h"
|
||||
#endif
|
||||
#include "webkit/glue/plugins/plugin_list.h"
|
||||
#include "webkit/glue/webpreferences.h"
|
||||
|
||||
// Global CefContext pointer
|
||||
CefRefPtr<CefContext> _Context;
|
||||
|
||||
bool CefInitialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path)
|
||||
{
|
||||
// Return true if the context is already initialized
|
||||
if(_Context.get())
|
||||
return true;
|
||||
|
||||
// Create the new global context object
|
||||
_Context = new CefContext();
|
||||
// Initialize the global context
|
||||
return _Context->Initialize(multi_threaded_message_loop, cache_path);
|
||||
}
|
||||
|
||||
void CefShutdown()
|
||||
{
|
||||
// Verify that the context is already initialized
|
||||
if(!_Context.get())
|
||||
return;
|
||||
|
||||
// Shut down the global context
|
||||
_Context->Shutdown();
|
||||
// Delete the global context object
|
||||
_Context = NULL;
|
||||
}
|
||||
|
||||
void CefDoMessageLoopWork()
|
||||
{
|
||||
// Verify that the context is already initialized.
|
||||
if(!_Context.get() || !_Context->process())
|
||||
return;
|
||||
|
||||
if(!_Context->process()->CalledOnValidThread())
|
||||
return;
|
||||
_Context->process()->DoMessageLoopIteration();
|
||||
}
|
||||
|
||||
static void UIT_RegisterPlugin(struct CefPluginInfo* plugin_info)
|
||||
{
|
||||
REQUIRE_UIT();
|
||||
|
||||
NPAPI::PluginVersionInfo info;
|
||||
|
||||
info.path = FilePath(plugin_info->unique_name);
|
||||
info.product_name = plugin_info->display_name;
|
||||
info.file_description = plugin_info->description;
|
||||
info.file_version =plugin_info->version;
|
||||
|
||||
for(size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
|
||||
if(i > 0) {
|
||||
info.mime_types += L"|";
|
||||
info.file_extensions += L"|";
|
||||
info.type_descriptions += L"|";
|
||||
}
|
||||
|
||||
info.mime_types += plugin_info->mime_types[i].mime_type;
|
||||
info.type_descriptions += plugin_info->mime_types[i].description;
|
||||
|
||||
for(size_t j = 0;
|
||||
j < plugin_info->mime_types[i].file_extensions.size(); ++j) {
|
||||
if(j > 0) {
|
||||
info.file_extensions += L",";
|
||||
}
|
||||
info.file_extensions += plugin_info->mime_types[i].file_extensions[j];
|
||||
}
|
||||
}
|
||||
|
||||
info.entry_points.np_getentrypoints = plugin_info->np_getentrypoints;
|
||||
info.entry_points.np_initialize = plugin_info->np_initialize;
|
||||
info.entry_points.np_shutdown = plugin_info->np_shutdown;
|
||||
|
||||
NPAPI::PluginList::Singleton()->RegisterInternalPlugin(info);
|
||||
|
||||
delete plugin_info;
|
||||
}
|
||||
|
||||
bool CefRegisterPlugin(const struct CefPluginInfo& plugin_info)
|
||||
{
|
||||
if(!_Context.get())
|
||||
return false;
|
||||
|
||||
CefPluginInfo* pPluginInfo = new CefPluginInfo;
|
||||
*pPluginInfo = plugin_info;
|
||||
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
NewRunnableFunction(UIT_RegisterPlugin, pPluginInfo));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int GetThreadId(CefThreadId threadId)
|
||||
{
|
||||
switch(threadId) {
|
||||
case TID_UI: return CefThread::UI;
|
||||
case TID_IO: return CefThread::IO;
|
||||
case TID_FILE: return CefThread::FILE;
|
||||
};
|
||||
NOTREACHED();
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool CefCurrentlyOn(CefThreadId threadId)
|
||||
{
|
||||
int id = GetThreadId(threadId);
|
||||
if(id < 0)
|
||||
return false;
|
||||
|
||||
return CefThread::CurrentlyOn(static_cast<CefThread::ID>(id));
|
||||
}
|
||||
|
||||
class CefTaskHelper : public base::RefCountedThreadSafe<CefTaskHelper>
|
||||
{
|
||||
public:
|
||||
CefTaskHelper(CefRefPtr<CefTask> task) : task_(task) {}
|
||||
void Execute(CefThreadId threadId) { task_->Execute(threadId); }
|
||||
private:
|
||||
CefRefPtr<CefTask> task_;
|
||||
DISALLOW_COPY_AND_ASSIGN(CefTaskHelper);
|
||||
};
|
||||
|
||||
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task)
|
||||
{
|
||||
int id = GetThreadId(threadId);
|
||||
if(id < 0)
|
||||
return false;
|
||||
|
||||
scoped_refptr<CefTaskHelper> helper(new CefTaskHelper(task));
|
||||
return CefThread::PostTask(static_cast<CefThread::ID>(id), FROM_HERE,
|
||||
NewRunnableMethod(helper.get(), &CefTaskHelper::Execute, threadId));
|
||||
}
|
||||
|
||||
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
||||
long delay_ms)
|
||||
{
|
||||
int id = GetThreadId(threadId);
|
||||
if(id < 0)
|
||||
return false;
|
||||
|
||||
scoped_refptr<CefTaskHelper> helper(new CefTaskHelper(task));
|
||||
return CefThread::PostDelayedTask(static_cast<CefThread::ID>(id), FROM_HERE,
|
||||
NewRunnableMethod(helper.get(), &CefTaskHelper::Execute, threadId),
|
||||
delay_ms);
|
||||
}
|
||||
|
||||
|
||||
// CefContext
|
||||
|
||||
CefContext::CefContext() : process_(NULL), webprefs_(NULL)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CefContext::~CefContext()
|
||||
{
|
||||
// Just in case CefShutdown() isn't called
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
bool CefContext::Initialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path)
|
||||
{
|
||||
cache_path_ = cache_path;
|
||||
|
||||
// Initialize web preferences
|
||||
webprefs_ = new WebPreferences;
|
||||
*webprefs_ = WebPreferences();
|
||||
webprefs_->standard_font_family = L"Times";
|
||||
webprefs_->fixed_font_family = L"Courier";
|
||||
webprefs_->serif_font_family = L"Times";
|
||||
webprefs_->sans_serif_font_family = L"Helvetica";
|
||||
// These two fonts are picked from the intersection of
|
||||
// Win XP font list and Vista font list :
|
||||
// http://www.microsoft.com/typography/fonts/winxp.htm
|
||||
// http://blogs.msdn.com/michkap/archive/2006/04/04/567881.aspx
|
||||
// Some of them are installed only with CJK and complex script
|
||||
// support enabled on Windows XP and are out of consideration here.
|
||||
// (although we enabled both on our buildbots.)
|
||||
// They (especially Impact for fantasy) are not typical cursive
|
||||
// and fantasy fonts, but it should not matter for layout tests
|
||||
// as long as they're available.
|
||||
#if defined(OS_MACOSX)
|
||||
webprefs_->cursive_font_family = L"Apple Chancery";
|
||||
webprefs_->fantasy_font_family = L"Papyrus";
|
||||
#else
|
||||
webprefs_->cursive_font_family = L"Comic Sans MS";
|
||||
webprefs_->fantasy_font_family = L"Impact";
|
||||
#endif
|
||||
webprefs_->default_encoding = "ISO-8859-1";
|
||||
webprefs_->default_font_size = 16;
|
||||
webprefs_->default_fixed_font_size = 13;
|
||||
webprefs_->minimum_font_size = 1;
|
||||
webprefs_->minimum_logical_font_size = 9;
|
||||
webprefs_->javascript_can_open_windows_automatically = true;
|
||||
webprefs_->dom_paste_enabled = true;
|
||||
webprefs_->developer_extras_enabled = true;
|
||||
webprefs_->site_specific_quirks_enabled = true;
|
||||
webprefs_->shrinks_standalone_images_to_fit = false;
|
||||
webprefs_->uses_universal_detector = false;
|
||||
webprefs_->text_areas_are_resizable = true;
|
||||
webprefs_->java_enabled = true;
|
||||
webprefs_->allow_scripts_to_close_windows = false;
|
||||
webprefs_->xss_auditor_enabled = false;
|
||||
webprefs_->remote_fonts_enabled = true;
|
||||
webprefs_->local_storage_enabled = true;
|
||||
webprefs_->application_cache_enabled = true;
|
||||
webprefs_->databases_enabled = true;
|
||||
webprefs_->allow_file_access_from_file_urls = true;
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN)
|
||||
// We want to be sure to init NSPR on the main thread.
|
||||
base::EnsureNSPRInit();
|
||||
#endif
|
||||
|
||||
process_ = new CefProcess(multi_threaded_message_loop);
|
||||
process_->CreateChildThreads();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefContext::Shutdown()
|
||||
{
|
||||
// Remove all existing browsers.
|
||||
//RemoveAllBrowsers();
|
||||
|
||||
// Deleting the process will destroy the child threads.
|
||||
process_ = NULL;
|
||||
}
|
||||
|
||||
|
||||
bool CefContext::AddBrowser(CefRefPtr<CefBrowserImpl> browser)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
Lock();
|
||||
|
||||
// check that the browser isn't already in the list before adding
|
||||
BrowserList::const_iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get() == browser.get()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
browser->UIT_SetUniqueID(next_browser_id_++);
|
||||
browserlist_.push_back(browser);
|
||||
}
|
||||
|
||||
Unlock();
|
||||
return !found;
|
||||
}
|
||||
|
||||
bool CefContext::RemoveBrowser(CefRefPtr<CefBrowserImpl> browser)
|
||||
{
|
||||
bool deleted = false;
|
||||
bool empty = false;
|
||||
|
||||
Lock();
|
||||
|
||||
BrowserList::iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get() == browser.get()) {
|
||||
browserlist_.erase(it);
|
||||
deleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (browserlist_.empty()) {
|
||||
next_browser_id_ = 1;
|
||||
empty = true;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (empty) {
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE,
|
||||
NewRunnableFunction(webkit_glue::ClearCache));
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserImpl> CefContext::GetBrowserByID(int id)
|
||||
{
|
||||
CefRefPtr<CefBrowserImpl> browser;
|
||||
Lock();
|
||||
|
||||
BrowserList::const_iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get()->UIT_GetUniqueID() == id) {
|
||||
browser = it->get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return browser;
|
||||
}
|
81
libcef/cef_context.h
Normal file
81
libcef/cef_context.h
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that can
|
||||
// be found in the LICENSE file.
|
||||
|
||||
#ifndef _CEF_CONTEXT_H
|
||||
#define _CEF_CONTEXT_H
|
||||
|
||||
#include "../include/cef.h"
|
||||
#include "browser_request_context.h"
|
||||
#include "cef_process.h"
|
||||
#include "cef_thread.h"
|
||||
|
||||
#include "base/at_exit.h"
|
||||
#include "base/file_path.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/ref_counted.h"
|
||||
#include <map>
|
||||
|
||||
class BrowserRequestContext;
|
||||
class CefBrowserImpl;
|
||||
struct WebPreferences;
|
||||
|
||||
class CefContext : public CefThreadSafeBase<CefBase>
|
||||
{
|
||||
public:
|
||||
typedef std::list<CefRefPtr<CefBrowserImpl> > BrowserList;
|
||||
|
||||
CefContext();
|
||||
~CefContext();
|
||||
|
||||
// These methods will be called on the main application thread.
|
||||
bool Initialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path);
|
||||
void Shutdown();
|
||||
|
||||
scoped_refptr<CefProcess> process() { return process_; }
|
||||
|
||||
bool AddBrowser(CefRefPtr<CefBrowserImpl> browser);
|
||||
bool RemoveBrowser(CefRefPtr<CefBrowserImpl> browser);
|
||||
CefRefPtr<CefBrowserImpl> GetBrowserByID(int id);
|
||||
BrowserList* GetBrowserList() { return &browserlist_; }
|
||||
|
||||
// Retrieve the path at which cache data will be stored on disk. If empty,
|
||||
// cache data will be stored in-memory.
|
||||
const std::wstring& cache_path() { return cache_path_; }
|
||||
|
||||
WebPreferences* web_preferences()
|
||||
{
|
||||
REQUIRE_UIT();
|
||||
return webprefs_;
|
||||
}
|
||||
|
||||
// The BrowserRequestContext object is managed by CefProcessIOThread.
|
||||
void set_request_context(BrowserRequestContext* request_context)
|
||||
{ request_context_ = request_context; }
|
||||
scoped_refptr<BrowserRequestContext> request_context()
|
||||
{ return request_context_; }
|
||||
|
||||
private:
|
||||
// Manages the various process threads.
|
||||
scoped_refptr<CefProcess> process_;
|
||||
|
||||
// Initialize the AtExitManager on the main application thread to avoid
|
||||
// asserts and possible memory leaks.
|
||||
base::AtExitManager at_exit_manager_;
|
||||
|
||||
std::wstring cache_path_;
|
||||
WebPreferences* webprefs_;
|
||||
scoped_refptr<BrowserRequestContext> request_context_;
|
||||
|
||||
// Map of browsers that currently exist.
|
||||
BrowserList browserlist_;
|
||||
|
||||
// Used for assigning unique IDs to browser instances.
|
||||
int next_browser_id_;
|
||||
};
|
||||
|
||||
// Global context object pointer
|
||||
extern CefRefPtr<CefContext> _Context;
|
||||
|
||||
#endif // _CONTEXT_H
|
134
libcef/cef_process.cc
Normal file
134
libcef/cef_process.cc
Normal file
@ -0,0 +1,134 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "cef_process.h"
|
||||
#include "cef_process_io_thread.h"
|
||||
#include "cef_process_sub_thread.h"
|
||||
#include "cef_process_ui_thread.h"
|
||||
|
||||
#include "base/thread.h"
|
||||
#include "base/waitable_event.h"
|
||||
|
||||
CefProcess* g_cef_process = NULL;
|
||||
|
||||
// Class used to process events on the current message loop.
|
||||
class CefMessageLoopForUI : public MessageLoopForUI
|
||||
{
|
||||
typedef MessageLoopForUI inherited;
|
||||
|
||||
public:
|
||||
CefMessageLoopForUI()
|
||||
{
|
||||
}
|
||||
|
||||
// Returns the MessageLoopForUI of the current thread.
|
||||
static CefMessageLoopForUI* current() {
|
||||
MessageLoop* loop = MessageLoop::current();
|
||||
DCHECK_EQ(MessageLoop::TYPE_UI, loop->type());
|
||||
return static_cast<CefMessageLoopForUI*>(loop);
|
||||
}
|
||||
|
||||
virtual bool DoIdleWork() {
|
||||
bool valueToRet = inherited::DoIdleWork();
|
||||
pump_->Quit();
|
||||
return valueToRet;
|
||||
}
|
||||
|
||||
void DoMessageLoopIteration() {
|
||||
Run(NULL);
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CefMessageLoopForUI);
|
||||
};
|
||||
|
||||
CefProcess::CefProcess(bool multi_threaded_message_loop)
|
||||
: multi_threaded_message_loop_(multi_threaded_message_loop),
|
||||
created_ui_thread_(false),
|
||||
created_io_thread_(false),
|
||||
created_file_thread_(false) {
|
||||
g_cef_process = this;
|
||||
}
|
||||
|
||||
CefProcess::~CefProcess() {
|
||||
// Terminate the IO thread.
|
||||
io_thread_.reset();
|
||||
|
||||
// Terminate the FILE thread.
|
||||
file_thread_.reset();
|
||||
|
||||
if(!multi_threaded_message_loop_) {
|
||||
// Must explicitly clean up the UI thread.
|
||||
ui_thread_->CleanUp();
|
||||
|
||||
// Terminate the UI thread.
|
||||
ui_thread_.reset();
|
||||
|
||||
// Terminate the message loop.
|
||||
ui_message_loop_.reset();
|
||||
}
|
||||
|
||||
g_cef_process = NULL;
|
||||
}
|
||||
|
||||
void CefProcess::DoMessageLoopIteration() {
|
||||
DCHECK(CalledOnValidThread() && ui_message_loop_.get() != NULL);
|
||||
ui_message_loop_->DoMessageLoopIteration();
|
||||
}
|
||||
|
||||
void CefProcess::CreateUIThread() {
|
||||
DCHECK(!created_ui_thread_ && ui_thread_.get() == NULL);
|
||||
created_ui_thread_ = true;
|
||||
|
||||
scoped_ptr<CefProcessUIThread> thread;
|
||||
if(multi_threaded_message_loop_) {
|
||||
// Create the message loop on a new thread.
|
||||
thread.reset(new CefProcessUIThread());
|
||||
base::Thread::Options options;
|
||||
options.message_loop_type = MessageLoop::TYPE_UI;
|
||||
if (!thread->StartWithOptions(options))
|
||||
return;
|
||||
} else {
|
||||
// Create the message loop on the current (main application) thread.
|
||||
ui_message_loop_.reset(new CefMessageLoopForUI());
|
||||
thread.reset(
|
||||
new CefProcessUIThread(ui_message_loop_.get()));
|
||||
|
||||
// Must explicitly initialize the UI thread.
|
||||
thread->Init();
|
||||
}
|
||||
|
||||
ui_thread_.swap(thread);
|
||||
}
|
||||
|
||||
void CefProcess::CreateIOThread() {
|
||||
DCHECK(!created_io_thread_ && io_thread_.get() == NULL);
|
||||
created_io_thread_ = true;
|
||||
|
||||
scoped_ptr<CefProcessIOThread> thread(new CefProcessIOThread());
|
||||
base::Thread::Options options;
|
||||
options.message_loop_type = MessageLoop::TYPE_IO;
|
||||
if (!thread->StartWithOptions(options))
|
||||
return;
|
||||
io_thread_.swap(thread);
|
||||
}
|
||||
|
||||
void CefProcess::CreateFileThread() {
|
||||
DCHECK(!created_file_thread_ && file_thread_.get() == NULL);
|
||||
created_file_thread_ = true;
|
||||
|
||||
scoped_ptr<base::Thread> thread(new CefProcessSubThread(CefThread::FILE));
|
||||
base::Thread::Options options;
|
||||
#if defined(OS_WIN)
|
||||
// On Windows, the FILE thread needs to be have a UI message loop which pumps
|
||||
// messages in such a way that Google Update can communicate back to us.
|
||||
options.message_loop_type = MessageLoop::TYPE_UI;
|
||||
#else
|
||||
options.message_loop_type = MessageLoop::TYPE_IO;
|
||||
#endif
|
||||
if (!thread->StartWithOptions(options))
|
||||
return;
|
||||
file_thread_.swap(thread);
|
||||
}
|
117
libcef/cef_process.h
Normal file
117
libcef/cef_process.h
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This interface is for managing the global services of the application. Each
|
||||
// service is lazily created when requested the first time. The service getters
|
||||
// will return NULL if the service is not available, so callers must check for
|
||||
// this condition.
|
||||
|
||||
#ifndef _CEF_PROCESS_H
|
||||
#define _CEF_PROCESS_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/non_thread_safe.h"
|
||||
#include "base/ref_counted.h"
|
||||
#include "base/scoped_ptr.h"
|
||||
#include "ipc/ipc_message.h"
|
||||
|
||||
namespace base {
|
||||
class Thread;
|
||||
class WaitableEvent;
|
||||
}
|
||||
|
||||
class CefProcessIOThread;
|
||||
class CefProcessUIThread;
|
||||
class CefMessageLoopForUI;
|
||||
|
||||
// NOT THREAD SAFE, call only from the main thread.
|
||||
// These functions shouldn't return NULL unless otherwise noted.
|
||||
class CefProcess : public base::RefCounted<CefProcess>, public NonThreadSafe {
|
||||
public:
|
||||
CefProcess(bool multi_threaded_message_loop);
|
||||
virtual ~CefProcess();
|
||||
|
||||
// Creates key child threads. We need to do this explicitly since
|
||||
// CefThread::PostTask silently deletes a posted task if the target message
|
||||
// loop isn't created.
|
||||
void CreateChildThreads() {
|
||||
ui_thread();
|
||||
// Create the FILE thread before the IO thread because IO thread
|
||||
// initialization depends on existance of the FILE thread (for cache
|
||||
// support, etc).
|
||||
file_thread();
|
||||
io_thread();
|
||||
}
|
||||
|
||||
CefProcessUIThread* ui_thread() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
if (!created_ui_thread_)
|
||||
CreateUIThread();
|
||||
return ui_thread_.get();
|
||||
}
|
||||
|
||||
// Necessary to perform work on the UI thread if started without a multi
|
||||
// threaded message loop.
|
||||
void DoMessageLoopIteration();
|
||||
|
||||
// Returns the thread that we perform I/O coordination on (network requests,
|
||||
// communication with renderers, etc.
|
||||
// NOTE: You should ONLY use this to pass to IPC or other objects which must
|
||||
// need a MessageLoop*. If you just want to post a task, use
|
||||
// CefThread::PostTask (or other variants) as they take care of checking
|
||||
// that a thread is still alive, race conditions, lifetime differences etc.
|
||||
// If you still must use this, need to check the return value for NULL.
|
||||
CefProcessIOThread* io_thread() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
if (!created_io_thread_)
|
||||
CreateIOThread();
|
||||
return io_thread_.get();
|
||||
}
|
||||
|
||||
// Returns the thread that we perform random file operations on. For code
|
||||
// that wants to do I/O operations (not network requests or even file: URL
|
||||
// requests), this is the thread to use to avoid blocking the UI thread.
|
||||
// It might be nicer to have a thread pool for this kind of thing.
|
||||
base::Thread* file_thread() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
if (!created_file_thread_)
|
||||
CreateFileThread();
|
||||
return file_thread_.get();
|
||||
}
|
||||
|
||||
#if defined(IPC_MESSAGE_LOG_ENABLED)
|
||||
// Enable or disable IPC logging for the browser, all processes
|
||||
// derived from ChildProcess (plugin etc), and all
|
||||
// renderers.
|
||||
void SetIPCLoggingEnabled(bool enable);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void CreateUIThread();
|
||||
void CreateIOThread();
|
||||
void CreateFileThread();
|
||||
|
||||
bool multi_threaded_message_loop_;
|
||||
|
||||
bool created_ui_thread_;
|
||||
scoped_ptr<CefProcessUIThread> ui_thread_;
|
||||
scoped_ptr<CefMessageLoopForUI> ui_message_loop_;
|
||||
|
||||
bool created_io_thread_;
|
||||
scoped_ptr<CefProcessIOThread> io_thread_;
|
||||
|
||||
bool created_file_thread_;
|
||||
scoped_ptr<base::Thread> file_thread_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefProcess);
|
||||
};
|
||||
|
||||
extern CefProcess* g_cef_process;
|
||||
|
||||
#endif // _CEF_PROCESS_H
|
60
libcef/cef_process_io_thread.cc
Normal file
60
libcef/cef_process_io_thread.cc
Normal file
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "cef_process_io_thread.h"
|
||||
#include "cef_context.h"
|
||||
#include "browser_appcache_system.h"
|
||||
#include "browser_resource_loader_bridge.h"
|
||||
#include "browser_socket_stream_bridge.h"
|
||||
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <Objbase.h>
|
||||
#endif
|
||||
|
||||
CefProcessIOThread::CefProcessIOThread()
|
||||
: CefThread(CefThread::IO), request_context_(NULL) {}
|
||||
|
||||
CefProcessIOThread::CefProcessIOThread(MessageLoop* message_loop)
|
||||
: CefThread(CefThread::IO, message_loop), request_context_(NULL) {}
|
||||
|
||||
CefProcessIOThread::~CefProcessIOThread() {
|
||||
// We cannot rely on our base class to stop the thread since we want our
|
||||
// CleanUp function to run.
|
||||
Stop();
|
||||
}
|
||||
|
||||
void CefProcessIOThread::Init() {
|
||||
#if defined(OS_WIN)
|
||||
// Initializes the COM library on the current thread.
|
||||
CoInitialize(NULL);
|
||||
#endif
|
||||
|
||||
request_context_ = new BrowserRequestContext(FilePath(_Context->cache_path()),
|
||||
net::HttpCache::NORMAL, false);
|
||||
_Context->set_request_context(request_context_);
|
||||
|
||||
BrowserAppCacheSystem::InitializeOnIOThread(request_context_);
|
||||
BrowserSocketStreamBridge::InitializeOnIOThread(request_context_);
|
||||
}
|
||||
|
||||
void CefProcessIOThread::CleanUp() {
|
||||
// Flush any remaining messages. This ensures that any accumulated
|
||||
// Task objects get destroyed before we exit, which avoids noise in
|
||||
// purify leak-test results.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
|
||||
BrowserSocketStreamBridge::Cleanup();
|
||||
|
||||
_Context->set_request_context(NULL);
|
||||
request_context_ = NULL;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Closes the COM library on the current thread. CoInitialize must
|
||||
// be balanced by a corresponding call to CoUninitialize.
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
40
libcef/cef_process_io_thread.h
Normal file
40
libcef/cef_process_io_thread.h
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _CEF_PROCESS_IO_THREAD
|
||||
#define _CEF_PROCESS_IO_THREAD
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "cef_thread.h"
|
||||
#include "browser_request_context.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CefProcessIOThread
|
||||
//
|
||||
// This simple thread object is used for the specialized threads that the
|
||||
// CefProcess spins up.
|
||||
//
|
||||
// Applications must initialize the COM library before they can call
|
||||
// COM library functions other than CoGetMalloc and memory allocation
|
||||
// functions, so this class initializes COM for those users.
|
||||
class CefProcessIOThread : public CefThread {
|
||||
public:
|
||||
explicit CefProcessIOThread();
|
||||
CefProcessIOThread(MessageLoop* message_loop);
|
||||
virtual ~CefProcessIOThread();
|
||||
|
||||
virtual void Init();
|
||||
virtual void CleanUp();
|
||||
|
||||
scoped_refptr<BrowserRequestContext> request_context()
|
||||
{ return request_context_; }
|
||||
|
||||
private:
|
||||
scoped_refptr<BrowserRequestContext> request_context_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefProcessIOThread);
|
||||
};
|
||||
|
||||
#endif // _CEF_PROCESS_UI_THREAD
|
44
libcef/cef_process_sub_thread.cc
Normal file
44
libcef/cef_process_sub_thread.cc
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "cef_process_sub_thread.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <Objbase.h>
|
||||
#endif
|
||||
|
||||
CefProcessSubThread::CefProcessSubThread(CefThread::ID identifier)
|
||||
: CefThread(identifier) {}
|
||||
|
||||
CefProcessSubThread::CefProcessSubThread(CefThread::ID identifier,
|
||||
MessageLoop* message_loop)
|
||||
: CefThread(identifier, message_loop) {}
|
||||
|
||||
CefProcessSubThread::~CefProcessSubThread() {
|
||||
// We cannot rely on our base class to stop the thread since we want our
|
||||
// CleanUp function to run.
|
||||
Stop();
|
||||
}
|
||||
|
||||
void CefProcessSubThread::Init() {
|
||||
#if defined(OS_WIN)
|
||||
// Initializes the COM library on the current thread.
|
||||
CoInitialize(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CefProcessSubThread::CleanUp() {
|
||||
// Flush any remaining messages. This ensures that any accumulated
|
||||
// Task objects get destroyed before we exit, which avoids noise in
|
||||
// purify leak-test results.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Closes the COM library on the current thread. CoInitialize must
|
||||
// be balanced by a corresponding call to CoUninitialize.
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
35
libcef/cef_process_sub_thread.h
Normal file
35
libcef/cef_process_sub_thread.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _CEF_PROCESS_SUB_THREAD
|
||||
#define _CEF_PROCESS_SUB_THREAD
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "cef_thread.h"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CefProcessSubThread
|
||||
//
|
||||
// This simple thread object is used for the specialized threads that the
|
||||
// CefProcess spins up.
|
||||
//
|
||||
// Applications must initialize the COM library before they can call
|
||||
// COM library functions other than CoGetMalloc and memory allocation
|
||||
// functions, so this class initializes COM for those users.
|
||||
class CefProcessSubThread : public CefThread {
|
||||
public:
|
||||
explicit CefProcessSubThread(CefThread::ID identifier);
|
||||
CefProcessSubThread(CefThread::ID identifier, MessageLoop* message_loop);
|
||||
virtual ~CefProcessSubThread();
|
||||
|
||||
protected:
|
||||
virtual void Init();
|
||||
virtual void CleanUp();
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(CefProcessSubThread);
|
||||
};
|
||||
|
||||
#endif // _CEF_PROCESS_SUB_THREAD
|
153
libcef/cef_process_ui_thread.cc
Normal file
153
libcef/cef_process_ui_thread.cc
Normal file
@ -0,0 +1,153 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "cef_process_ui_thread.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_resource_loader_bridge.h"
|
||||
#include "browser_request_context.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#include "browser_webkit_init.h"
|
||||
#include "cef_context.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "base/stats_table.h"
|
||||
#include "build/build_config.h"
|
||||
#include "net/base/net_module.h"
|
||||
#if defined(OS_WIN)
|
||||
#include "net/socket/ssl_client_socket_nss_factory.h"
|
||||
#endif
|
||||
#include "webkit/extensions/v8/gc_extension.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include <commctrl.h>
|
||||
#include <Objbase.h>
|
||||
#endif
|
||||
|
||||
static const char* kStatsFilePrefix = "libcef_";
|
||||
static int kStatsFileThreads = 20;
|
||||
static int kStatsFileCounters = 200;
|
||||
|
||||
CefProcessUIThread::CefProcessUIThread()
|
||||
: CefThread(CefThread::UI), statstable_(NULL), webkit_init_(NULL) {}
|
||||
|
||||
CefProcessUIThread::CefProcessUIThread(MessageLoop* message_loop)
|
||||
: CefThread(CefThread::UI, message_loop), statstable_(NULL),
|
||||
webkit_init_(NULL) {}
|
||||
|
||||
CefProcessUIThread::~CefProcessUIThread() {
|
||||
// We cannot rely on our base class to stop the thread since we want our
|
||||
// CleanUp function to run.
|
||||
Stop();
|
||||
}
|
||||
|
||||
void CefProcessUIThread::Init() {
|
||||
#if defined(OS_WIN)
|
||||
HRESULT res;
|
||||
|
||||
// Initialize common controls
|
||||
res = CoInitialize(NULL);
|
||||
DCHECK(SUCCEEDED(res));
|
||||
INITCOMMONCONTROLSEX InitCtrlEx;
|
||||
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||||
InitCtrlEx.dwICC = ICC_STANDARD_CLASSES;
|
||||
InitCommonControlsEx(&InitCtrlEx);
|
||||
|
||||
// Start COM stuff
|
||||
res = OleInitialize(NULL);
|
||||
DCHECK(SUCCEEDED(res));
|
||||
|
||||
// Register the window class
|
||||
WNDCLASSEX wcex = {
|
||||
/* cbSize = */ sizeof(WNDCLASSEX),
|
||||
/* style = */ CS_HREDRAW | CS_VREDRAW,
|
||||
/* lpfnWndProc = */ CefBrowserImpl::WndProc,
|
||||
/* cbClsExtra = */ 0,
|
||||
/* cbWndExtra = */ 0,
|
||||
/* hInstance = */ ::GetModuleHandle(NULL),
|
||||
/* hIcon = */ NULL,
|
||||
/* hCursor = */ LoadCursor(NULL, IDC_ARROW),
|
||||
/* hbrBackground = */ 0,
|
||||
/* lpszMenuName = */ NULL,
|
||||
/* lpszClassName = */ CefBrowserImpl::GetWndClass(),
|
||||
/* hIconSm = */ NULL,
|
||||
};
|
||||
RegisterClassEx(&wcex);
|
||||
#endif
|
||||
|
||||
#ifndef _DEBUG
|
||||
// Only log error messages and above in release build.
|
||||
logging::SetMinLogLevel(logging::LOG_ERROR);
|
||||
#endif
|
||||
|
||||
// Initialize the global CommandLine object.
|
||||
CommandLine::Init(0, NULL);
|
||||
|
||||
// Initialize WebKit.
|
||||
webkit_init_ = new BrowserWebKitInit();
|
||||
|
||||
// Initialize WebKit encodings
|
||||
webkit_glue::InitializeTextEncoding();
|
||||
|
||||
// Load ICU data tables.
|
||||
bool ret = icu_util::Initialize();
|
||||
if(!ret) {
|
||||
#if defined(OS_WIN)
|
||||
MessageBox(NULL, L"Failed to load the required icudt38 library",
|
||||
L"CEF Initialization Error", MB_ICONERROR | MB_OK);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Config the network module so it has access to a limited set of resources.
|
||||
net::NetModule::SetResourceProvider(webkit_glue::NetResourceProvider);
|
||||
|
||||
// Load and initialize the stats table. Attempt to construct a somewhat
|
||||
// unique name to isolate separate instances from each other.
|
||||
statstable_ = new StatsTable(
|
||||
kStatsFilePrefix + Uint64ToString(base::RandUint64()),
|
||||
kStatsFileThreads,
|
||||
kStatsFileCounters);
|
||||
StatsTable::set_current(statstable_);
|
||||
|
||||
// CEF always exposes the GC.
|
||||
webkit_glue::SetJavaScriptFlags(L"--expose-gc");
|
||||
// Expose GCController to JavaScript.
|
||||
WebKit::WebScriptController::registerExtension(
|
||||
extensions_v8::GCExtension::Get());
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Use NSS for SSL on Windows. TODO(wtc): this should eventually be hidden
|
||||
// inside DefaultClientSocketFactory::CreateSSLClientSocket.
|
||||
net::ClientSocketFactory::SetSSLClientSocketFactory(
|
||||
net::SSLClientSocketNSSFactory);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CefProcessUIThread::CleanUp() {
|
||||
// Flush any remaining messages. This ensures that any accumulated
|
||||
// Task objects get destroyed before we exit, which avoids noise in
|
||||
// purify leak-test results.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
|
||||
// Tear down the shared StatsTable.
|
||||
StatsTable::set_current(NULL);
|
||||
delete statstable_;
|
||||
statstable_ = NULL;
|
||||
|
||||
// Shut down WebKit.
|
||||
delete webkit_init_;
|
||||
webkit_init_ = NULL;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Uninitialize COM stuff
|
||||
OleUninitialize();
|
||||
|
||||
// Closes the COM library on the current thread. CoInitialize must
|
||||
// be balanced by a corresponding call to CoUninitialize.
|
||||
CoUninitialize();
|
||||
#endif
|
||||
}
|
42
libcef/cef_process_ui_thread.h
Normal file
42
libcef/cef_process_ui_thread.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _CEF_PROCESS_UI_THREAD
|
||||
#define _CEF_PROCESS_UI_THREAD
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "cef_thread.h"
|
||||
|
||||
class BrowserWebKitInit;
|
||||
class StatsTable;
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// CefProcessUIThread
|
||||
//
|
||||
// This simple thread object is used for the specialized threads that the
|
||||
// CefProcess spins up.
|
||||
//
|
||||
// Applications must initialize the COM library before they can call
|
||||
// COM library functions other than CoGetMalloc and memory allocation
|
||||
// functions, so this class initializes COM for those users.
|
||||
class CefProcessUIThread : public CefThread {
|
||||
public:
|
||||
explicit CefProcessUIThread();
|
||||
CefProcessUIThread(MessageLoop* message_loop);
|
||||
virtual ~CefProcessUIThread();
|
||||
|
||||
virtual void Init();
|
||||
virtual void CleanUp();
|
||||
|
||||
private:
|
||||
StatsTable* statstable_;
|
||||
|
||||
// WebKit implementation class.
|
||||
BrowserWebKitInit* webkit_init_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CefProcessUIThread);
|
||||
};
|
||||
|
||||
#endif // _CEF_PROCESS_UI_THREAD
|
210
libcef/cef_thread.cc
Normal file
210
libcef/cef_thread.cc
Normal file
@ -0,0 +1,210 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "cef_thread.h"
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "base/message_loop_proxy.h"
|
||||
|
||||
using base::MessageLoopProxy;
|
||||
|
||||
// Friendly names for the well-known threads.
|
||||
static const char* cef_thread_names[CefThread::ID_COUNT] = {
|
||||
"Cef_UIThread", // UI
|
||||
"Cef_FileThread", // FILE
|
||||
"Cef_IOThread", // IO
|
||||
};
|
||||
|
||||
// An implementation of MessageLoopProxy to be used in conjunction
|
||||
// with CefThread.
|
||||
class CefThreadMessageLoopProxy : public MessageLoopProxy {
|
||||
public:
|
||||
explicit CefThreadMessageLoopProxy(CefThread::ID identifier)
|
||||
: id_(identifier) {
|
||||
}
|
||||
|
||||
// MessageLoopProxy implementation.
|
||||
virtual bool PostTask(const tracked_objects::Location& from_here,
|
||||
Task* task) {
|
||||
return CefThread::PostTask(id_, from_here, task);
|
||||
}
|
||||
|
||||
virtual bool PostDelayedTask(const tracked_objects::Location& from_here,
|
||||
Task* task, int64 delay_ms) {
|
||||
return CefThread::PostDelayedTask(id_, from_here, task, delay_ms);
|
||||
}
|
||||
|
||||
virtual bool PostNonNestableTask(const tracked_objects::Location& from_here,
|
||||
Task* task) {
|
||||
return CefThread::PostNonNestableTask(id_, from_here, task);
|
||||
}
|
||||
|
||||
virtual bool PostNonNestableDelayedTask(
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms) {
|
||||
return CefThread::PostNonNestableDelayedTask(id_, from_here, task,
|
||||
delay_ms);
|
||||
}
|
||||
virtual bool BelongsToCurrentThread() {
|
||||
return CefThread::CurrentlyOn(id_);
|
||||
}
|
||||
|
||||
private:
|
||||
CefThread::ID id_;
|
||||
DISALLOW_COPY_AND_ASSIGN(CefThreadMessageLoopProxy);
|
||||
};
|
||||
|
||||
|
||||
Lock CefThread::lock_;
|
||||
|
||||
CefThread* CefThread::cef_threads_[ID_COUNT];
|
||||
|
||||
CefThread::CefThread(CefThread::ID identifier)
|
||||
: Thread(cef_thread_names[identifier]),
|
||||
identifier_(identifier) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
CefThread::CefThread(ID identifier, MessageLoop* message_loop)
|
||||
: Thread(cef_thread_names[identifier]),
|
||||
identifier_(identifier) {
|
||||
message_loop->set_thread_name(cef_thread_names[identifier]);
|
||||
set_message_loop(message_loop);
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void CefThread::Initialize() {
|
||||
AutoLock lock(lock_);
|
||||
DCHECK(identifier_ >= 0 && identifier_ < ID_COUNT);
|
||||
DCHECK(cef_threads_[identifier_] == NULL);
|
||||
cef_threads_[identifier_] = this;
|
||||
}
|
||||
|
||||
CefThread::~CefThread() {
|
||||
// Stop the thread here, instead of the parent's class destructor. This is so
|
||||
// that if there are pending tasks that run, code that checks that it's on the
|
||||
// correct CefThread succeeds.
|
||||
Stop();
|
||||
|
||||
AutoLock lock(lock_);
|
||||
cef_threads_[identifier_] = NULL;
|
||||
#ifndef NDEBUG
|
||||
// Double check that the threads are ordererd correctly in the enumeration.
|
||||
for (int i = identifier_ + 1; i < ID_COUNT; ++i) {
|
||||
DCHECK(!cef_threads_[i]) <<
|
||||
"Threads must be listed in the reverse order that they die";
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::IsWellKnownThread(ID identifier) {
|
||||
AutoLock lock(lock_);
|
||||
return (identifier >= 0 && identifier < ID_COUNT &&
|
||||
cef_threads_[identifier]);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::CurrentlyOn(ID identifier) {
|
||||
AutoLock lock(lock_);
|
||||
DCHECK(identifier >= 0 && identifier < ID_COUNT);
|
||||
return cef_threads_[identifier] &&
|
||||
cef_threads_[identifier]->message_loop() == MessageLoop::current();
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::PostTask(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task) {
|
||||
return PostTaskHelper(identifier, from_here, task, 0, true);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::PostDelayedTask(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms) {
|
||||
return PostTaskHelper(identifier, from_here, task, delay_ms, true);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::PostNonNestableTask(
|
||||
ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task) {
|
||||
return PostTaskHelper(identifier, from_here, task, 0, false);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::PostNonNestableDelayedTask(
|
||||
ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms) {
|
||||
return PostTaskHelper(identifier, from_here, task, delay_ms, false);
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::GetCurrentThreadIdentifier(ID* identifier) {
|
||||
MessageLoop* cur_message_loop = MessageLoop::current();
|
||||
for (int i = 0; i < ID_COUNT; ++i) {
|
||||
if (cef_threads_[i] &&
|
||||
cef_threads_[i]->message_loop() == cur_message_loop) {
|
||||
*identifier = cef_threads_[i]->identifier_;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
scoped_refptr<MessageLoopProxy> CefThread::GetMessageLoopProxyForThread(
|
||||
ID identifier) {
|
||||
scoped_refptr<MessageLoopProxy> proxy =
|
||||
new CefThreadMessageLoopProxy(identifier);
|
||||
return proxy;
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefThread::PostTaskHelper(
|
||||
ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms,
|
||||
bool nestable) {
|
||||
DCHECK(identifier >= 0 && identifier < ID_COUNT);
|
||||
// Optimization: to avoid unnecessary locks, we listed the ID enumeration in
|
||||
// order of lifetime. So no need to lock if we know that the other thread
|
||||
// outlives this one.
|
||||
// Note: since the array is so small, ok to loop instead of creating a map,
|
||||
// which would require a lock because std::map isn't thread safe, defeating
|
||||
// the whole purpose of this optimization.
|
||||
ID current_thread;
|
||||
bool guaranteed_to_outlive_target_thread =
|
||||
GetCurrentThreadIdentifier(¤t_thread) &&
|
||||
current_thread >= identifier;
|
||||
|
||||
if (!guaranteed_to_outlive_target_thread)
|
||||
lock_.Acquire();
|
||||
|
||||
MessageLoop* message_loop = cef_threads_[identifier] ?
|
||||
cef_threads_[identifier]->message_loop() : NULL;
|
||||
if (message_loop) {
|
||||
if (nestable) {
|
||||
message_loop->PostDelayedTask(from_here, task, delay_ms);
|
||||
} else {
|
||||
message_loop->PostNonNestableDelayedTask(from_here, task, delay_ms);
|
||||
}
|
||||
} else {
|
||||
delete task;
|
||||
}
|
||||
|
||||
if (!guaranteed_to_outlive_target_thread)
|
||||
lock_.Release();
|
||||
|
||||
return !!message_loop;
|
||||
}
|
185
libcef/cef_thread.h
Normal file
185
libcef/cef_thread.h
Normal file
@ -0,0 +1,185 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2010 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _CEF_THREAD_H
|
||||
#define _CEF_THREAD_H
|
||||
|
||||
#include "base/lock.h"
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
namespace base {
|
||||
class MessageLoopProxy;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CefThread
|
||||
//
|
||||
// This class represents a thread that is known by a browser-wide name. For
|
||||
// example, there is one IO thread for the entire browser process, and various
|
||||
// pieces of code find it useful to retrieve a pointer to the IO thread's
|
||||
// Invoke a task by thread ID:
|
||||
//
|
||||
// CefThread::PostTask(CefThread::IO, FROM_HERE, task);
|
||||
//
|
||||
// The return value is false if the task couldn't be posted because the target
|
||||
// thread doesn't exist. If this could lead to data loss, you need to check the
|
||||
// result and restructure the code to ensure it doesn't occur.
|
||||
//
|
||||
// This class automatically handles the lifetime of different threads.
|
||||
// It's always safe to call PostTask on any thread. If it's not yet created,
|
||||
// the task is deleted. There are no race conditions. If the thread that the
|
||||
// task is posted to is guaranteed to outlive the current thread, then no locks
|
||||
// are used. You should never need to cache pointers to MessageLoops, since
|
||||
// they're not thread safe.
|
||||
class CefThread : public base::Thread {
|
||||
public:
|
||||
// An enumeration of the well-known threads.
|
||||
// NOTE: threads must be listed in the order of their life-time, with each
|
||||
// thread outliving every other thread below it.
|
||||
enum ID {
|
||||
// The main thread in the browser.
|
||||
UI,
|
||||
|
||||
// This is the thread that interacts with the file system.
|
||||
FILE,
|
||||
|
||||
// This is the thread that processes IPC and network messages.
|
||||
IO,
|
||||
|
||||
// This identifier does not represent a thread. Instead it counts the
|
||||
// number of well-known threads. Insert new well-known threads before this
|
||||
// identifier.
|
||||
ID_COUNT
|
||||
};
|
||||
|
||||
// Construct a CefThread with the supplied identifier. It is an error
|
||||
// to construct a CefThread that already exists.
|
||||
explicit CefThread(ID identifier);
|
||||
|
||||
// Special constructor for the main (UI) thread and unittests. We use a dummy
|
||||
// thread here since the main thread already exists.
|
||||
CefThread(ID identifier, MessageLoop* message_loop);
|
||||
|
||||
virtual ~CefThread();
|
||||
|
||||
// These are the same methods in message_loop.h, but are guaranteed to either
|
||||
// get posted to the MessageLoop if it's still alive, or be deleted otherwise.
|
||||
// They return true if the thread existed and the task was posted. Note that
|
||||
// even if the task is posted, there's no guarantee that it will run, since
|
||||
// the target thread may already have a Quit message in its queue.
|
||||
static bool PostTask(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task);
|
||||
static bool PostDelayedTask(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms);
|
||||
static bool PostNonNestableTask(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task);
|
||||
static bool PostNonNestableDelayedTask(
|
||||
ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms);
|
||||
|
||||
template <class T>
|
||||
static bool DeleteSoon(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
T* object) {
|
||||
return PostNonNestableTask(
|
||||
identifier, from_here, new DeleteTask<T>(object));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
static bool ReleaseSoon(ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
T* object) {
|
||||
return PostNonNestableTask(
|
||||
identifier, from_here, new ReleaseTask<T>(object));
|
||||
}
|
||||
|
||||
// Callable on any thread. Returns whether the given ID corresponds to a well
|
||||
// known thread.
|
||||
static bool IsWellKnownThread(ID identifier);
|
||||
|
||||
// Callable on any thread. Returns whether you're currently on a particular
|
||||
// thread.
|
||||
static bool CurrentlyOn(ID identifier);
|
||||
|
||||
// If the current message loop is one of the known threads, returns true and
|
||||
// sets identifier to its ID. Otherwise returns false.
|
||||
static bool GetCurrentThreadIdentifier(ID* identifier);
|
||||
|
||||
// Callers can hold on to a refcounted MessageLoopProxy beyond the lifetime
|
||||
// of the thread.
|
||||
static scoped_refptr<base::MessageLoopProxy> GetMessageLoopProxyForThread(
|
||||
ID identifier);
|
||||
|
||||
// Use these templates in conjuction with RefCountedThreadSafe when you want
|
||||
// to ensure that an object is deleted on a specific thread. This is needed
|
||||
// when an object can hop between threads (i.e. IO -> FILE -> IO), and thread
|
||||
// switching delays can mean that the final IO tasks executes before the FILE
|
||||
// task's stack unwinds. This would lead to the object destructing on the
|
||||
// FILE thread, which often is not what you want (i.e. to unregister from
|
||||
// NotificationService, to notify other objects on the creating thread etc).
|
||||
template<ID thread>
|
||||
struct DeleteOnThread {
|
||||
template<typename T>
|
||||
static void Destruct(T* x) {
|
||||
if (CurrentlyOn(thread)) {
|
||||
delete x;
|
||||
} else {
|
||||
DeleteSoon(thread, FROM_HERE, x);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Sample usage:
|
||||
// class Foo
|
||||
// : public base::RefCountedThreadSafe<
|
||||
// Foo, CefThread::DeleteOnIOThread> {
|
||||
//
|
||||
// ...
|
||||
// private:
|
||||
// friend class CefThread;
|
||||
// friend class DeleteTask<Foo>;
|
||||
//
|
||||
// ~Foo();
|
||||
struct DeleteOnUIThread : public DeleteOnThread<UI> { };
|
||||
struct DeleteOnIOThread : public DeleteOnThread<IO> { };
|
||||
struct DeleteOnFileThread : public DeleteOnThread<FILE> { };
|
||||
|
||||
private:
|
||||
// Common initialization code for the constructors.
|
||||
void Initialize();
|
||||
|
||||
static bool PostTaskHelper(
|
||||
ID identifier,
|
||||
const tracked_objects::Location& from_here,
|
||||
Task* task,
|
||||
int64 delay_ms,
|
||||
bool nestable);
|
||||
|
||||
// The identifier of this thread. Only one thread can exist with a given
|
||||
// identifier at a given time.
|
||||
ID identifier_;
|
||||
|
||||
// This lock protects |cef_threads_|. Do not read or modify that array
|
||||
// without holding this lock. Do not block while holding this lock.
|
||||
static Lock lock_;
|
||||
|
||||
// An array of the CefThread objects. This array is protected by |lock_|.
|
||||
// The threads are not owned by this array. Typically, the threads are owned
|
||||
// on the UI thread by the g_browser_process object. CefThreads remove
|
||||
// themselves from this array upon destruction.
|
||||
static CefThread* cef_threads_[ID_COUNT];
|
||||
};
|
||||
|
||||
#define REQUIRE_UIT() DCHECK(CefThread::CurrentlyOn(CefThread::UI))
|
||||
#define REQUIRE_IOT() DCHECK(CefThread::CurrentlyOn(CefThread::IO))
|
||||
|
||||
#endif // _CEF_THREAD_H
|
@ -1,593 +0,0 @@
|
||||
// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "context.h"
|
||||
#include "browser_impl.h"
|
||||
#include "browser_resource_loader_bridge.h"
|
||||
#include "browser_request_context.h"
|
||||
#include "browser_webkit_glue.h"
|
||||
#include "browser_webkit_init.h"
|
||||
#include "../include/cef_nplugin.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/i18n/icu_util.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/rand_util.h"
|
||||
#include "base/resource_util.h"
|
||||
#include "base/stats_table.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "net/base/net_module.h"
|
||||
#include "third_party/WebKit/WebKit/chromium/public/WebScriptController.h"
|
||||
#include "webkit/extensions/v8/gc_extension.h"
|
||||
#include "webkit/glue/plugins/webplugin.h"
|
||||
#include "webkit/glue/plugins/plugin_lib.h"
|
||||
#include "webkit/glue/plugins/plugin_list.h"
|
||||
|
||||
#include <commctrl.h>
|
||||
|
||||
|
||||
// Global CefContext pointer
|
||||
CefRefPtr<CefContext> _Context;
|
||||
|
||||
static const char* kStatsFilePrefix = "libcef_";
|
||||
static int kStatsFileThreads = 20;
|
||||
static int kStatsFileCounters = 200;
|
||||
|
||||
|
||||
// Class used to process events on the current message loop.
|
||||
class CefMessageLoopForUI : public MessageLoopForUI
|
||||
{
|
||||
typedef MessageLoopForUI inherited;
|
||||
|
||||
public:
|
||||
CefMessageLoopForUI()
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool DoIdleWork() {
|
||||
bool valueToRet = inherited::DoIdleWork();
|
||||
pump_->Quit();
|
||||
return valueToRet;
|
||||
}
|
||||
|
||||
void DoMessageLoopIteration() {
|
||||
Run(NULL);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
bool CefInitialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path)
|
||||
{
|
||||
// Return true if the context is already initialized
|
||||
if(_Context.get())
|
||||
return true;
|
||||
|
||||
// Create the new global context object
|
||||
_Context = new CefContext();
|
||||
// Initialize the glboal context
|
||||
return _Context->Initialize(multi_threaded_message_loop, cache_path);
|
||||
}
|
||||
|
||||
void CefShutdown()
|
||||
{
|
||||
// Verify that the context is already initialized
|
||||
if(!_Context.get())
|
||||
return;
|
||||
|
||||
// Shut down the global context
|
||||
_Context->Shutdown();
|
||||
// Delete the global context object
|
||||
_Context = NULL;
|
||||
}
|
||||
|
||||
void CefDoMessageLoopWork()
|
||||
{
|
||||
if(!_Context->RunningOnUIThread())
|
||||
return;
|
||||
((CefMessageLoopForUI*)CefMessageLoopForUI::current())->DoMessageLoopIteration();
|
||||
}
|
||||
|
||||
bool CefRegisterPlugin(const struct CefPluginInfo& plugin_info)
|
||||
{
|
||||
if(!_Context.get())
|
||||
return false;
|
||||
|
||||
CefPluginInfo* pPluginInfo = new CefPluginInfo;
|
||||
*pPluginInfo = plugin_info;
|
||||
|
||||
PostTask(FROM_HERE, NewRunnableMethod(_Context.get(),
|
||||
&CefContext::UIT_RegisterPlugin, pPluginInfo));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefContext::UIT_RegisterPlugin(struct CefPluginInfo* plugin_info)
|
||||
{
|
||||
REQUIRE_UIT();
|
||||
|
||||
NPAPI::PluginVersionInfo info;
|
||||
|
||||
info.path = FilePath(plugin_info->unique_name);
|
||||
info.product_name = plugin_info->display_name;
|
||||
info.file_description = plugin_info->description;
|
||||
info.file_version =plugin_info->version;
|
||||
|
||||
for(size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
|
||||
if(i > 0) {
|
||||
info.mime_types += L"|";
|
||||
info.file_extensions += L"|";
|
||||
info.type_descriptions += L"|";
|
||||
}
|
||||
|
||||
info.mime_types += plugin_info->mime_types[i].mime_type;
|
||||
info.type_descriptions += plugin_info->mime_types[i].description;
|
||||
|
||||
for(size_t j = 0;
|
||||
j < plugin_info->mime_types[i].file_extensions.size(); ++j) {
|
||||
if(j > 0) {
|
||||
info.file_extensions += L",";
|
||||
}
|
||||
info.file_extensions += plugin_info->mime_types[i].file_extensions[j];
|
||||
}
|
||||
}
|
||||
|
||||
info.entry_points.np_getentrypoints = plugin_info->np_getentrypoints;
|
||||
info.entry_points.np_initialize = plugin_info->np_initialize;
|
||||
info.entry_points.np_shutdown = plugin_info->np_shutdown;
|
||||
|
||||
NPAPI::PluginList::Singleton()->RegisterInternalPlugin(info);
|
||||
|
||||
delete plugin_info;
|
||||
}
|
||||
|
||||
bool CefContext::DoInitialize()
|
||||
{
|
||||
HRESULT res;
|
||||
|
||||
// Initialize common controls
|
||||
res = CoInitialize(NULL);
|
||||
DCHECK(SUCCEEDED(res));
|
||||
INITCOMMONCONTROLSEX InitCtrlEx;
|
||||
InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
||||
InitCtrlEx.dwICC = ICC_STANDARD_CLASSES;
|
||||
InitCommonControlsEx(&InitCtrlEx);
|
||||
|
||||
// Start COM stuff
|
||||
res = OleInitialize(NULL);
|
||||
DCHECK(SUCCEEDED(res));
|
||||
|
||||
// Initialize the global CommandLine object.
|
||||
CommandLine::Init(0, NULL);
|
||||
|
||||
// Initialize WebKit.
|
||||
webkit_init_ = new BrowserWebKitInit();
|
||||
|
||||
// Initialize WebKit encodings
|
||||
webkit_glue::InitializeTextEncoding();
|
||||
|
||||
// Initializing with a default context, which means no on-disk cookie DB,
|
||||
// and no support for directory listings.
|
||||
//PathService::Get(base::DIR_EXE, &cache_path);
|
||||
BrowserResourceLoaderBridge::Init(FilePath(cache_path_), net::HttpCache::NORMAL,
|
||||
false);
|
||||
|
||||
// Load ICU data tables.
|
||||
bool ret = icu_util::Initialize();
|
||||
if(!ret) {
|
||||
MessageBox(NULL, L"Failed to load the required icudt38 library",
|
||||
L"CEF Initialization Error", MB_ICONERROR | MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Config the network module so it has access to a limited set of resources.
|
||||
net::NetModule::SetResourceProvider(webkit_glue::NetResourceProvider);
|
||||
|
||||
// Load and initialize the stats table. Attempt to construct a somewhat
|
||||
// unique name to isolate separate instances from each other.
|
||||
statstable_ = new StatsTable(
|
||||
kStatsFilePrefix + Uint64ToString(base::RandUint64()),
|
||||
kStatsFileThreads,
|
||||
kStatsFileCounters);
|
||||
StatsTable::set_current(statstable_);
|
||||
|
||||
// CEF always exposes the GC.
|
||||
webkit_glue::SetJavaScriptFlags(L"--expose-gc");
|
||||
// Expose GCController to JavaScript.
|
||||
WebKit::WebScriptController::registerExtension(
|
||||
extensions_v8::GCExtension::Get());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefContext::DoUninitialize()
|
||||
{
|
||||
// Flush any remaining messages. This ensures that any accumulated
|
||||
// Task objects get destroyed before we exit, which avoids noise in
|
||||
// purify leak-test results.
|
||||
MessageLoop::current()->RunAllPending();
|
||||
|
||||
BrowserResourceLoaderBridge::Shutdown();
|
||||
|
||||
// Tear down the shared StatsTable.
|
||||
StatsTable::set_current(NULL);
|
||||
delete statstable_;
|
||||
statstable_ = NULL;
|
||||
|
||||
// Shut down WebKit.
|
||||
delete webkit_init_;
|
||||
webkit_init_ = NULL;
|
||||
|
||||
// Uninitialize COM stuff
|
||||
OleUninitialize();
|
||||
|
||||
// Uninitialize common controls
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
DWORD WINAPI ThreadHandlerUI(LPVOID lpParam)
|
||||
{
|
||||
CefContext *pContext = static_cast<CefContext*>(lpParam);
|
||||
|
||||
// AtExitManager is scoped to the UI thread.
|
||||
base::AtExitManager at_exit_manager;
|
||||
|
||||
if (!pContext->DoInitialize())
|
||||
return 1;
|
||||
|
||||
// Instantiate the message loop for this thread.
|
||||
MessageLoopForUI main_message_loop;
|
||||
pContext->SetMessageLoopForUI(&main_message_loop);
|
||||
|
||||
// Notify the context that initialization is complete so that the
|
||||
// Initialize() function can return.
|
||||
pContext->NotifyEvent();
|
||||
|
||||
// Execute the message loop that will run until a quit task is received.
|
||||
MessageLoop::current()->Run();
|
||||
|
||||
pContext->DoUninitialize();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
CefContext::CefContext()
|
||||
{
|
||||
multi_threaded_message_loop_ = false;
|
||||
hthreadui_ = NULL;
|
||||
idthreadui_ = 0;
|
||||
heventui_ = NULL;
|
||||
messageloopui_ = NULL;
|
||||
in_transition_ = false;
|
||||
webprefs_ = NULL;
|
||||
statstable_ = NULL;
|
||||
at_exit_manager_ = NULL;
|
||||
hinstance_ = ::GetModuleHandle(NULL);
|
||||
next_browser_id_ = 1;
|
||||
webkit_init_ = NULL;
|
||||
}
|
||||
|
||||
CefContext::~CefContext()
|
||||
{
|
||||
// Just in case CefShutdown() isn't called
|
||||
Shutdown();
|
||||
if(!multi_threaded_message_loop_) {
|
||||
if(messageloopui_)
|
||||
delete messageloopui_;
|
||||
if(at_exit_manager_)
|
||||
delete at_exit_manager_;
|
||||
}
|
||||
}
|
||||
|
||||
bool CefContext::Initialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path)
|
||||
{
|
||||
bool initialized = false, intransition = false;
|
||||
|
||||
Lock();
|
||||
|
||||
// We only need to initialize if the UI thread is not currently running
|
||||
if(!idthreadui_) {
|
||||
// Only start the initialization if we're not currently in a transitional
|
||||
// state
|
||||
intransition = in_transition_;
|
||||
if(!intransition) {
|
||||
// We are now in a transitional state
|
||||
in_transition_ = true;
|
||||
|
||||
cache_path_ = cache_path;
|
||||
|
||||
// Register the window class
|
||||
WNDCLASSEX wcex = {
|
||||
/* cbSize = */ sizeof(WNDCLASSEX),
|
||||
/* style = */ CS_HREDRAW | CS_VREDRAW,
|
||||
/* lpfnWndProc = */ CefBrowserImpl::WndProc,
|
||||
/* cbClsExtra = */ 0,
|
||||
/* cbWndExtra = */ 0,
|
||||
/* hInstance = */ hinstance_,
|
||||
/* hIcon = */ NULL,
|
||||
/* hCursor = */ LoadCursor(NULL, IDC_ARROW),
|
||||
/* hbrBackground = */ 0,
|
||||
/* lpszMenuName = */ NULL,
|
||||
/* lpszClassName = */ CefBrowserImpl::GetWndClass(),
|
||||
/* hIconSm = */ NULL,
|
||||
};
|
||||
RegisterClassEx(&wcex);
|
||||
|
||||
#ifndef _DEBUG
|
||||
// Only log error messages and above in release build.
|
||||
logging::SetMinLogLevel(logging::LOG_ERROR);
|
||||
#endif
|
||||
|
||||
// Initialize web preferences
|
||||
webprefs_ = new WebPreferences;
|
||||
*webprefs_ = WebPreferences();
|
||||
webprefs_->standard_font_family = L"Times";
|
||||
webprefs_->fixed_font_family = L"Courier";
|
||||
webprefs_->serif_font_family = L"Times";
|
||||
webprefs_->sans_serif_font_family = L"Helvetica";
|
||||
// These two fonts are picked from the intersection of
|
||||
// Win XP font list and Vista font list :
|
||||
// http://www.microsoft.com/typography/fonts/winxp.htm
|
||||
// http://blogs.msdn.com/michkap/archive/2006/04/04/567881.aspx
|
||||
// Some of them are installed only with CJK and complex script
|
||||
// support enabled on Windows XP and are out of consideration here.
|
||||
// (although we enabled both on our buildbots.)
|
||||
// They (especially Impact for fantasy) are not typical cursive
|
||||
// and fantasy fonts, but it should not matter for layout tests
|
||||
// as long as they're available.
|
||||
#if defined(OS_MACOSX)
|
||||
webprefs_->cursive_font_family = L"Apple Chancery";
|
||||
webprefs_->fantasy_font_family = L"Papyrus";
|
||||
#else
|
||||
webprefs_->cursive_font_family = L"Comic Sans MS";
|
||||
webprefs_->fantasy_font_family = L"Impact";
|
||||
#endif
|
||||
webprefs_->default_encoding = "ISO-8859-1";
|
||||
webprefs_->default_font_size = 16;
|
||||
webprefs_->default_fixed_font_size = 13;
|
||||
webprefs_->minimum_font_size = 1;
|
||||
webprefs_->minimum_logical_font_size = 9;
|
||||
webprefs_->javascript_can_open_windows_automatically = true;
|
||||
webprefs_->dom_paste_enabled = true;
|
||||
webprefs_->developer_extras_enabled = true;
|
||||
webprefs_->site_specific_quirks_enabled = true;
|
||||
webprefs_->shrinks_standalone_images_to_fit = false;
|
||||
webprefs_->uses_universal_detector = false;
|
||||
webprefs_->text_areas_are_resizable = true;
|
||||
webprefs_->java_enabled = true;
|
||||
webprefs_->allow_scripts_to_close_windows = false;
|
||||
webprefs_->xss_auditor_enabled = false;
|
||||
webprefs_->remote_fonts_enabled = true;
|
||||
webprefs_->local_storage_enabled = true;
|
||||
webprefs_->application_cache_enabled = true;
|
||||
webprefs_->databases_enabled = true;
|
||||
webprefs_->allow_file_access_from_file_urls = true;
|
||||
|
||||
if (multi_threaded_message_loop) {
|
||||
// Event that will be used to signal thread setup completion. Start
|
||||
// in non-signaled mode so that the event will block.
|
||||
heventui_ = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||
DCHECK(heventui_ != NULL);
|
||||
|
||||
// Thread that hosts the UI loop
|
||||
hthreadui_ = CreateThread(
|
||||
NULL, 0, ThreadHandlerUI, this, 0, &idthreadui_);
|
||||
DCHECK(hthreadui_ != NULL);
|
||||
DCHECK(idthreadui_ != 0);
|
||||
} else {
|
||||
// AtExitManager is scoped to the context.
|
||||
at_exit_manager_ = new base::AtExitManager;
|
||||
if (!DoInitialize()) {
|
||||
// TODO: Process initialization errors
|
||||
}
|
||||
// Message loop is scoped to the context.
|
||||
SetMessageLoopForUI(new CefMessageLoopForUI());
|
||||
idthreadui_ = GetCurrentThreadId();
|
||||
DCHECK(idthreadui_ != 0);
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if(initialized) {
|
||||
multi_threaded_message_loop_ = multi_threaded_message_loop;
|
||||
|
||||
if (multi_threaded_message_loop) {
|
||||
// Wait for initial UI thread setup to complete
|
||||
WaitForSingleObject(heventui_, INFINITE);
|
||||
}
|
||||
|
||||
Lock();
|
||||
|
||||
// We have exited the transitional state
|
||||
in_transition_ = false;
|
||||
|
||||
Unlock();
|
||||
}
|
||||
|
||||
return intransition ? false : true;
|
||||
}
|
||||
|
||||
void CefContext::Shutdown()
|
||||
{
|
||||
bool shutdown = false, intransition = false;
|
||||
BrowserList browserlist;
|
||||
|
||||
Lock();
|
||||
|
||||
// We only need to shut down if the UI thread is currently running
|
||||
if(idthreadui_) {
|
||||
// Only start the shutdown if we're not currently in a transitional state
|
||||
intransition = in_transition_;
|
||||
if(!intransition) {
|
||||
DCHECK(messageloopui_ != NULL);
|
||||
|
||||
// We are now in a transitional state
|
||||
in_transition_ = true;
|
||||
|
||||
browserlist = browserlist_;
|
||||
browserlist_.empty();
|
||||
|
||||
if(webprefs_) {
|
||||
delete webprefs_;
|
||||
webprefs_ = NULL;
|
||||
}
|
||||
|
||||
// Post the quit message to the UI message loop
|
||||
messageloopui_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
|
||||
|
||||
shutdown = true;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if(shutdown) {
|
||||
if (browserlist.size() > 0) {
|
||||
// Close any remaining browser windows
|
||||
BrowserList::const_iterator it = browserlist.begin();
|
||||
for (; it != browserlist.end(); ++it)
|
||||
PostMessage((*it)->GetWindowHandle(), WM_CLOSE, 0, 0);
|
||||
browserlist.empty();
|
||||
}
|
||||
|
||||
if (hthreadui_) {
|
||||
// Wait for the UI thread to exit
|
||||
WaitForSingleObject(hthreadui_, INFINITE);
|
||||
|
||||
// Clean up thread and event handles
|
||||
CloseHandle(hthreadui_);
|
||||
CloseHandle(heventui_);
|
||||
|
||||
hthreadui_ = NULL;
|
||||
heventui_ = NULL;
|
||||
} else {
|
||||
DoUninitialize();
|
||||
}
|
||||
|
||||
Lock();
|
||||
|
||||
// Unregister the window class
|
||||
UnregisterClass(CefBrowserImpl::GetWndClass(), hinstance_);
|
||||
|
||||
idthreadui_ = 0;
|
||||
|
||||
// We have exited the transitional state
|
||||
in_transition_ = false;
|
||||
|
||||
Unlock();
|
||||
}
|
||||
}
|
||||
|
||||
bool CefContext::AddBrowser(CefRefPtr<CefBrowserImpl> browser)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
Lock();
|
||||
|
||||
// check that the browser isn't already in the list before adding
|
||||
BrowserList::const_iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get() == browser.get()) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
{
|
||||
browser->UIT_SetUniqueID(next_browser_id_++);
|
||||
browserlist_.push_back(browser);
|
||||
}
|
||||
|
||||
Unlock();
|
||||
return !found;
|
||||
}
|
||||
|
||||
void CefContext::UIT_ClearCache()
|
||||
{
|
||||
webkit_glue::ClearCache();
|
||||
}
|
||||
|
||||
bool CefContext::RemoveBrowser(CefRefPtr<CefBrowserImpl> browser)
|
||||
{
|
||||
bool deleted = false;
|
||||
bool empty = false;
|
||||
|
||||
Lock();
|
||||
|
||||
BrowserList::iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get() == browser.get()) {
|
||||
browserlist_.erase(it);
|
||||
deleted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (browserlist_.empty()) {
|
||||
next_browser_id_ = 1;
|
||||
empty = true;
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
if (empty) {
|
||||
PostTask(FROM_HERE, NewRunnableMethod(_Context.get(),
|
||||
&CefContext::UIT_ClearCache));
|
||||
}
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserImpl> CefContext::GetBrowserByID(int id)
|
||||
{
|
||||
CefRefPtr<CefBrowserImpl> browser;
|
||||
Lock();
|
||||
|
||||
BrowserList::const_iterator it = browserlist_.begin();
|
||||
for(; it != browserlist_.end(); ++it) {
|
||||
if(it->get()->UIT_GetUniqueID() == id) {
|
||||
browser = it->get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Unlock();
|
||||
|
||||
return browser;
|
||||
}
|
||||
|
||||
void CefContext::SetMessageLoopForUI(MessageLoopForUI* loop)
|
||||
{
|
||||
Lock();
|
||||
messageloopui_ = loop;
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void CefContext::NotifyEvent()
|
||||
{
|
||||
Lock();
|
||||
// Set the event state to signaled so that the waiting thread will be
|
||||
// released.
|
||||
if(heventui_)
|
||||
SetEvent(heventui_);
|
||||
Unlock();
|
||||
}
|
||||
|
||||
void PostTask(const tracked_objects::Location& from_here, Task* task)
|
||||
{
|
||||
if(_Context.get()) {
|
||||
_Context->Lock();
|
||||
MessageLoopForUI *pMsgLoop = _Context->GetMessageLoopForUI();
|
||||
if(pMsgLoop)
|
||||
pMsgLoop->PostTask(from_here, task);
|
||||
_Context->Unlock();
|
||||
}
|
||||
}
|
110
libcef/context.h
110
libcef/context.h
@ -1,110 +0,0 @@
|
||||
// Copyright (c) 2008 The Chromium Embedded Framework Authors.
|
||||
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef _CONTEXT_H
|
||||
#define _CONTEXT_H
|
||||
|
||||
#include "../include/cef.h"
|
||||
#include "base/at_exit.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/stats_table.h"
|
||||
#include "gfx/native_widget_types.h"
|
||||
#include "webkit/glue/webpreferences.h"
|
||||
|
||||
class BrowserWebKitInit;
|
||||
class CefBrowserImpl;
|
||||
|
||||
class CefContext : public CefThreadSafeBase<CefBase>
|
||||
{
|
||||
public:
|
||||
typedef std::list<CefRefPtr<CefBrowserImpl> > BrowserList;
|
||||
|
||||
CefContext();
|
||||
~CefContext();
|
||||
|
||||
bool Initialize(bool multi_threaded_message_loop,
|
||||
const std::wstring& cache_path);
|
||||
void Shutdown();
|
||||
|
||||
MessageLoopForUI* GetMessageLoopForUI() { return messageloopui_; }
|
||||
|
||||
HMODULE GetInstanceHandle() { return hinstance_; }
|
||||
HANDLE GetUIThreadHandle() { return hthreadui_; }
|
||||
DWORD GetUIThreadId() { return idthreadui_; }
|
||||
WebPreferences* GetWebPreferences() { return webprefs_; }
|
||||
|
||||
// Retrieve the path at which cache data will be stored on disk. If empty,
|
||||
// cache data will be stored in-memory.
|
||||
std::wstring GetCachePath() { return cache_path_; }
|
||||
|
||||
bool AddBrowser(CefRefPtr<CefBrowserImpl> browser);
|
||||
bool RemoveBrowser(CefRefPtr<CefBrowserImpl> browser);
|
||||
CefRefPtr<CefBrowserImpl> GetBrowserByID(int id);
|
||||
BrowserList* GetBrowserList() { return &browserlist_; }
|
||||
|
||||
// Returns true if the calling thread is the same as the UI thread
|
||||
bool RunningOnUIThread() { return (GetCurrentThreadId() == idthreadui_); }
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// ALL UIT_* METHODS MUST ONLY BE CALLED ON THE UI THREAD //
|
||||
////////////////////////////////////////////////////////////
|
||||
|
||||
void UIT_RegisterPlugin(struct CefPluginInfo* plugin_info);
|
||||
void UIT_UnregisterPlugin(struct CefPluginInfo* plugin_info);
|
||||
void UIT_ClearCache();
|
||||
|
||||
bool DoWork();
|
||||
bool DoDelayedWork();
|
||||
bool DoIdleWork();
|
||||
|
||||
static bool ImplementsThreadSafeReferenceCounting() { return true; }
|
||||
|
||||
private:
|
||||
void SetMessageLoopForUI(MessageLoopForUI* loop);
|
||||
void NotifyEvent();
|
||||
|
||||
bool DoInitialize();
|
||||
void DoUninitialize();
|
||||
|
||||
protected:
|
||||
bool multi_threaded_message_loop_;
|
||||
|
||||
HMODULE hinstance_;
|
||||
DWORD idthreadui_;
|
||||
HANDLE hthreadui_;
|
||||
HANDLE heventui_;
|
||||
bool in_transition_;
|
||||
BrowserList browserlist_;
|
||||
WebPreferences* webprefs_;
|
||||
StatsTable* statstable_;
|
||||
std::wstring cache_path_;
|
||||
|
||||
// MessageLoopForUI will be scoped to the context when running in single
|
||||
// threaded message loop mode.
|
||||
MessageLoopForUI* messageloopui_;
|
||||
|
||||
// AtExitManager will be scoped to the context when running in single threaded
|
||||
// message loop mode.
|
||||
base::AtExitManager* at_exit_manager_;
|
||||
|
||||
// WebKit implementation class.
|
||||
BrowserWebKitInit* webkit_init_;
|
||||
|
||||
// Used for assigning unique IDs to browser instances.
|
||||
int next_browser_id_;
|
||||
|
||||
friend DWORD WINAPI ThreadHandlerUI(LPVOID lpParam);
|
||||
};
|
||||
|
||||
// Post a task to the UI message loop
|
||||
void PostTask(const tracked_objects::Location& from_here, Task* task);
|
||||
|
||||
// Global context object pointer
|
||||
extern CefRefPtr<CefContext> _Context;
|
||||
|
||||
// Macro for requiring that a function be called on the UI thread
|
||||
#define REQUIRE_UIT() DCHECK(_Context->RunningOnUIThread())
|
||||
|
||||
#endif // _CONTEXT_H
|
@ -7,7 +7,6 @@
|
||||
#include "base/logging.h"
|
||||
#include "base/message_loop.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
#include "base/worker_pool.h"
|
||||
#include "googleurl/src/url_util.h"
|
||||
#include "net/base/completion_callback.h"
|
||||
#include "net/base/io_buffer.h"
|
||||
@ -19,7 +18,7 @@
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "tracker.h"
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
#include "request_impl.h"
|
||||
|
||||
#include <map>
|
||||
@ -68,8 +67,8 @@ public:
|
||||
// Continue asynchronously.
|
||||
DCHECK(!async_resolver_);
|
||||
async_resolver_ = new AsyncResolver(this);
|
||||
WorkerPool::PostTask(FROM_HERE, NewRunnableMethod(
|
||||
async_resolver_.get(), &AsyncResolver::Resolve, url_), true);
|
||||
CefThread::PostTask(CefThread::IO, FROM_HERE, NewRunnableMethod(
|
||||
async_resolver_.get(), &AsyncResolver::Resolve, url_));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -411,7 +410,7 @@ bool CefRegisterScheme(const std::wstring& scheme_name,
|
||||
new SchemeRequestJobWrapper(WideToUTF8(scheme_name),
|
||||
WideToUTF8(host_name), factory));
|
||||
|
||||
PostTask(FROM_HERE, NewRunnableMethod(wrapper.get(),
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(wrapper.get(),
|
||||
&SchemeRequestJobWrapper::RegisterScheme));
|
||||
|
||||
return true;
|
||||
|
@ -3,7 +3,7 @@
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "v8_impl.h"
|
||||
#include "context.h"
|
||||
#include "cef_context.h"
|
||||
#include "tracker.h"
|
||||
#include "base/lazy_instance.h"
|
||||
#include "base/utf_string_conversions.h"
|
||||
@ -156,7 +156,7 @@ bool CefRegisterExtension(const std::wstring& extension_name,
|
||||
ExtensionWrapper* wrapper = new ExtensionWrapper(name->GetString(),
|
||||
code->GetString(), handler.get());
|
||||
|
||||
PostTask(FROM_HERE, NewRunnableMethod(wrapper,
|
||||
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(wrapper,
|
||||
&ExtensionWrapper::UIT_RegisterExtension));
|
||||
return true;
|
||||
}
|
||||
|
40
libcef_dll/cpptoc/task_cpptoc.cc
Normal file
40
libcef_dll/cpptoc/task_cpptoc.cc
Normal file
@ -0,0 +1,40 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// A portion of this file was generated by the CEF translator tool. When
|
||||
// making changes by hand only do so within the body of existing function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/task_cpptoc.h"
|
||||
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
void CEF_CALLBACK task_execute(struct _cef_task_t* self,
|
||||
cef_thread_id_t threadId)
|
||||
{
|
||||
DCHECK(self);
|
||||
if(!self)
|
||||
return;
|
||||
|
||||
CefTaskCppToC::Get(self)->Execute(threadId);
|
||||
}
|
||||
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefTaskCppToC::CefTaskCppToC(CefTask* cls)
|
||||
: CefCppToC<CefTaskCppToC, CefTask, cef_task_t>(cls)
|
||||
{
|
||||
struct_.struct_.execute = task_execute;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
long CefCppToC<CefTaskCppToC, CefTask, cef_task_t>::DebugObjCt = 0;
|
||||
#endif
|
||||
|
34
libcef_dll/cpptoc/task_cpptoc.h
Normal file
34
libcef_dll/cpptoc/task_cpptoc.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool and should not edited
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
#ifndef _TASK_CPPTOC_H
|
||||
#define _TASK_CPPTOC_H
|
||||
|
||||
#ifndef USING_CEF_SHARED
|
||||
#pragma message("Warning: "__FILE__" may be accessed wrapper-side only")
|
||||
#else // USING_CEF_SHARED
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "include/cef_capi.h"
|
||||
#include "libcef_dll/cpptoc/cpptoc.h"
|
||||
|
||||
// Wrap a C++ class with a C structure.
|
||||
// This class may be instantiated and accessed wrapper-side only.
|
||||
class CefTaskCppToC
|
||||
: public CefCppToC<CefTaskCppToC, CefTask, cef_task_t>
|
||||
{
|
||||
public:
|
||||
CefTaskCppToC(CefTask* cls);
|
||||
virtual ~CefTaskCppToC() {}
|
||||
};
|
||||
|
||||
#endif // USING_CEF_SHARED
|
||||
#endif // _TASK_CPPTOC_H
|
||||
|
30
libcef_dll/ctocpp/task_ctocpp.cc
Normal file
30
libcef_dll/ctocpp/task_ctocpp.cc
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// A portion of this file was generated by the CEF translator tool. When
|
||||
// making changes by hand only do so within the body of existing static and
|
||||
// virtual method implementations. See the translator.README.txt file in the
|
||||
// tools directory for more information.
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/task_ctocpp.h"
|
||||
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
void CefTaskCToCpp::Execute(CefThreadId threadId)
|
||||
{
|
||||
if(CEF_MEMBER_MISSING(struct_, execute))
|
||||
return;
|
||||
|
||||
struct_->execute(struct_, threadId);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
long CefCToCpp<CefTaskCToCpp, CefTask, cef_task_t>::DebugObjCt = 0;
|
||||
#endif
|
||||
|
39
libcef_dll/ctocpp/task_ctocpp.h
Normal file
39
libcef_dll/ctocpp/task_ctocpp.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2009 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
//
|
||||
// -------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool and should not edited
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
|
||||
#ifndef _TASK_CTOCPP_H
|
||||
#define _TASK_CTOCPP_H
|
||||
|
||||
#ifndef BUILDING_CEF_SHARED
|
||||
#pragma message("Warning: "__FILE__" may be accessed DLL-side only")
|
||||
#else // BUILDING_CEF_SHARED
|
||||
|
||||
#include "include/cef.h"
|
||||
#include "include/cef_capi.h"
|
||||
#include "libcef_dll/ctocpp/ctocpp.h"
|
||||
|
||||
// Wrap a C structure with a C++ class.
|
||||
// This class may be instantiated and accessed DLL-side only.
|
||||
class CefTaskCToCpp
|
||||
: public CefCToCpp<CefTaskCToCpp, CefTask, cef_task_t>
|
||||
{
|
||||
public:
|
||||
CefTaskCToCpp(cef_task_t* str)
|
||||
: CefCToCpp<CefTaskCToCpp, CefTask, cef_task_t>(str) {}
|
||||
virtual ~CefTaskCToCpp() {}
|
||||
|
||||
// CefTask methods
|
||||
virtual void Execute(CefThreadId threadId);
|
||||
};
|
||||
|
||||
#endif // BUILDING_CEF_SHARED
|
||||
#endif // _TASK_CTOCPP_H
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "ctocpp/read_handler_ctocpp.h"
|
||||
#include "ctocpp/scheme_handler_ctocpp.h"
|
||||
#include "ctocpp/scheme_handler_factory_ctocpp.h"
|
||||
#include "ctocpp/task_ctocpp.h"
|
||||
#include "ctocpp/v8handler_ctocpp.h"
|
||||
#include "ctocpp/write_handler_ctocpp.h"
|
||||
#include "base/string_util.h"
|
||||
@ -133,3 +134,28 @@ CEF_EXPORT int cef_register_scheme(const wchar_t* scheme_name,
|
||||
return CefRegisterScheme(nameStr, codeStr,
|
||||
CefSchemeHandlerFactoryCToCpp::Wrap(factory));
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_currently_on(cef_thread_id_t threadId)
|
||||
{
|
||||
return CefCurrentlyOn(threadId);
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_post_task(cef_thread_id_t threadId,
|
||||
struct _cef_task_t* task)
|
||||
{
|
||||
DCHECK(task);
|
||||
if(!task)
|
||||
return 0;
|
||||
|
||||
return CefPostTask(threadId, CefTaskCToCpp::Wrap(task));
|
||||
}
|
||||
|
||||
CEF_EXPORT int cef_post_delayed_task(cef_thread_id_t threadId,
|
||||
struct _cef_task_t* task, long delay_ms)
|
||||
{
|
||||
DCHECK(task);
|
||||
if(!task)
|
||||
return 0;
|
||||
|
||||
return CefPostDelayedTask(threadId, CefTaskCToCpp::Wrap(task), delay_ms);
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
#include "libcef_dll/cpptoc/read_handler_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/scheme_handler_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/task_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/v8handler_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/write_handler_cpptoc.h"
|
||||
#include "libcef_dll/ctocpp/browser_ctocpp.h"
|
||||
@ -111,3 +112,20 @@ bool CefRegisterScheme(const std::wstring& scheme_name,
|
||||
return cef_register_scheme(scheme_name.c_str(), host_name.c_str(),
|
||||
CefSchemeHandlerFactoryCppToC::Wrap(factory))?true:false;
|
||||
}
|
||||
|
||||
bool CefCurrentlyOn(CefThreadId threadId)
|
||||
{
|
||||
return cef_currently_on(threadId)?true:false;
|
||||
}
|
||||
|
||||
bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task)
|
||||
{
|
||||
return cef_post_task(threadId, CefTaskCppToC::Wrap(task))?true:false;
|
||||
}
|
||||
|
||||
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
|
||||
long delay_ms)
|
||||
{
|
||||
return cef_post_delayed_task(threadId, CefTaskCppToC::Wrap(task), delay_ms)?
|
||||
true:false;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "resource_util.h"
|
||||
#include "scheme_test.h"
|
||||
#include "string_util.h"
|
||||
#include "thread_util.h"
|
||||
#include "uiplugin_test.h"
|
||||
#include <sstream>
|
||||
#include <commdlg.h>
|
||||
@ -376,12 +375,12 @@ public:
|
||||
new ClientReadHandler(pBytes, dwSize));
|
||||
mimeType = L"text/html";
|
||||
}
|
||||
} else if(wcsstr(url.c_str(), L"/logo.gif") != NULL) {
|
||||
} else if(wcsstr(url.c_str(), L"/logo1w.png") != NULL) {
|
||||
// Any time we find "logo.gif" in the URL substitute in our own image
|
||||
if(LoadBinaryResource(IDS_LOGO, dwSize, pBytes)) {
|
||||
resourceStream = CefStreamReader::CreateForHandler(
|
||||
new ClientReadHandler(pBytes, dwSize));
|
||||
mimeType = L"image/jpg";
|
||||
mimeType = L"image/png";
|
||||
}
|
||||
} else if(wcsstr(url.c_str(), L"/logoball.png") != NULL) {
|
||||
// Load the "logoball.png" image resource.
|
||||
@ -563,7 +562,7 @@ public:
|
||||
fclose(file);
|
||||
|
||||
if(first_message) {
|
||||
// Show the message box on the UI thread.
|
||||
// Show the message box on the main application thread.
|
||||
PostMessage(m_MainHwnd, WM_COMMAND, ID_WARN_CONSOLEMESSAGE, 0);
|
||||
}
|
||||
}
|
||||
@ -945,23 +944,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
#ifdef TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
RunGetSourceTest(browser->GetMainFrame());
|
||||
#else // !TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
// Execute the GetSource() call on a new worker thread to avoid
|
||||
// blocking the UI thread when using a multi-threaded message loop
|
||||
// Execute the GetSource() call on the FILE thread to avoid blocking
|
||||
// the UI thread when using a multi-threaded message loop
|
||||
// (issue #79).
|
||||
class ExecHandler : public Thread::Handler
|
||||
class ExecTask : public CefThreadSafeBase<CefTask>
|
||||
{
|
||||
public:
|
||||
ExecHandler(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
|
||||
virtual DWORD Run()
|
||||
ExecTask(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
|
||||
virtual void Execute(CefThreadId threadId)
|
||||
{
|
||||
RunGetSourceTest(m_Frame);
|
||||
return 0;
|
||||
}
|
||||
virtual void Destroy() { delete this; }
|
||||
private:
|
||||
CefRefPtr<CefFrame> m_Frame;
|
||||
};
|
||||
Thread::Execute(new ExecHandler(browser->GetMainFrame()));
|
||||
CefPostTask(TID_FILE, new ExecTask(browser->GetMainFrame()));
|
||||
#endif // !TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
}
|
||||
return 0;
|
||||
@ -970,23 +967,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
#ifdef TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
RunGetTextTest(browser->GetMainFrame());
|
||||
#else // !TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
// Execute the GetText() call on a new worker thread to avoid
|
||||
// blocking the UI thread when using a multi-threaded message loop
|
||||
// Execute the GetText() call on the FILE thread to avoid blocking
|
||||
// the UI thread when using a multi-threaded message loop
|
||||
// (issue #79).
|
||||
class ExecHandler : public Thread::Handler
|
||||
class ExecTask : public CefThreadSafeBase<CefTask>
|
||||
{
|
||||
public:
|
||||
ExecHandler(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
|
||||
virtual DWORD Run()
|
||||
ExecTask(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
|
||||
virtual void Execute(CefThreadId threadId)
|
||||
{
|
||||
RunGetTextTest(m_Frame);
|
||||
return 0;
|
||||
}
|
||||
virtual void Destroy() { delete this; }
|
||||
private:
|
||||
CefRefPtr<CefFrame> m_Frame;
|
||||
};
|
||||
Thread::Execute(new ExecHandler(browser->GetMainFrame()));
|
||||
CefPostTask(TID_FILE, new ExecTask(browser->GetMainFrame()));
|
||||
#endif // !TEST_SINGLE_THREADED_MESSAGE_LOOP
|
||||
}
|
||||
return 0;
|
||||
|
@ -28,7 +28,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
// Binary
|
||||
//
|
||||
|
||||
IDS_LOGO BINARY "res\logo.jpg"
|
||||
IDS_LOGO BINARY "res\logo.png"
|
||||
IDS_UIPLUGIN BINARY "res\uiplugin.html"
|
||||
IDS_LOGOBALL BINARY "res\logoball.png"
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB |
BIN
tests/cefclient/res/logo.png
Normal file
BIN
tests/cefclient/res/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
@ -1,58 +0,0 @@
|
||||
// Copyright (c) 2010 The Chromium Embedded Framework Authors. All rights
|
||||
// reserved. Use of this source code is governed by a BSD-style license that
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#pragma once
|
||||
#include <windows.h>
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
// Interface for thread execution.
|
||||
class Handler
|
||||
{
|
||||
public:
|
||||
virtual DWORD Run() =0;
|
||||
virtual void Destroy() =0;
|
||||
};
|
||||
|
||||
// Create and execute a new thread for the specified handler.
|
||||
static HANDLE Execute(Handler* pHandler)
|
||||
{
|
||||
if (!pHandler)
|
||||
return 0;
|
||||
Thread* pThread = new Thread(pHandler);
|
||||
return pThread->Execute();
|
||||
}
|
||||
|
||||
private:
|
||||
Thread(Handler* pHandler) : m_hThread(NULL), m_pHandler(pHandler) {}
|
||||
~Thread()
|
||||
{
|
||||
if (m_hThread)
|
||||
CloseHandle(m_hThread);
|
||||
m_pHandler->Destroy();
|
||||
}
|
||||
|
||||
HANDLE Execute()
|
||||
{
|
||||
m_hThread = CreateThread(NULL, 4096, ThreadHandler,
|
||||
reinterpret_cast<LPVOID>(this), 0, NULL);
|
||||
if (m_hThread == NULL) {
|
||||
delete this;
|
||||
return NULL;
|
||||
}
|
||||
return m_hThread;
|
||||
}
|
||||
|
||||
static DWORD WINAPI ThreadHandler(LPVOID lpThreadParameter)
|
||||
{
|
||||
Thread* pThread = reinterpret_cast<Thread*>(lpThreadParameter);
|
||||
DWORD ret = pThread->m_pHandler->Run();
|
||||
delete pThread;
|
||||
return ret;
|
||||
}
|
||||
|
||||
Handler* m_pHandler;
|
||||
HANDLE m_hThread;
|
||||
};
|
@ -1072,6 +1072,7 @@ class obj_analysis:
|
||||
'bool' : 'int',
|
||||
'CefWindowHandle' : 'cef_window_handle_t',
|
||||
'CefRect' : 'cef_rect_t',
|
||||
'CefThreadId' : 'cef_thread_id_t',
|
||||
}
|
||||
if value in simpletypes.keys():
|
||||
return {
|
||||
|
Loading…
x
Reference in New Issue
Block a user