diff options
author | Andras Becsi <andras.becsi@theqtcompany.com> | 2015-05-11 14:32:01 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-06-08 10:56:08 +0000 |
commit | 8c3178b64d992435cb90a426ff075fee6778e04a (patch) | |
tree | e53836e4824073851f94d4c6fcfac99526f0a100 /src/core/api | |
parent | bfef77e3ca0d82253fb70ff178ff5a826c671d55 (diff) |
Move QWebEngineCallback to core API and templatize CallbackDirectory
This undocumented helper template will also be utilized by the
core API since Chromium's content API heavily relies on callbacks.
To make the internal CallbackDirectory easily extendable with new
types, templatize its callback registration and dispatching functions
to be able to replace its type switches and the internal union.
Change-Id: I3f636fef48973ac95253f1c1bd396550286e571e
Reviewed-by: Pierre Rossi <pierre.rossi@theqtcompany.com>
Diffstat (limited to 'src/core/api')
-rw-r--r-- | src/core/api/core_api.pro | 2 | ||||
-rw-r--r-- | src/core/api/qwebenginecallback.h | 92 | ||||
-rw-r--r-- | src/core/api/qwebenginecallback_p.h | 213 |
3 files changed, 307 insertions, 0 deletions
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 829b59925..e0a6c2de4 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -26,6 +26,8 @@ INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core \ linux-g++*: QMAKE_CXXFLAGS += -Wno-unused-parameter HEADERS = \ + qwebenginecallback.h \ + qwebenginecallback_p.h \ qtwebenginecoreglobal.h \ qtwebenginecoreglobal_p.h \ diff --git a/src/core/api/qwebenginecallback.h b/src/core/api/qwebenginecallback.h new file mode 100644 index 000000000..a88fa838c --- /dev/null +++ b/src/core/api/qwebenginecallback.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINECALLBACK_H +#define QWEBENGINECALLBACK_H + +#include "qtwebenginecoreglobal.h" + +#include <QtCore/qcompilerdetection.h> // Needed for Q_DECL_OVERRIDE +#include <QExplicitlySharedDataPointer> +#include <QString> +#include <QVariant> + +namespace QtWebEngineCore { +class CallbackDirectory; +} + +QT_BEGIN_NAMESPACE + +namespace QtWebEnginePrivate { + +template <typename T> +class QWebEngineCallbackPrivateBase : public QSharedData { +public: + QWebEngineCallbackPrivateBase() {} + virtual ~QWebEngineCallbackPrivateBase() {} + virtual void operator()(T) = 0; +}; + +template <typename T, typename F> +class QWebEngineCallbackPrivate : public QWebEngineCallbackPrivateBase<T> { +public: + QWebEngineCallbackPrivate(F callable) + : m_callable(callable) + {} + virtual void operator()(T value) Q_DECL_OVERRIDE { m_callable(value); } +private: + F m_callable; +}; + +} // namespace QtWebEnginePrivate + +template <typename T> +class QWebEngineCallback { +public: + template <typename F> + QWebEngineCallback(F f) + : d(new QtWebEnginePrivate::QWebEngineCallbackPrivate<T, F>(f)) + { } + QWebEngineCallback() { } + operator bool() const { return d; } +private: + friend class QtWebEngineCore::CallbackDirectory; + QExplicitlySharedDataPointer<QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> > d; +}; + +QT_END_NAMESPACE + +#endif // QWEBENGINECALLBACK_H diff --git a/src/core/api/qwebenginecallback_p.h b/src/core/api/qwebenginecallback_p.h new file mode 100644 index 000000000..9c798acbe --- /dev/null +++ b/src/core/api/qwebenginecallback_p.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINECALLBACK_P_H +#define QWEBENGINECALLBACK_P_H + +#include "qtwebenginecoreglobal_p.h" +#include "qwebenginecallback.h" + +#include <QHash> +#include <QSharedData> +#include <QString> +#include <QVariant> +#include <type_traits> + +#define FOR_EACH_TYPE(F) \ + F(bool) \ + F(int) \ + F(const QString &) \ + F(const QVariant &) + +namespace QtWebEngineCore { + +class CallbackDirectory { + template<typename T> + void invokeInternal(quint64 callbackId, T result); + template<typename T> + void invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback); + +public: + ~CallbackDirectory() + { + // "Cancel" pending callbacks by calling them with an invalid value. + // This guarantees that each callback is called exactly once. + for (CallbackSharedDataPointerBase * const sharedPtrBase: m_callbackMap) { + Q_ASSERT(sharedPtrBase); + sharedPtrBase->invokeEmpty(); + delete sharedPtrBase; + } + } + + template<typename T> + void registerCallback(quint64 callbackId, const QWebEngineCallback<T> &callback); + + template<typename T> + void invokeEmpty(const QWebEngineCallback<T> &callback); + +#define DEFINE_INVOKE_FOR_TYPE(Type) \ + void invoke(quint64 callbackId, Type result) { \ + invokeInternal<Type>(callbackId, std::forward<Type>(result)); \ + } + FOR_EACH_TYPE(DEFINE_INVOKE_FOR_TYPE) +#undef DEFINE_INVOKE_FOR_TYPE + +private: + struct CallbackSharedDataPointerBase { + virtual ~CallbackSharedDataPointerBase() { } + virtual void invokeEmpty() = 0; + virtual void doRef() = 0; + virtual void doDeref() = 0; + virtual operator bool () const = 0; + }; + + template <typename T> + struct CallbackSharedDataPointer : public CallbackSharedDataPointerBase { + CallbackDirectory* parent; + QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback; + + ~CallbackSharedDataPointer() { doDeref(); } + CallbackSharedDataPointer() : parent(0), callback(0) { } + CallbackSharedDataPointer(const CallbackSharedDataPointer<T> &other) + : parent(other.parent), callback(other.callback) { doRef(); } + CallbackSharedDataPointer(CallbackDirectory *p, QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *c) + : parent(p), callback(c) { Q_ASSERT(callback); doRef(); } + + void invokeEmpty() override; + operator bool () const override { return callback; } + + private: + void doRef() override; + void doDeref() override; + }; + + QHash<quint64, CallbackSharedDataPointerBase*> m_callbackMap; +}; + +template<typename T> +inline +void CallbackDirectory::registerCallback(quint64 callbackId, const QWebEngineCallback<T> &callback) +{ + if (!callback.d) + return; + m_callbackMap.insert(callbackId, new CallbackSharedDataPointer<T>(this, callback.d.data())); +} + +template<typename T> +inline +void CallbackDirectory::invokeInternal(quint64 callbackId, T result) +{ + CallbackSharedDataPointerBase * const sharedPtrBase = m_callbackMap.take(callbackId); + if (!sharedPtrBase) + return; + + auto ptr = static_cast<CallbackSharedDataPointer<T> *>(sharedPtrBase); + Q_ASSERT(ptr); + (*ptr->callback)(std::forward<T>(result)); + delete ptr; +} + +template<typename T> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> *callback) +{ + Q_ASSERT(callback); + using NoRefT = typename std::remove_reference<T>::type; + using NoConstNoRefT = typename std::remove_const<NoRefT>::type; + NoConstNoRefT t; + (*callback)(t); +} + +template<> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<bool> *callback) +{ + Q_ASSERT(callback); + (*callback)(false); +} + +template<> +inline +void CallbackDirectory::invokeEmptyInternal(QtWebEnginePrivate::QWebEngineCallbackPrivateBase<int> *callback) +{ + Q_ASSERT(callback); + (*callback)(0); +} + +template<typename T> +inline +void CallbackDirectory::invokeEmpty(const QWebEngineCallback<T> &callback) +{ + if (!callback.d) + return; + + invokeEmptyInternal(callback.d.data()); +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::doRef() +{ + if (!callback) + return; + + callback->ref.ref(); +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::doDeref() +{ + if (!callback) + return; + if (!callback->ref.deref()) + delete callback; +} + +template <typename T> +inline +void CallbackDirectory::CallbackSharedDataPointer<T>::invokeEmpty() +{ + if (!callback) + return; + + Q_ASSERT(parent); + parent->invokeEmptyInternal(callback); +} + +} // namespace QtWebEngineCore + +#endif // QWEBENGINECALLBACK_P_H |