From 83dd15925f41368d6acc713b9fb5cb86ee29ff74 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Sat, 29 Jan 2011 22:52:34 +0000 Subject: [PATCH] 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 --- cef.gyp | 5 + include/cef_runnable.h | 341 ++++++++ include/cef_tuple.h | 1083 ++++++++++++++++++++++++ libcef/browser_impl.cc | 116 +-- libcef/browser_impl.h | 27 +- libcef/browser_impl_gtk.cc | 27 +- libcef/browser_impl_mac.mm | 27 +- libcef/browser_impl_win.cc | 27 +- libcef/browser_webview_delegate_win.cc | 4 +- libcef/cef_context.cc | 15 +- tests/cefclient/cefclient.cpp | 66 +- tests/cefclient/download_handler.cpp | 70 +- 12 files changed, 1598 insertions(+), 210 deletions(-) create mode 100644 include/cef_runnable.h create mode 100644 include/cef_tuple.h diff --git a/cef.gyp b/cef.gyp index 2d3825e48..0aa053869 100644 --- a/cef.gyp +++ b/cef.gyp @@ -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', diff --git a/include/cef_runnable.h b/include/cef_runnable.h new file mode 100644 index 000000000..3941cd606 --- /dev/null +++ b/include/cef_runnable.h @@ -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 +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 { \ + 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 CefRunnableMethod : public CefThreadSafeBase { + 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 traits_; +}; + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method) { + return new CefRunnableMethod(object, method, MakeTuple()); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b, + c)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d) { + return new CefRunnableMethod >(object, method, + MakeTuple(a, b, + c, + d)); +} + +template +inline CefRefPtr NewCefRunnableMethod(T* object, Method method, + const A& a, const B& b, + const C& c, const D& d, + const E& e) { + return new CefRunnableMethod >(object, + method, + MakeTuple(a, b, c, d, + e)); +} + +template +inline CefRefPtr 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 >(object, + method, + MakeTuple(a, b, c, d, + e, f)); +} + +template +inline CefRefPtr 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 >(object, + method, + MakeTuple(a, b, c, + d, e, f, + g)); +} + +// CefRunnableFunction and NewCefRunnableFunction implementation -------------- + +template +class CefRunnableFunction : public CefThreadSafeBase { + 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 +inline CefRefPtr NewCefRunnableFunction(Function function) { + return new CefRunnableFunction(function, MakeTuple()); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a) { + return new CefRunnableFunction >(function, MakeTuple(a)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b) { + return new CefRunnableFunction >(function, + MakeTuple(a, b)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, + c)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, + c, + d)); +} + +template +inline CefRefPtr NewCefRunnableFunction(Function function, + const A& a, const B& b, + const C& c, const D& d, + const E& e) { + return new CefRunnableFunction >(function, + MakeTuple(a, b, c, d, e)); +} + +template +inline CefRefPtr 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, + MakeTuple(a, b, c, d, e, f)); +} + +template +inline CefRefPtr 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, MakeTuple(a, b, c, d, e, f, g)); +} + +template +inline CefRefPtr 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, MakeTuple(a, b, c, d, e, f, g, h)); +} + +#endif // _CEF_RUNNABLE_H diff --git a/include/cef_tuple.h b/include/cef_tuple.h new file mode 100644 index 000000000..da71441de --- /dev/null +++ b/include/cef_tuple.h @@ -0,0 +1,1083 @@ +// 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 identical to base/tuple.h + +// A Tuple is a generic templatized container, similar in concept to std::pair. +// There are classes Tuple0 to Tuple6, cooresponding to the number of elements +// it contains. The convenient MakeTuple() function takes 0 to 6 arguments, +// and will construct and return the appropriate Tuple object. The functions +// DispatchToMethod and DispatchToFunction take a function pointer or instance +// and method pointer, and unpack a tuple into arguments to the call. +// +// Tuple elements are copied by value, and stored in the tuple. See the unit +// tests for more details of how/when the values are copied. +// +// Example usage: +// // These two methods of creating a Tuple are identical. +// Tuple2 tuple_a(1, "wee"); +// Tuple2 tuple_b = MakeTuple(1, "wee"); +// +// void SomeFunc(int a, const char* b) { } +// DispatchToFunction(&SomeFunc, tuple_a); // SomeFunc(1, "wee") +// DispatchToFunction( +// &SomeFunc, MakeTuple(10, "foo")); // SomeFunc(10, "foo") +// +// struct { void SomeMeth(int a, int b, int c) { } } foo; +// DispatchToMethod(&foo, &Foo::SomeMeth, MakeTuple(1, 2, 3)); +// // foo->SomeMeth(1, 2, 3); + +#ifndef BASE_TUPLE_H__ +#define BASE_TUPLE_H__ +#pragma once + +#if defined(OS_CHROMEOS) +// To troubleshoot crosbug.com/7327. +#include "base/logging.h" +#endif +// Traits ---------------------------------------------------------------------- +// +// A simple traits class for tuple arguments. +// +// ValueType: the bare, nonref version of a type (same as the type for nonrefs). +// RefType: the ref version of a type (same as the type for refs). +// ParamType: what type to pass to functions (refs should not be constified). + +template +struct TupleTraits { + typedef P ValueType; + typedef P& RefType; + typedef const P& ParamType; +}; + +template +struct TupleTraits { + typedef P ValueType; + typedef P& RefType; + typedef P& ParamType; +}; + +template +struct TupleTypes { }; + +// Tuple ----------------------------------------------------------------------- +// +// This set of classes is useful for bundling 0 or more heterogeneous data types +// into a single variable. The advantage of this is that it greatly simplifies +// function objects that need to take an arbitrary number of parameters; see +// RunnableMethod and IPC::MessageWithTuple. +// +// Tuple0 is supplied to act as a 'void' type. It can be used, for example, +// when dispatching to a function that accepts no arguments (see the +// Dispatchers below). +// Tuple1 is rarely useful. One such use is when A is non-const ref that you +// want filled by the dispatchee, and the tuple is merely a container for that +// output (a "tier"). See MakeRefTuple and its usages. + +struct Tuple0 { + typedef Tuple0 ValueTuple; + typedef Tuple0 RefTuple; + typedef Tuple0 ParamTuple; +}; + +template +struct Tuple1 { + public: + typedef A TypeA; + + Tuple1() {} + explicit Tuple1(typename TupleTraits::ParamType a) : a(a) {} + + A a; +}; + +template +struct Tuple2 { + public: + typedef A TypeA; + typedef B TypeB; + + Tuple2() {} + Tuple2(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b) + : a(a), b(b) { + } + + A a; + B b; +}; + +template +struct Tuple3 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + + Tuple3() {} + Tuple3(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c) + : a(a), b(b), c(c){ + } + + A a; + B b; + C c; +}; + +template +struct Tuple4 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + + Tuple4() {} + Tuple4(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d) + : a(a), b(b), c(c), d(d) { + } + + A a; + B b; + C c; + D d; +}; + +template +struct Tuple5 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + + Tuple5() {} + Tuple5(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e) + : a(a), b(b), c(c), d(d), e(e) { + } + + A a; + B b; + C c; + D d; + E e; +}; + +template +struct Tuple6 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + + Tuple6() {} + Tuple6(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f) + : a(a), b(b), c(c), d(d), e(e), f(f) { + } + + A a; + B b; + C c; + D d; + E e; + F f; +}; + +template +struct Tuple7 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + typedef G TypeG; + + Tuple7() {} + Tuple7(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f, + typename TupleTraits::ParamType g) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g) { + } + + A a; + B b; + C c; + D d; + E e; + F f; + G g; +}; + +template +struct Tuple8 { + public: + typedef A TypeA; + typedef B TypeB; + typedef C TypeC; + typedef D TypeD; + typedef E TypeE; + typedef F TypeF; + typedef G TypeG; + typedef H TypeH; + + Tuple8() {} + Tuple8(typename TupleTraits::ParamType a, + typename TupleTraits::ParamType b, + typename TupleTraits::ParamType c, + typename TupleTraits::ParamType d, + typename TupleTraits::ParamType e, + typename TupleTraits::ParamType f, + typename TupleTraits::ParamType g, + typename TupleTraits::ParamType h) + : a(a), b(b), c(c), d(d), e(e), f(f), g(g), h(h) { + } + + A a; + B b; + C c; + D d; + E e; + F f; + G g; + H h; +}; + +// Tuple types ---------------------------------------------------------------- +// +// Allows for selection of ValueTuple/RefTuple/ParamTuple without needing the +// definitions of class types the tuple takes as parameters. + +template <> +struct TupleTypes< Tuple0 > { + typedef Tuple0 ValueTuple; + typedef Tuple0 RefTuple; + typedef Tuple0 ParamTuple; +}; + +template +struct TupleTypes< Tuple1 > { + typedef Tuple1::ValueType> ValueTuple; + typedef Tuple1::RefType> RefTuple; + typedef Tuple1::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple2 > { + typedef Tuple2::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple2::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple2::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple3 > { + typedef Tuple3::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple3::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple3::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple4 > { + typedef Tuple4::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple4::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple4::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple5 > { + typedef Tuple5::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple5::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple5::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple6 > { + typedef Tuple6::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple6::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple6::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple7 > { + typedef Tuple7::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple7::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple7::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +template +struct TupleTypes< Tuple8 > { + typedef Tuple8::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType, + typename TupleTraits::ValueType> ValueTuple; +typedef Tuple8::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType, + typename TupleTraits::RefType> RefTuple; + typedef Tuple8::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType, + typename TupleTraits::ParamType> ParamTuple; +}; + +// Tuple creators ------------------------------------------------------------- +// +// Helper functions for constructing tuples while inferring the template +// argument types. + +inline Tuple0 MakeTuple() { + return Tuple0(); +} + +template +inline Tuple1 MakeTuple(const A& a) { + return Tuple1(a); +} + +template +inline Tuple2 MakeTuple(const A& a, const B& b) { + return Tuple2(a, b); +} + +template +inline Tuple3 MakeTuple(const A& a, const B& b, const C& c) { + return Tuple3(a, b, c); +} + +template +inline Tuple4 MakeTuple(const A& a, const B& b, const C& c, + const D& d) { + return Tuple4(a, b, c, d); +} + +template +inline Tuple5 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e) { + return Tuple5(a, b, c, d, e); +} + +template +inline Tuple6 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e, const F& f) { + return Tuple6(a, b, c, d, e, f); +} + +template +inline Tuple7 MakeTuple(const A& a, const B& b, const C& c, + const D& d, const E& e, const F& f, + const G& g) { + return Tuple7(a, b, c, d, e, f, g); +} + +template +inline Tuple8 MakeTuple(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 Tuple8(a, b, c, d, e, f, g, h); +} + +// The following set of helpers make what Boost refers to as "Tiers" - a tuple +// of references. + +template +inline Tuple1 MakeRefTuple(A& a) { + return Tuple1(a); +} + +template +inline Tuple2 MakeRefTuple(A& a, B& b) { + return Tuple2(a, b); +} + +template +inline Tuple3 MakeRefTuple(A& a, B& b, C& c) { + return Tuple3(a, b, c); +} + +template +inline Tuple4 MakeRefTuple(A& a, B& b, C& c, D& d) { + return Tuple4(a, b, c, d); +} + +template +inline Tuple5 MakeRefTuple(A& a, B& b, C& c, D& d, E& e) { + return Tuple5(a, b, c, d, e); +} + +template +inline Tuple6 MakeRefTuple(A& a, B& b, C& c, D& d, E& e, + F& f) { + return Tuple6(a, b, c, d, e, f); +} + +template +inline Tuple7 MakeRefTuple(A& a, B& b, C& c, D& d, + E& e, F& f, G& g) { + return Tuple7(a, b, c, d, e, f, g); +} + +template +inline Tuple8 MakeRefTuple(A& a, B& b, C& c, + D& d, E& e, F& f, + G& g, H& h) { + return Tuple8(a, b, c, d, e, f, g, h); +} + +// Dispatchers ---------------------------------------------------------------- +// +// Helper functions that call the given method on an object, with the unpacked +// tuple arguments. Notice that they all have the same number of arguments, +// so you need only write: +// DispatchToMethod(object, &Object::method, args); +// This is very useful for templated dispatchers, since they don't need to know +// what type |args| is. + +// Non-Static Dispatchers with no out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, const Tuple0& arg) { + (obj->*method)(); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const A& arg) { + (obj->*method)(arg); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const Tuple1& arg) { + +#if defined(OS_CHROMEOS) + // To troubleshoot crosbug.com/7327. + CHECK(obj); + CHECK(&arg); + CHECK(method); +#endif + (obj->*method)(arg.a); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple2& arg) { + (obj->*method)(arg.a, arg.b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& arg) { + (obj->*method)(arg.a, arg.b, arg.c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& arg) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& arg) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& arg) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple7& arg) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); +} + +// Static Dispatchers with no out params. + +template +inline void DispatchToFunction(Function function, const Tuple0& arg) { + (*function)(); +} + +template +inline void DispatchToFunction(Function function, const A& arg) { + (*function)(arg); +} + +template +inline void DispatchToFunction(Function function, const Tuple1& arg) { + (*function)(arg.a); +} + +template +inline void DispatchToFunction(Function function, const Tuple2& arg) { + (*function)(arg.a, arg.b); +} + +template +inline void DispatchToFunction(Function function, const Tuple3& arg) { + (*function)(arg.a, arg.b, arg.c); +} + +template +inline void DispatchToFunction(Function function, + const Tuple4& arg) { + (*function)(arg.a, arg.b, arg.c, arg.d); +} + +template +inline void DispatchToFunction(Function function, + const Tuple5& arg) { + (*function)(arg.a, arg.b, arg.c, arg.d, arg.e); +} + +template +inline void DispatchToFunction(Function function, + const Tuple6& arg) { + (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); +} + +template +inline void DispatchToFunction(Function function, + const Tuple7& arg) { + (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g); +} + +template +inline void DispatchToFunction(Function function, + const Tuple8& arg) { + (*function)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f, arg.g, arg.h); +} + +// Dispatchers with 0 out param (as a Tuple0). + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple0& arg, Tuple0*) { + (obj->*method)(); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, const A& arg, Tuple0*) { + (obj->*method)(arg); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple1& arg, Tuple0*) { + (obj->*method)(arg.a); +} + +template +inline void DispatchToMethod(ObjT* obj, + Method method, + const Tuple2& arg, Tuple0*) { + (obj->*method)(arg.a, arg.b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& arg, Tuple0*) { + (obj->*method)(arg.a, arg.b, arg.c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& arg, Tuple0*) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& arg, Tuple0*) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& arg, Tuple0*) { + (obj->*method)(arg.a, arg.b, arg.c, arg.d, arg.e, arg.f); +} + +// Dispatchers with 1 out param. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple1* out) { + (obj->*method)(&out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple1* out) { + (obj->*method)(in, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple1* out) { + (obj->*method)(in.a, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple1* out) { + (obj->*method)(in.a, in.b, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple1* out) { + (obj->*method)(in.a, in.b, in.c, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple1* out) { + (obj->*method)(in.a, in.b, in.c, in.d, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple1* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple1* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a); +} + +// Dispatchers with 2 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple2* out) { + (obj->*method)(&out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple2* out) { + (obj->*method)(in, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple2* out) { + (obj->*method)(in.a, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple2* out) { + (obj->*method)(in.a, in.b, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple2* out) { + (obj->*method)(in.a, in.b, in.c, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple2* out) { + (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple2* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple2* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b); +} + +// Dispatchers with 3 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple3* out) { + (obj->*method)(&out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple3* out) { + (obj->*method)(in, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple3* out) { + (obj->*method)(in.a, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple3* out) { + (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple3* out) { + (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple3* out) { + (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple3* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, &out->a, &out->b, &out->c); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple3* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, &out->a, &out->b, &out->c); +} + +// Dispatchers with 4 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple4* out) { + (obj->*method)(&out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple4* out) { + (obj->*method)(in, &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple4* out) { + (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple4* out) { + (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple4* out) { + (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple4* out) { + (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple4* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, + &out->a, &out->b, &out->c, &out->d); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple4* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, + &out->a, &out->b, &out->c, &out->d); +} + +// Dispatchers with 5 out params. + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple0& in, + Tuple5* out) { + (obj->*method)(&out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const InA& in, + Tuple5* out) { + (obj->*method)(in, &out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple1& in, + Tuple5* out) { + (obj->*method)(in.a, &out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple2& in, + Tuple5* out) { + (obj->*method)(in.a, in.b, &out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple3& in, + Tuple5* out) { + (obj->*method)(in.a, in.b, in.c, &out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple4& in, + Tuple5* out) { + (obj->*method)(in.a, in.b, in.c, in.d, &out->a, &out->b, &out->c, &out->d, + &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple5& in, + Tuple5* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, + &out->a, &out->b, &out->c, &out->d, &out->e); +} + +template +inline void DispatchToMethod(ObjT* obj, Method method, + const Tuple6& in, + Tuple5* out) { + (obj->*method)(in.a, in.b, in.c, in.d, in.e, in.f, + &out->a, &out->b, &out->c, &out->d, &out->e); +} + +#endif // BASE_TUPLE_H__ diff --git a/libcef/browser_impl.cc b/libcef/browser_impl.cc index e8c989492..554e6d14d 100644 --- a/libcef/browser_impl.cc +++ b/libcef/browser_impl.cc @@ -278,66 +278,57 @@ void CefBrowserImpl::CloseDevTools() void CefBrowserImpl::Undo(CefRefPtr 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 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 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 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 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 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 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 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 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 frame) @@ -374,27 +365,23 @@ void CefBrowserImpl::LoadRequest(CefRefPtr frame, CefRefPtr 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 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 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 frame, @@ -402,11 +389,8 @@ void CefBrowserImpl::LoadStream(CefRefPtr 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 frame, @@ -414,9 +398,8 @@ void CefBrowserImpl::ExecuteJavaScript(CefRefPtr 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 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 frame, + CefRefPtr request) { CefString url = request->GetURL(); CefString method = request->GetMethod(); - CefRequestImpl *impl = static_cast(request); + CefRequestImpl *impl = static_cast(request.get()); WebHTTPBody upload_data; CefRefPtr 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 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 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 frame, + CefRefPtr 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 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 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 diff --git a/libcef/browser_impl.h b/libcef/browser_impl.h index d65becae2..4ae249c4c 100644 --- a/libcef/browser_impl.h +++ b/libcef/browser_impl.h @@ -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 frame, const CefString& url); - void UIT_LoadURLForRequest(CefFrame* frame, + void UIT_LoadURLForRequest(CefRefPtr 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 frame, + CefRefPtr request); + void UIT_LoadHTML(CefRefPtr frame, const CefString& html, const CefString& url); - void UIT_LoadHTMLForStreamRef(CefFrame* frame, - CefStreamReader* stream, + void UIT_LoadHTMLForStreamRef(CefRefPtr frame, + CefRefPtr stream, const CefString& url); - void UIT_ExecuteJavaScript(CefFrame* frame, + void UIT_ExecuteJavaScript(CefRefPtr 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 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_; diff --git a/libcef/browser_impl_gtk.cc b/libcef/browser_impl_gtk.cc index 61d2c79e2..a32c6355f 100644 --- a/libcef/browser_impl_gtk.cc +++ b/libcef/browser_impl_gtk.cc @@ -66,11 +66,17 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url) handler_->HandleAfterCreated(this); } - if(url.size() > 0) { - CefRefPtr 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(); -} diff --git a/libcef/browser_impl_mac.mm b/libcef/browser_impl_mac.mm index 4e20262f9..c1630d8c0 100644 --- a/libcef/browser_impl_mac.mm +++ b/libcef/browser_impl_mac.mm @@ -71,11 +71,17 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url) handler_->HandleAfterCreated(this); } - if(url.size() > 0) { - CefRefPtr 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(); -} diff --git a/libcef/browser_impl_win.cc b/libcef/browser_impl_win.cc index 755eb27d4..8136355f5 100644 --- a/libcef/browser_impl_win.cc +++ b/libcef/browser_impl_win.cc @@ -149,11 +149,16 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url) handler_->HandleAfterCreated(this); } - if(url.length() > 0) { - CefRefPtr 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); -} diff --git a/libcef/browser_webview_delegate_win.cc b/libcef/browser_webview_delegate_win.cc index 7fe6620a3..d68f6fb3f 100644 --- a/libcef/browser_webview_delegate_win.cc +++ b/libcef/browser_webview_delegate_win.cc @@ -371,9 +371,7 @@ void BrowserWebViewDelegate::showContextMenu( if(!handled) { // Execute the action - CefRefPtr frame = browser_->GetFocusedFrame(); - frame->AddRef(); - browser_->UIT_HandleAction(menuId, frame.get()); + browser_->UIT_HandleAction(menuId, browser_->GetFocusedFrame()); } } } diff --git a/libcef/cef_context.cc b/libcef/cef_context.cc index e736cc809..9f9e693b2 100644 --- a/libcef/cef_context.cc +++ b/libcef/cef_context.cc @@ -154,13 +154,15 @@ bool CefCurrentlyOn(CefThreadId threadId) return CefThread::CurrentlyOn(static_cast(id)); } -class CefTaskHelper : public base::RefCountedThreadSafe +class CefTaskHelper : public Task { public: - CefTaskHelper(CefRefPtr task) : task_(task) {} - void Execute(CefThreadId threadId) { task_->Execute(threadId); } + CefTaskHelper(CefRefPtr task, CefThreadId threadId) + : task_(task), thread_id_(threadId) {} + virtual void Run() { task_->Execute(thread_id_); } private: CefRefPtr task_; + CefThreadId thread_id_; DISALLOW_COPY_AND_ASSIGN(CefTaskHelper); }; @@ -170,9 +172,8 @@ bool CefPostTask(CefThreadId threadId, CefRefPtr task) if(id < 0) return false; - scoped_refptr helper(new CefTaskHelper(task)); return CefThread::PostTask(static_cast(id), FROM_HERE, - NewRunnableMethod(helper.get(), &CefTaskHelper::Execute, threadId)); + new CefTaskHelper(task, threadId)); } bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr task, @@ -182,10 +183,8 @@ bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr task, if(id < 0) return false; - scoped_refptr helper(new CefTaskHelper(task)); return CefThread::PostDelayedTask(static_cast(id), FROM_HERE, - NewRunnableMethod(helper.get(), &CefTaskHelper::Execute, threadId), - delay_ms); + new CefTaskHelper(task, threadId), delay_ms); } diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index 10f869b73..9284f4335 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -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 frame) +{ + // Retrieve the current page source and display. + std::string source = frame->GetSource(); + source = StringReplace(source, "<", "<"); + source = StringReplace(source, ">", ">"); + std::stringstream ss; + ss << "Source:" << "
" << source
+      << "
"; + frame->LoadString(ss.str(), "http://tests/getsource"); +} + void RunGetSourceTest(CefRefPtr browser) { // Execute the GetSource() call on the UI thread. - class ExecTask : public CefThreadSafeBase - { - public: - ExecTask(CefRefPtr 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, "<", "<"); - source = StringReplace(source, ">", ">"); - std::stringstream ss; - ss << "Source:" << "
" << source
-          << "
"; - m_Frame->LoadString(ss.str(), "http://tests/getsource"); - } - private: - CefRefPtr m_Frame; - }; - CefPostTask(TID_UI, new ExecTask(browser->GetMainFrame())); + CefPostTask(TID_UI, + NewCefRunnableFunction(&ExecuteGetSource, browser->GetMainFrame())); +} + +static void ExecuteGetText(CefRefPtr frame) +{ + std::string text = frame->GetText(); + text = StringReplace(text, "<", "<"); + text = StringReplace(text, ">", ">"); + std::stringstream ss; + ss << "Text:" << "
" << text
+      << "
"; + frame->LoadString(ss.str(), "http://tests/gettext"); } void RunGetTextTest(CefRefPtr browser) { // Execute the GetText() call on the UI thread. - class ExecTask : public CefThreadSafeBase - { - public: - ExecTask(CefRefPtr 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, "<", "<"); - text = StringReplace(text, ">", ">"); - std::stringstream ss; - ss << "Text:" << "
" << text
-          << "
"; - m_Frame->LoadString(ss.str(), "http://tests/gettext"); - } - private: - CefRefPtr m_Frame; - }; - CefPostTask(TID_UI, new ExecTask(browser->GetMainFrame())); + CefPostTask(TID_UI, + NewCefRunnableFunction(&ExecuteGetText, browser->GetMainFrame())); } void RunRequestTest(CefRefPtr browser) diff --git a/tests/cefclient/download_handler.cpp b/tests/cefclient/download_handler.cpp index 6908ad5d5..1efd62925 100644 --- a/tests/cefclient/download_handler.cpp +++ b/tests/cefclient/download_handler.cpp @@ -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 @@ -14,38 +15,6 @@ #include #endif // _WIN32 - -namespace { - -// Template for creating a task that executes a method with no arguments. -template -class Task : public CefThreadSafeBase -{ -public: - Task(T* object, Method method) - : object_(object), method_(method) {} - - virtual void Execute(CefThreadId threadId) - { - (object_->*method_)(); - } - -protected: - CefRefPtr object_; - Method method_; -}; - -// Helper method for posting a task on a specific thread. -template -inline void PostOnThread(CefThreadId threadId, - T* object, - Method method) { - CefRefPtr task = new Task(object, method); - CefPostTask(threadId, task); -} - -} // namespace - // Implementation of the CefDownloadHandler interface. class ClientDownloadHandler : public CefThreadSafeBase { @@ -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 - { - 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 listener_; CefString filename_; @@ -232,5 +207,8 @@ private: CefRefPtr CreateDownloadHandler( CefRefPtr listener, const CefString& fileName) { - return new ClientDownloadHandler(listener, fileName); + CefRefPtr handler = + new ClientDownloadHandler(listener, fileName); + handler->Initialize(); + return handler.get(); }