Introduce cef_runnable.h and cef_tuple.h and perform further thread-related cleanup (issue #175).

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@176 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2011-01-29 22:52:34 +00:00
parent 942fa69d8b
commit 83dd15925f
12 changed files with 1598 additions and 210 deletions

View File

@ -25,6 +25,11 @@
'..',
],
'sources': [
'include/cef.h',
'include/cef_nplugin.h',
'include/cef_runnable.h',
'include/cef_tuple.h',
'include/cef_wrapper.h',
'tests/cefclient/binding_test.cpp',
'tests/cefclient/binding_test.h',
'tests/cefclient/cefclient.cpp',

341
include/cef_runnable.h Normal file
View File

@ -0,0 +1,341 @@
// Copyright (c) 2011 Marshall A. Greenblatt. Portions Copyright (c)
// 2006-2011 Google Inc. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the name Chromium Embedded
// Framework nor the names of its contributors may be used to endorse
// or promote products derived from this software without specific prior
// written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The contents of this file are a modified extract of base/task.h
#ifndef _CEF_RUNNABLE_H
#define _CEF_RUNNABLE_H
#pragma once
#include "cef.h"
#ifdef BUILDING_CEF_SHARED
#include "base/tuple.h"
#else
#include "cef_tuple.h"
#endif
// CefRunnableMethodTraits -----------------------------------------------------
//
// This traits-class is used by CefRunnableMethod to manage the lifetime of the
// callee object. By default, it is assumed that the callee supports AddRef
// and Release methods. A particular class can specialize this template to
// define other lifetime management. For example, if the callee is known to
// live longer than the CefRunnableMethod object, then a CefRunnableMethodTraits
// struct could be defined with empty RetainCallee and ReleaseCallee methods.
//
// The DISABLE_RUNNABLE_METHOD_REFCOUNT macro is provided as a convenient way
// for declaring a CefRunnableMethodTraits that disables refcounting.
template <class T>
struct CefRunnableMethodTraits {
CefRunnableMethodTraits() {
}
~CefRunnableMethodTraits() {
}
void RetainCallee(T* obj) {
#ifndef NDEBUG
// Catch NewCefRunnableMethod being called in an object's constructor.
// This isn't safe since the method can be invoked before the constructor
// completes, causing the object to be deleted.
obj->AddRef();
obj->Release();
#endif
obj->AddRef();
}
void ReleaseCallee(T* obj) {
obj->Release();
}
};
// Convenience macro for declaring a CefRunnableMethodTraits that disables
// refcounting of a class. This is useful if you know that the callee
// will outlive the CefRunnableMethod object and thus do not need the ref
// counts.
//
// The invocation of DISABLE_RUNNABLE_METHOD_REFCOUNT should be done at the
// global namespace scope. Example:
//
// namespace foo {
// class Bar {
// ...
// };
// } // namespace foo
//
// DISABLE_RUNNABLE_METHOD_REFCOUNT(foo::Bar);
//
// This is different from DISALLOW_COPY_AND_ASSIGN which is declared inside the
// class.
#define DISABLE_RUNNABLE_METHOD_REFCOUNT(TypeName) \
template <> \
struct CefRunnableMethodTraits<TypeName> { \
void RetainCallee(TypeName* manager) {} \
void ReleaseCallee(TypeName* manager) {} \
}
// CefRunnableMethod and CefRunnableFunction ----------------------------------
//
// CefRunnable methods are a type of task that call a function on an object
// when they are run. We implement both an object and a set of
// NewCefRunnableMethod and NewCefRunnableFunction functions for convenience.
// These functions are overloaded and will infer the template types,
// simplifying calling code.
//
// The template definitions all use the following names:
// T - the class type of the object you're supplying
// this is not needed for the Static version of the call
// Method/Function - the signature of a pointer to the method or function you
// want to call
// Param - the parameter(s) to the method, possibly packed as a Tuple
// A - the first parameter (if any) to the method
// B - the second parameter (if any) to the method
//
// Put these all together and you get an object that can call a method whose
// signature is:
// R T::MyFunction([A[, B]])
//
// Usage:
// CefPostTask(TID_UI, NewCefRunnableMethod(object, &Object::method[, a[, b]])
// CefPostTask(TID_UI, NewCefRunnableFunction(&function[, a[, b]])
// CefRunnableMethod and NewCefRunnableMethod implementation ------------------
template <class T, class Method, class Params>
class CefRunnableMethod : public CefThreadSafeBase<CefTask> {
public:
CefRunnableMethod(T* obj, Method meth, const Params& params)
: obj_(obj), meth_(meth), params_(params) {
traits_.RetainCallee(obj_);
}
~CefRunnableMethod() {
T* obj = obj_;
obj_ = NULL;
if (obj)
traits_.ReleaseCallee(obj);
}
virtual void Execute(CefThreadId threadId) {
if (obj_)
DispatchToMethod(obj_, meth_, params_);
}
private:
T* obj_;
Method meth_;
Params params_;
CefRunnableMethodTraits<T> traits_;
};
template <class T, class Method>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method) {
return new CefRunnableMethod<T, Method, Tuple0>(object, method, MakeTuple());
}
template <class T, class Method, class A>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a) {
return new CefRunnableMethod<T, Method, Tuple1<A> >(object,
method,
MakeTuple(a));
}
template <class T, class Method, class A, class B>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b) {
return new CefRunnableMethod<T, Method, Tuple2<A, B> >(object, method,
MakeTuple(a, b));
}
template <class T, class Method, class A, class B, class C>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b,
const C& c) {
return new CefRunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
MakeTuple(a, b,
c));
}
template <class T, class Method, class A, class B, class C, class D>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b,
const C& c, const D& d) {
return new CefRunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
MakeTuple(a, b,
c,
d));
}
template <class T, class Method, class A, class B, class C, class D, class E>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b,
const C& c, const D& d,
const E& e) {
return new CefRunnableMethod<T,
Method,
Tuple5<A, B, C, D, E> >(object,
method,
MakeTuple(a, b, c, d,
e));
}
template <class T, class Method, class A, class B, class C, class D, class E,
class F>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b,
const C& c, const D& d,
const E& e, const F& f) {
return new CefRunnableMethod<T,
Method,
Tuple6<A, B, C, D, E, F> >(object,
method,
MakeTuple(a, b, c, d,
e, f));
}
template <class T, class Method, class A, class B, class C, class D, class E,
class F, class G>
inline CefRefPtr<CefTask> NewCefRunnableMethod(T* object, Method method,
const A& a, const B& b,
const C& c, const D& d,
const E& e, const F& f,
const G& g) {
return new CefRunnableMethod<T,
Method,
Tuple7<A, B, C, D, E, F, G> >(object,
method,
MakeTuple(a, b, c,
d, e, f,
g));
}
// CefRunnableFunction and NewCefRunnableFunction implementation --------------
template <class Function, class Params>
class CefRunnableFunction : public CefThreadSafeBase<CefTask> {
public:
CefRunnableFunction(Function function, const Params& params)
: function_(function), params_(params) {
}
~CefRunnableFunction() {
}
virtual void Execute(CefThreadId threadId) {
if (function_)
DispatchToFunction(function_, params_);
}
private:
Function function_;
Params params_;
};
template <class Function>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function) {
return new CefRunnableFunction<Function, Tuple0>(function, MakeTuple());
}
template <class Function, class A>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a) {
return new CefRunnableFunction<Function, Tuple1<A> >(function, MakeTuple(a));
}
template <class Function, class A, class B>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b) {
return new CefRunnableFunction<Function, Tuple2<A, B> >(function,
MakeTuple(a, b));
}
template <class Function, class A, class B, class C>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c) {
return new CefRunnableFunction<Function, Tuple3<A, B, C> >(function,
MakeTuple(a, b,
c));
}
template <class Function, class A, class B, class C, class D>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c, const D& d) {
return new CefRunnableFunction<Function, Tuple4<A, B, C, D> >(function,
MakeTuple(a, b,
c,
d));
}
template <class Function, class A, class B, class C, class D, class E>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c, const D& d,
const E& e) {
return new CefRunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
MakeTuple(a, b, c, d, e));
}
template <class Function, class A, class B, class C, class D, class E,
class F>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c, const D& d,
const E& e, const F& f) {
return new CefRunnableFunction<Function, Tuple6<A, B, C, D, E, F> >(function,
MakeTuple(a, b, c, d, e, f));
}
template <class Function, class A, class B, class C, class D, class E,
class F, class G>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c, const D& d,
const E& e, const F& f,
const G& g) {
return new CefRunnableFunction<Function, Tuple7<A, B, C, D, E, F, G> >(
function, MakeTuple(a, b, c, d, e, f, g));
}
template <class Function, class A, class B, class C, class D, class E,
class F, class G, class H>
inline CefRefPtr<CefTask> NewCefRunnableFunction(Function function,
const A& a, const B& b,
const C& c, const D& d,
const E& e, const F& f,
const G& g, const H& h) {
return new CefRunnableFunction<Function, Tuple8<A, B, C, D, E, F, G, H> >(
function, MakeTuple(a, b, c, d, e, f, g, h));
}
#endif // _CEF_RUNNABLE_H

1083
include/cef_tuple.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -278,66 +278,57 @@ void CefBrowserImpl::CloseDevTools()
void CefBrowserImpl::Undo(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_UNDO, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_UNDO, frame));
}
void CefBrowserImpl::Redo(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_REDO, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_REDO, frame));
}
void CefBrowserImpl::Cut(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_CUT, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_CUT, frame));
}
void CefBrowserImpl::Copy(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_COPY, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_COPY, frame));
}
void CefBrowserImpl::Paste(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PASTE, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PASTE, frame));
}
void CefBrowserImpl::Delete(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_DELETE, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_DELETE, frame));
}
void CefBrowserImpl::SelectAll(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_SELECTALL, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_SELECTALL, frame));
}
void CefBrowserImpl::Print(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PRINT, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_PRINT, frame));
}
void CefBrowserImpl::ViewSource(CefRefPtr<CefFrame> frame)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_HandleAction, MENU_ID_VIEWSOURCE, frame.get()));
&CefBrowserImpl::UIT_HandleAction, MENU_ID_VIEWSOURCE, frame));
}
CefString CefBrowserImpl::GetSource(CefRefPtr<CefFrame> frame)
@ -374,27 +365,23 @@ void CefBrowserImpl::LoadRequest(CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request)
{
DCHECK(request.get() != NULL);
frame->AddRef();
request->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_LoadURLForRequestRef, frame.get(), request.get()));
&CefBrowserImpl::UIT_LoadURLForRequestRef, frame, request));
}
void CefBrowserImpl::LoadURL(CefRefPtr<CefFrame> frame,
const CefString& url)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_LoadURL, frame.get(), url));
&CefBrowserImpl::UIT_LoadURL, frame, url));
}
void CefBrowserImpl::LoadString(CefRefPtr<CefFrame> frame,
const CefString& string,
const CefString& url)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_LoadHTML, frame.get(), string, url));
&CefBrowserImpl::UIT_LoadHTML, frame, string, url));
}
void CefBrowserImpl::LoadStream(CefRefPtr<CefFrame> frame,
@ -402,11 +389,8 @@ void CefBrowserImpl::LoadStream(CefRefPtr<CefFrame> frame,
const CefString& url)
{
DCHECK(stream.get() != NULL);
frame->AddRef();
stream->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_LoadHTMLForStreamRef, frame.get(), stream.get(),
url));
&CefBrowserImpl::UIT_LoadHTMLForStreamRef, frame, stream, url));
}
void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame,
@ -414,9 +398,8 @@ void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame,
const CefString& scriptUrl,
int startLine)
{
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_ExecuteJavaScript, frame.get(), jsCode, scriptUrl,
&CefBrowserImpl::UIT_ExecuteJavaScript, frame, jsCode, scriptUrl,
startLine));
}
@ -532,11 +515,23 @@ void CefBrowserImpl::UIT_DestroyBrowser()
handler_->HandleBeforeWindowClose(this);
}
UIT_GetWebViewDelegate()->RevokeDragDrop();
// If the current browser window is a dev tools client then disconnect from
// the agent and destroy the client before destroying the window.
UIT_DestroyDevToolsClient();
if (dev_tools_agent_.get()) {
BrowserDevToolsClient* client = dev_tools_agent_->client();
if (client)
client->browser()->UIT_DestroyBrowser();
if (client) {
// Destroy the client before freeing the agent.
client->browser()->UIT_DestroyDevToolsClient();
if(!_Context->shutting_down()) {
// Explicitly close the client browser window.
client->browser()->UIT_CloseBrowser();
}
}
// Free the agent.
dev_tools_agent_.reset();
}
// Clean up anything associated with the WebViewHost widget.
@ -550,20 +545,20 @@ void CefBrowserImpl::UIT_DestroyBrowser()
_Context->RemoveBrowser(this);
}
void CefBrowserImpl::UIT_LoadURL(CefFrame* frame,
void CefBrowserImpl::UIT_LoadURL(CefRefPtr<CefFrame> frame,
const CefString& url)
{
UIT_LoadURLForRequest(frame, url, CefString(), WebHTTPBody(),
CefRequest::HeaderMap());
}
void CefBrowserImpl::UIT_LoadURLForRequestRef(CefFrame* frame,
CefRequest* request)
void CefBrowserImpl::UIT_LoadURLForRequestRef(CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request)
{
CefString url = request->GetURL();
CefString method = request->GetMethod();
CefRequestImpl *impl = static_cast<CefRequestImpl*>(request);
CefRequestImpl *impl = static_cast<CefRequestImpl*>(request.get());
WebHTTPBody upload_data;
CefRefPtr<CefPostData> postdata = impl->GetPostData();
@ -576,11 +571,9 @@ void CefBrowserImpl::UIT_LoadURLForRequestRef(CefFrame* frame,
impl->GetHeaderMap(headers);
UIT_LoadURLForRequest(frame, url, method, upload_data, headers);
request->Release();
}
void CefBrowserImpl::UIT_LoadURLForRequest(CefFrame* frame,
void CefBrowserImpl::UIT_LoadURLForRequest(CefRefPtr<CefFrame> frame,
const CefString& url,
const CefString& method,
const WebKit::WebHTTPBody& upload_data,
@ -605,11 +598,9 @@ void CefBrowserImpl::UIT_LoadURLForRequest(CefFrame* frame,
nav_controller_->LoadEntry(
new BrowserNavigationEntry(-1, gurl, CefString(), frame->GetName(),
method, upload_data, headers));
frame->Release();
}
void CefBrowserImpl::UIT_LoadHTML(CefFrame* frame,
void CefBrowserImpl::UIT_LoadHTML(CefRefPtr<CefFrame> frame,
const CefString& html,
const CefString& url)
{
@ -629,12 +620,10 @@ void CefBrowserImpl::UIT_LoadHTML(CefFrame* frame,
WebFrame* web_frame = UIT_GetWebFrame(frame);
if(web_frame)
web_frame->loadHTMLString(std::string(html), gurl);
frame->Release();
}
void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefFrame* frame,
CefStreamReader* stream,
void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefRefPtr<CefFrame> frame,
CefRefPtr<CefStreamReader> stream,
const CefString& url)
{
REQUIRE_UIT();
@ -666,12 +655,9 @@ void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefFrame* frame,
WebFrame* web_frame = UIT_GetWebFrame(frame);
if(web_frame)
web_frame->loadHTMLString(ss.str(), gurl);
stream->Release();
frame->Release();
}
void CefBrowserImpl::UIT_ExecuteJavaScript(CefFrame* frame,
void CefBrowserImpl::UIT_ExecuteJavaScript(CefRefPtr<CefFrame> frame,
const CefString& js_code,
const CefString& script_url,
int start_line)
@ -683,8 +669,6 @@ void CefBrowserImpl::UIT_ExecuteJavaScript(CefFrame* frame,
web_frame->executeScript(WebScriptSource(string16(js_code),
WebURL(GURL(std::string(script_url))), start_line));
}
frame->Release();
}
void CefBrowserImpl::UIT_GoBackOrForward(int offset)
@ -826,7 +810,7 @@ void CefBrowserImpl::UIT_HandleActionView(CefHandler::MenuId menuId)
}
void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId,
CefFrame* frame)
CefRefPtr<CefFrame> frame)
{
REQUIRE_UIT();
@ -889,9 +873,6 @@ void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId,
UIT_ViewDocumentString(web_frame);
break;
}
if(frame)
frame->Release();
}
void CefBrowserImpl::UIT_Find(int identifier, const CefString& search_text,
@ -1094,6 +1075,18 @@ void CefBrowserImpl::UIT_ShowDevTools()
}
}
void CefBrowserImpl::UIT_CloseDevTools()
{
REQUIRE_UIT();
if(!dev_tools_agent_.get())
return;
BrowserDevToolsClient* client = dev_tools_agent_->client();
if (client)
client->browser()->UIT_CloseBrowser();
}
void CefBrowserImpl::set_zoom_level(double zoomLevel)
{
AutoLock lock_scope(this);
@ -1130,6 +1123,15 @@ void CefBrowserImpl::UIT_CreateDevToolsClient(BrowserDevToolsAgent *agent)
dev_tools_client_.reset(new BrowserDevToolsClient(this, agent));
}
void CefBrowserImpl::UIT_DestroyDevToolsClient()
{
if (dev_tools_client_.get()) {
// Free the client. This will cause the client to clear pending messages
// and detach from the agent.
dev_tools_client_.reset();
}
}
// CefFrameImpl

View File

@ -180,25 +180,33 @@ public:
title_ = title;
}
// Create the native browser window and populate browser members.
void UIT_CreateBrowser(const CefString& url);
// Destroy the browser members. This method should only be called after the
// native browser window is not longer processing messages.
void UIT_DestroyBrowser();
void UIT_LoadURL(CefFrame* frame,
// Sends a message via the OS to close the native browser window.
// UIT_DestroyBrowser will be called after the native window has closed.
void UIT_CloseBrowser();
void UIT_LoadURL(CefRefPtr<CefFrame> frame,
const CefString& url);
void UIT_LoadURLForRequest(CefFrame* frame,
void UIT_LoadURLForRequest(CefRefPtr<CefFrame> frame,
const CefString& url,
const CefString& method,
const WebKit::WebHTTPBody& upload_data,
const CefRequest::HeaderMap& headers);
void UIT_LoadURLForRequestRef(CefFrame* frame,
CefRequest* request);
void UIT_LoadHTML(CefFrame* frame,
void UIT_LoadURLForRequestRef(CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request);
void UIT_LoadHTML(CefRefPtr<CefFrame> frame,
const CefString& html,
const CefString& url);
void UIT_LoadHTMLForStreamRef(CefFrame* frame,
CefStreamReader* stream,
void UIT_LoadHTMLForStreamRef(CefRefPtr<CefFrame> frame,
CefRefPtr<CefStreamReader> stream,
const CefString& url);
void UIT_ExecuteJavaScript(CefFrame* frame,
void UIT_ExecuteJavaScript(CefRefPtr<CefFrame> frame,
const CefString& js_code,
const CefString& script_url,
int start_line);
@ -218,7 +226,7 @@ public:
// Handles most simple browser actions
void UIT_HandleActionView(CefHandler::MenuId menuId);
void UIT_HandleAction(CefHandler::MenuId menuId, CefFrame* frame);
void UIT_HandleAction(CefHandler::MenuId menuId, CefRefPtr<CefFrame> frame);
// Save the document HTML to a temporary file and open in the default viewing
// application
@ -262,6 +270,7 @@ public:
protected:
void UIT_CreateDevToolsClient(BrowserDevToolsAgent* agent);
void UIT_DestroyDevToolsClient();
protected:
CefWindowInfo window_info_;

View File

@ -66,11 +66,17 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
handler_->HandleAfterCreated(this);
}
if(url.size() > 0) {
CefRefPtr<CefFrame> frame = GetMainFrame();
frame->AddRef();
UIT_LoadURL(frame, url);
}
if(url.size() > 0)
UIT_LoadURL(GetMainFrame(), url);
}
void CefBrowserImpl::UIT_CloseBrowser()
{
REQUIRE_UIT();
DCHECK(!_Context->shutting_down());
// TODO(port): Close the browser window.
NOTREACHED();
}
void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -136,14 +142,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
NOTIMPLEMENTED();
return 0;
}
void CefBrowserImpl::UIT_CloseDevTools()
{
REQUIRE_UIT();
if(!dev_tools_agent_.get())
return;
// TODO(port): Add implementation.
NOTIMPLEMENTED();
}

View File

@ -71,11 +71,17 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
handler_->HandleAfterCreated(this);
}
if(url.size() > 0) {
CefRefPtr<CefFrame> frame = GetMainFrame();
frame->AddRef();
UIT_LoadURL(frame, url);
}
if(url.size() > 0)
UIT_LoadURL(GetMainFrame(), url);
}
void CefBrowserImpl::UIT_CloseBrowser()
{
REQUIRE_UIT();
DCHECK(!_Context->shutting_down());
// TODO(port): Close the browser window.
NOTREACHED();
}
void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -145,14 +151,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
NOTIMPLEMENTED();
return 0;
}
void CefBrowserImpl::UIT_CloseDevTools()
{
REQUIRE_UIT();
if(!dev_tools_agent_.get())
return;
// TODO(port): Add implementation.
NOTIMPLEMENTED();
}

View File

@ -149,11 +149,16 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
handler_->HandleAfterCreated(this);
}
if(url.length() > 0) {
CefRefPtr<CefFrame> frame = GetMainFrame();
frame->AddRef();
UIT_LoadURL(frame, url);
}
if(url.length() > 0)
UIT_LoadURL(GetMainFrame(), url);
}
void CefBrowserImpl::UIT_CloseBrowser()
{
REQUIRE_UIT();
DCHECK(!_Context->shutting_down());
PostMessage(UIT_GetMainWndHandle(), WM_CLOSE, 0, 0);
}
void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -489,15 +494,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
return page_count;
}
void CefBrowserImpl::UIT_CloseDevTools()
{
REQUIRE_UIT();
if(!dev_tools_agent_.get())
return;
BrowserDevToolsClient* client = dev_tools_agent_->client();
if (client)
PostMessage(client->browser()->UIT_GetMainWndHandle(), WM_CLOSE, 0, 0);
}

View File

@ -371,9 +371,7 @@ void BrowserWebViewDelegate::showContextMenu(
if(!handled) {
// Execute the action
CefRefPtr<CefFrame> frame = browser_->GetFocusedFrame();
frame->AddRef();
browser_->UIT_HandleAction(menuId, frame.get());
browser_->UIT_HandleAction(menuId, browser_->GetFocusedFrame());
}
}
}

View File

@ -154,13 +154,15 @@ bool CefCurrentlyOn(CefThreadId threadId)
return CefThread::CurrentlyOn(static_cast<CefThread::ID>(id));
}
class CefTaskHelper : public base::RefCountedThreadSafe<CefTaskHelper>
class CefTaskHelper : public Task
{
public:
CefTaskHelper(CefRefPtr<CefTask> task) : task_(task) {}
void Execute(CefThreadId threadId) { task_->Execute(threadId); }
CefTaskHelper(CefRefPtr<CefTask> task, CefThreadId threadId)
: task_(task), thread_id_(threadId) {}
virtual void Run() { task_->Execute(thread_id_); }
private:
CefRefPtr<CefTask> task_;
CefThreadId thread_id_;
DISALLOW_COPY_AND_ASSIGN(CefTaskHelper);
};
@ -170,9 +172,8 @@ bool CefPostTask(CefThreadId threadId, CefRefPtr<CefTask> task)
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));
new CefTaskHelper(task, threadId));
}
bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
@ -182,10 +183,8 @@ bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr<CefTask> task,
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);
new CefTaskHelper(task, threadId), delay_ms);
}

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file.
#include "include/cef.h"
#include "include/cef_runnable.h"
#include "include/cef_wrapper.h"
#include "cefclient.h"
#include "binding_test.h"
@ -289,52 +290,41 @@ CefWindowHandle AppGetMainHwnd()
return g_handler->GetMainHwnd();
}
static void ExecuteGetSource(CefRefPtr<CefFrame> frame)
{
// Retrieve the current page source and display.
std::string source = frame->GetSource();
source = StringReplace(source, "<", "&lt;");
source = StringReplace(source, ">", "&gt;");
std::stringstream ss;
ss << "<html><body>Source:" << "<pre>" << source
<< "</pre></body></html>";
frame->LoadString(ss.str(), "http://tests/getsource");
}
void RunGetSourceTest(CefRefPtr<CefBrowser> browser)
{
// Execute the GetSource() call on the UI thread.
class ExecTask : public CefThreadSafeBase<CefTask>
{
public:
ExecTask(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
virtual void Execute(CefThreadId threadId)
{
// Retrieve the current page source and display.
std::string source = m_Frame->GetSource();
source = StringReplace(source, "<", "&lt;");
source = StringReplace(source, ">", "&gt;");
std::stringstream ss;
ss << "<html><body>Source:" << "<pre>" << source
<< "</pre></body></html>";
m_Frame->LoadString(ss.str(), "http://tests/getsource");
}
private:
CefRefPtr<CefFrame> m_Frame;
};
CefPostTask(TID_UI, new ExecTask(browser->GetMainFrame()));
CefPostTask(TID_UI,
NewCefRunnableFunction(&ExecuteGetSource, browser->GetMainFrame()));
}
static void ExecuteGetText(CefRefPtr<CefFrame> frame)
{
std::string text = frame->GetText();
text = StringReplace(text, "<", "&lt;");
text = StringReplace(text, ">", "&gt;");
std::stringstream ss;
ss << "<html><body>Text:" << "<pre>" << text
<< "</pre></body></html>";
frame->LoadString(ss.str(), "http://tests/gettext");
}
void RunGetTextTest(CefRefPtr<CefBrowser> browser)
{
// Execute the GetText() call on the UI thread.
class ExecTask : public CefThreadSafeBase<CefTask>
{
public:
ExecTask(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
virtual void Execute(CefThreadId threadId)
{
// Retrieve the current page text and display.
std::string text = m_Frame->GetText();
text = StringReplace(text, "<", "&lt;");
text = StringReplace(text, ">", "&gt;");
std::stringstream ss;
ss << "<html><body>Text:" << "<pre>" << text
<< "</pre></body></html>";
m_Frame->LoadString(ss.str(), "http://tests/gettext");
}
private:
CefRefPtr<CefFrame> m_Frame;
};
CefPostTask(TID_UI, new ExecTask(browser->GetMainFrame()));
CefPostTask(TID_UI,
NewCefRunnableFunction(&ExecuteGetText, browser->GetMainFrame()));
}
void RunRequestTest(CefRefPtr<CefBrowser> browser)

View File

@ -2,6 +2,7 @@
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "include/cef_runnable.h"
#include "download_handler.h"
#include "util.h"
#include <sstream>
@ -14,38 +15,6 @@
#include <shlwapi.h>
#endif // _WIN32
namespace {
// Template for creating a task that executes a method with no arguments.
template <class T, class Method>
class Task : public CefThreadSafeBase<CefTask>
{
public:
Task(T* object, Method method)
: object_(object), method_(method) {}
virtual void Execute(CefThreadId threadId)
{
(object_->*method_)();
}
protected:
CefRefPtr<T> object_;
Method method_;
};
// Helper method for posting a task on a specific thread.
template <class T, class Method>
inline void PostOnThread(CefThreadId threadId,
T* object,
Method method) {
CefRefPtr<CefTask> task = new Task<T,Method>(object, method);
CefPostTask(threadId, task);
}
} // namespace
// Implementation of the CefDownloadHandler interface.
class ClientDownloadHandler : public CefThreadSafeBase<CefDownloadHandler>
{
@ -54,8 +23,6 @@ public:
const CefString& fileName)
: listener_(listener), filename_(fileName), file_(NULL)
{
// Open the file on the FILE thread.
PostOnThread(TID_FILE, this, &ClientDownloadHandler::OnOpen);
}
~ClientDownloadHandler()
@ -72,15 +39,9 @@ public:
if(file_) {
// Close the dangling file pointer on the FILE thread.
class TaskCloseFile : public CefThreadSafeBase<CefTask>
{
public:
TaskCloseFile(FILE* file) : file_(file) {}
virtual void Execute(CefThreadId threadId) { fclose(file_); }
private:
FILE* file_;
};
CefPostTask(TID_FILE, new TaskCloseFile(file_));
CefPostTask(TID_FILE,
NewCefRunnableFunction(&ClientDownloadHandler::CloseDanglingFile,
file_));
// Notify the listener that the download failed.
listener_->NotifyDownloadError(filename_);
@ -91,6 +52,13 @@ public:
// The following methods are called on the UI thread.
// --------------------------------------------------
void Initialize()
{
// Open the file on the FILE thread.
CefPostTask(TID_FILE,
NewCefRunnableMethod(this, &ClientDownloadHandler::OnOpen));
}
// A portion of the file contents have been received. This method will be
// called multiple times until the download is complete. Return |true| to
// continue receiving data and |false| to cancel.
@ -111,7 +79,8 @@ public:
Unlock();
// Write data to file on the FILE thread.
PostOnThread(TID_FILE, this, &ClientDownloadHandler::OnReceivedData);
CefPostTask(TID_FILE,
NewCefRunnableMethod(this, &ClientDownloadHandler::OnReceivedData));
return true;
}
@ -121,7 +90,8 @@ public:
REQUIRE_UI_THREAD();
// Flush and close the file on the FILE thread.
PostOnThread(TID_FILE, this, &ClientDownloadHandler::OnComplete);
CefPostTask(TID_FILE,
NewCefRunnableMethod(this, &ClientDownloadHandler::OnComplete));
}
// ----------------------------------------------------
@ -222,6 +192,11 @@ public:
data.clear();
}
static void CloseDanglingFile(FILE *file)
{
fclose(file);
}
private:
CefRefPtr<DownloadListener> listener_;
CefString filename_;
@ -232,5 +207,8 @@ private:
CefRefPtr<CefDownloadHandler> CreateDownloadHandler(
CefRefPtr<DownloadListener> listener, const CefString& fileName)
{
return new ClientDownloadHandler(listener, fileName);
CefRefPtr<ClientDownloadHandler> handler =
new ClientDownloadHandler(listener, fileName);
handler->Initialize();
return handler.get();
}