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': [ '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.cpp',
'tests/cefclient/binding_test.h', 'tests/cefclient/binding_test.h',
'tests/cefclient/cefclient.cpp', '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) void CefBrowserImpl::Undo(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Redo(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Cut(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Copy(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Paste(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Delete(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::SelectAll(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::Print(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) void CefBrowserImpl::ViewSource(CefRefPtr<CefFrame> frame)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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) CefString CefBrowserImpl::GetSource(CefRefPtr<CefFrame> frame)
@ -374,27 +365,23 @@ void CefBrowserImpl::LoadRequest(CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) CefRefPtr<CefRequest> request)
{ {
DCHECK(request.get() != NULL); DCHECK(request.get() != NULL);
frame->AddRef();
request->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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, void CefBrowserImpl::LoadURL(CefRefPtr<CefFrame> frame,
const CefString& url) const CefString& url)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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, void CefBrowserImpl::LoadString(CefRefPtr<CefFrame> frame,
const CefString& string, const CefString& string,
const CefString& url) const CefString& url)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, 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, void CefBrowserImpl::LoadStream(CefRefPtr<CefFrame> frame,
@ -402,11 +389,8 @@ void CefBrowserImpl::LoadStream(CefRefPtr<CefFrame> frame,
const CefString& url) const CefString& url)
{ {
DCHECK(stream.get() != NULL); DCHECK(stream.get() != NULL);
frame->AddRef();
stream->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_LoadHTMLForStreamRef, frame.get(), stream.get(), &CefBrowserImpl::UIT_LoadHTMLForStreamRef, frame, stream, url));
url));
} }
void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame, void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame,
@ -414,9 +398,8 @@ void CefBrowserImpl::ExecuteJavaScript(CefRefPtr<CefFrame> frame,
const CefString& scriptUrl, const CefString& scriptUrl,
int startLine) int startLine)
{ {
frame->AddRef();
CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this, CefThread::PostTask(CefThread::UI, FROM_HERE, NewRunnableMethod(this,
&CefBrowserImpl::UIT_ExecuteJavaScript, frame.get(), jsCode, scriptUrl, &CefBrowserImpl::UIT_ExecuteJavaScript, frame, jsCode, scriptUrl,
startLine)); startLine));
} }
@ -533,10 +516,22 @@ void CefBrowserImpl::UIT_DestroyBrowser()
} }
UIT_GetWebViewDelegate()->RevokeDragDrop(); 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()) { if (dev_tools_agent_.get()) {
BrowserDevToolsClient* client = dev_tools_agent_->client(); BrowserDevToolsClient* client = dev_tools_agent_->client();
if (client) if (client) {
client->browser()->UIT_DestroyBrowser(); // 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. // Clean up anything associated with the WebViewHost widget.
@ -550,20 +545,20 @@ void CefBrowserImpl::UIT_DestroyBrowser()
_Context->RemoveBrowser(this); _Context->RemoveBrowser(this);
} }
void CefBrowserImpl::UIT_LoadURL(CefFrame* frame, void CefBrowserImpl::UIT_LoadURL(CefRefPtr<CefFrame> frame,
const CefString& url) const CefString& url)
{ {
UIT_LoadURLForRequest(frame, url, CefString(), WebHTTPBody(), UIT_LoadURLForRequest(frame, url, CefString(), WebHTTPBody(),
CefRequest::HeaderMap()); CefRequest::HeaderMap());
} }
void CefBrowserImpl::UIT_LoadURLForRequestRef(CefFrame* frame, void CefBrowserImpl::UIT_LoadURLForRequestRef(CefRefPtr<CefFrame> frame,
CefRequest* request) CefRefPtr<CefRequest> request)
{ {
CefString url = request->GetURL(); CefString url = request->GetURL();
CefString method = request->GetMethod(); CefString method = request->GetMethod();
CefRequestImpl *impl = static_cast<CefRequestImpl*>(request); CefRequestImpl *impl = static_cast<CefRequestImpl*>(request.get());
WebHTTPBody upload_data; WebHTTPBody upload_data;
CefRefPtr<CefPostData> postdata = impl->GetPostData(); CefRefPtr<CefPostData> postdata = impl->GetPostData();
@ -576,11 +571,9 @@ void CefBrowserImpl::UIT_LoadURLForRequestRef(CefFrame* frame,
impl->GetHeaderMap(headers); impl->GetHeaderMap(headers);
UIT_LoadURLForRequest(frame, url, method, upload_data, 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& url,
const CefString& method, const CefString& method,
const WebKit::WebHTTPBody& upload_data, const WebKit::WebHTTPBody& upload_data,
@ -605,11 +598,9 @@ void CefBrowserImpl::UIT_LoadURLForRequest(CefFrame* frame,
nav_controller_->LoadEntry( nav_controller_->LoadEntry(
new BrowserNavigationEntry(-1, gurl, CefString(), frame->GetName(), new BrowserNavigationEntry(-1, gurl, CefString(), frame->GetName(),
method, upload_data, headers)); method, upload_data, headers));
frame->Release();
} }
void CefBrowserImpl::UIT_LoadHTML(CefFrame* frame, void CefBrowserImpl::UIT_LoadHTML(CefRefPtr<CefFrame> frame,
const CefString& html, const CefString& html,
const CefString& url) const CefString& url)
{ {
@ -629,12 +620,10 @@ void CefBrowserImpl::UIT_LoadHTML(CefFrame* frame,
WebFrame* web_frame = UIT_GetWebFrame(frame); WebFrame* web_frame = UIT_GetWebFrame(frame);
if(web_frame) if(web_frame)
web_frame->loadHTMLString(std::string(html), gurl); web_frame->loadHTMLString(std::string(html), gurl);
frame->Release();
} }
void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefFrame* frame, void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefRefPtr<CefFrame> frame,
CefStreamReader* stream, CefRefPtr<CefStreamReader> stream,
const CefString& url) const CefString& url)
{ {
REQUIRE_UIT(); REQUIRE_UIT();
@ -666,12 +655,9 @@ void CefBrowserImpl::UIT_LoadHTMLForStreamRef(CefFrame* frame,
WebFrame* web_frame = UIT_GetWebFrame(frame); WebFrame* web_frame = UIT_GetWebFrame(frame);
if(web_frame) if(web_frame)
web_frame->loadHTMLString(ss.str(), gurl); 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& js_code,
const CefString& script_url, const CefString& script_url,
int start_line) int start_line)
@ -683,8 +669,6 @@ void CefBrowserImpl::UIT_ExecuteJavaScript(CefFrame* frame,
web_frame->executeScript(WebScriptSource(string16(js_code), web_frame->executeScript(WebScriptSource(string16(js_code),
WebURL(GURL(std::string(script_url))), start_line)); WebURL(GURL(std::string(script_url))), start_line));
} }
frame->Release();
} }
void CefBrowserImpl::UIT_GoBackOrForward(int offset) void CefBrowserImpl::UIT_GoBackOrForward(int offset)
@ -826,7 +810,7 @@ void CefBrowserImpl::UIT_HandleActionView(CefHandler::MenuId menuId)
} }
void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId, void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId,
CefFrame* frame) CefRefPtr<CefFrame> frame)
{ {
REQUIRE_UIT(); REQUIRE_UIT();
@ -889,9 +873,6 @@ void CefBrowserImpl::UIT_HandleAction(CefHandler::MenuId menuId,
UIT_ViewDocumentString(web_frame); UIT_ViewDocumentString(web_frame);
break; break;
} }
if(frame)
frame->Release();
} }
void CefBrowserImpl::UIT_Find(int identifier, const CefString& search_text, 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) void CefBrowserImpl::set_zoom_level(double zoomLevel)
{ {
AutoLock lock_scope(this); AutoLock lock_scope(this);
@ -1130,6 +1123,15 @@ void CefBrowserImpl::UIT_CreateDevToolsClient(BrowserDevToolsAgent *agent)
dev_tools_client_.reset(new BrowserDevToolsClient(this, 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 // CefFrameImpl

View File

@ -180,25 +180,33 @@ public:
title_ = title; title_ = title;
} }
// Create the native browser window and populate browser members.
void UIT_CreateBrowser(const CefString& url); 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_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); const CefString& url);
void UIT_LoadURLForRequest(CefFrame* frame, void UIT_LoadURLForRequest(CefRefPtr<CefFrame> frame,
const CefString& url, const CefString& url,
const CefString& method, const CefString& method,
const WebKit::WebHTTPBody& upload_data, const WebKit::WebHTTPBody& upload_data,
const CefRequest::HeaderMap& headers); const CefRequest::HeaderMap& headers);
void UIT_LoadURLForRequestRef(CefFrame* frame, void UIT_LoadURLForRequestRef(CefRefPtr<CefFrame> frame,
CefRequest* request); CefRefPtr<CefRequest> request);
void UIT_LoadHTML(CefFrame* frame, void UIT_LoadHTML(CefRefPtr<CefFrame> frame,
const CefString& html, const CefString& html,
const CefString& url); const CefString& url);
void UIT_LoadHTMLForStreamRef(CefFrame* frame, void UIT_LoadHTMLForStreamRef(CefRefPtr<CefFrame> frame,
CefStreamReader* stream, CefRefPtr<CefStreamReader> stream,
const CefString& url); const CefString& url);
void UIT_ExecuteJavaScript(CefFrame* frame, void UIT_ExecuteJavaScript(CefRefPtr<CefFrame> frame,
const CefString& js_code, const CefString& js_code,
const CefString& script_url, const CefString& script_url,
int start_line); int start_line);
@ -218,7 +226,7 @@ public:
// Handles most simple browser actions // Handles most simple browser actions
void UIT_HandleActionView(CefHandler::MenuId menuId); 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 // Save the document HTML to a temporary file and open in the default viewing
// application // application
@ -262,6 +270,7 @@ public:
protected: protected:
void UIT_CreateDevToolsClient(BrowserDevToolsAgent* agent); void UIT_CreateDevToolsClient(BrowserDevToolsAgent* agent);
void UIT_DestroyDevToolsClient();
protected: protected:
CefWindowInfo window_info_; CefWindowInfo window_info_;

View File

@ -66,11 +66,17 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
handler_->HandleAfterCreated(this); handler_->HandleAfterCreated(this);
} }
if(url.size() > 0) { if(url.size() > 0)
CefRefPtr<CefFrame> frame = GetMainFrame(); UIT_LoadURL(GetMainFrame(), url);
frame->AddRef(); }
UIT_LoadURL(frame, 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) void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -136,14 +142,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return 0; 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); handler_->HandleAfterCreated(this);
} }
if(url.size() > 0) { if(url.size() > 0)
CefRefPtr<CefFrame> frame = GetMainFrame(); UIT_LoadURL(GetMainFrame(), url);
frame->AddRef(); }
UIT_LoadURL(frame, 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) void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -145,14 +151,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
NOTIMPLEMENTED(); NOTIMPLEMENTED();
return 0; 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); handler_->HandleAfterCreated(this);
} }
if(url.length() > 0) { if(url.length() > 0)
CefRefPtr<CefFrame> frame = GetMainFrame(); UIT_LoadURL(GetMainFrame(), url);
frame->AddRef(); }
UIT_LoadURL(frame, 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) void CefBrowserImpl::UIT_SetFocus(WebWidgetHost* host, bool enable)
@ -489,15 +494,3 @@ int CefBrowserImpl::UIT_GetPagesCount(WebKit::WebFrame* frame)
return page_count; 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) { if(!handled) {
// Execute the action // Execute the action
CefRefPtr<CefFrame> frame = browser_->GetFocusedFrame(); browser_->UIT_HandleAction(menuId, browser_->GetFocusedFrame());
frame->AddRef();
browser_->UIT_HandleAction(menuId, frame.get());
} }
} }
} }

View File

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

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include "include/cef.h" #include "include/cef.h"
#include "include/cef_runnable.h"
#include "include/cef_wrapper.h" #include "include/cef_wrapper.h"
#include "cefclient.h" #include "cefclient.h"
#include "binding_test.h" #include "binding_test.h"
@ -289,52 +290,41 @@ CefWindowHandle AppGetMainHwnd()
return g_handler->GetMainHwnd(); 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) void RunGetSourceTest(CefRefPtr<CefBrowser> browser)
{ {
// Execute the GetSource() call on the UI thread. // Execute the GetSource() call on the UI thread.
class ExecTask : public CefThreadSafeBase<CefTask> CefPostTask(TID_UI,
{ NewCefRunnableFunction(&ExecuteGetSource, browser->GetMainFrame()));
public: }
ExecTask(CefRefPtr<CefFrame> frame) : m_Frame(frame) {}
virtual void Execute(CefThreadId threadId) static void ExecuteGetText(CefRefPtr<CefFrame> frame)
{ {
// Retrieve the current page source and display. std::string text = frame->GetText();
std::string source = m_Frame->GetSource(); text = StringReplace(text, "<", "&lt;");
source = StringReplace(source, "<", "&lt;"); text = StringReplace(text, ">", "&gt;");
source = StringReplace(source, ">", "&gt;"); std::stringstream ss;
std::stringstream ss; ss << "<html><body>Text:" << "<pre>" << text
ss << "<html><body>Source:" << "<pre>" << source << "</pre></body></html>";
<< "</pre></body></html>"; frame->LoadString(ss.str(), "http://tests/gettext");
m_Frame->LoadString(ss.str(), "http://tests/getsource");
}
private:
CefRefPtr<CefFrame> m_Frame;
};
CefPostTask(TID_UI, new ExecTask(browser->GetMainFrame()));
} }
void RunGetTextTest(CefRefPtr<CefBrowser> browser) void RunGetTextTest(CefRefPtr<CefBrowser> browser)
{ {
// Execute the GetText() call on the UI thread. // Execute the GetText() call on the UI thread.
class ExecTask : public CefThreadSafeBase<CefTask> CefPostTask(TID_UI,
{ NewCefRunnableFunction(&ExecuteGetText, browser->GetMainFrame()));
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()));
} }
void RunRequestTest(CefRefPtr<CefBrowser> browser) 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 // reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file. // can be found in the LICENSE file.
#include "include/cef_runnable.h"
#include "download_handler.h" #include "download_handler.h"
#include "util.h" #include "util.h"
#include <sstream> #include <sstream>
@ -14,38 +15,6 @@
#include <shlwapi.h> #include <shlwapi.h>
#endif // _WIN32 #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. // Implementation of the CefDownloadHandler interface.
class ClientDownloadHandler : public CefThreadSafeBase<CefDownloadHandler> class ClientDownloadHandler : public CefThreadSafeBase<CefDownloadHandler>
{ {
@ -54,8 +23,6 @@ public:
const CefString& fileName) const CefString& fileName)
: listener_(listener), filename_(fileName), file_(NULL) : listener_(listener), filename_(fileName), file_(NULL)
{ {
// Open the file on the FILE thread.
PostOnThread(TID_FILE, this, &ClientDownloadHandler::OnOpen);
} }
~ClientDownloadHandler() ~ClientDownloadHandler()
@ -72,15 +39,9 @@ public:
if(file_) { if(file_) {
// Close the dangling file pointer on the FILE thread. // Close the dangling file pointer on the FILE thread.
class TaskCloseFile : public CefThreadSafeBase<CefTask> CefPostTask(TID_FILE,
{ NewCefRunnableFunction(&ClientDownloadHandler::CloseDanglingFile,
public: file_));
TaskCloseFile(FILE* file) : file_(file) {}
virtual void Execute(CefThreadId threadId) { fclose(file_); }
private:
FILE* file_;
};
CefPostTask(TID_FILE, new TaskCloseFile(file_));
// Notify the listener that the download failed. // Notify the listener that the download failed.
listener_->NotifyDownloadError(filename_); listener_->NotifyDownloadError(filename_);
@ -91,6 +52,13 @@ public:
// The following methods are called on the UI thread. // 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 // A portion of the file contents have been received. This method will be
// called multiple times until the download is complete. Return |true| to // called multiple times until the download is complete. Return |true| to
// continue receiving data and |false| to cancel. // continue receiving data and |false| to cancel.
@ -111,7 +79,8 @@ public:
Unlock(); Unlock();
// Write data to file on the FILE thread. // Write data to file on the FILE thread.
PostOnThread(TID_FILE, this, &ClientDownloadHandler::OnReceivedData); CefPostTask(TID_FILE,
NewCefRunnableMethod(this, &ClientDownloadHandler::OnReceivedData));
return true; return true;
} }
@ -121,7 +90,8 @@ public:
REQUIRE_UI_THREAD(); REQUIRE_UI_THREAD();
// Flush and close the file on the FILE 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(); data.clear();
} }
static void CloseDanglingFile(FILE *file)
{
fclose(file);
}
private: private:
CefRefPtr<DownloadListener> listener_; CefRefPtr<DownloadListener> listener_;
CefString filename_; CefString filename_;
@ -232,5 +207,8 @@ private:
CefRefPtr<CefDownloadHandler> CreateDownloadHandler( CefRefPtr<CefDownloadHandler> CreateDownloadHandler(
CefRefPtr<DownloadListener> listener, const CefString& fileName) CefRefPtr<DownloadListener> listener, const CefString& fileName)
{ {
return new ClientDownloadHandler(listener, fileName); CefRefPtr<ClientDownloadHandler> handler =
new ClientDownloadHandler(listener, fileName);
handler->Initialize();
return handler.get();
} }