diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 829b59925614754054e9f9f82c9df88a8d8f5cce..e0a6c2de4aa87f9abfa4eedb7bcec6e3e29dd97b 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 0000000000000000000000000000000000000000..a88fa838cccf27fd1bc97bc4bfe8fbe44a315cd9 --- /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 0000000000000000000000000000000000000000..9c798acbe6a53741c4724d4d0d902bbc38b11c3d --- /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 diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index bc0a97f97dc9eb873b2bda7043b8eb85dde19ffb..bf5868925ca97bc76ba90f5466021864c5a63ee5 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -79,106 +79,6 @@ static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::Wind } } -CallbackDirectory::~CallbackDirectory() -{ - // "Cancel" pending callbacks by calling them with an invalid value. - // This guarantees that each callback is called exactly once. - Q_FOREACH (const CallbackSharedDataPointer &sharedPtr, m_callbackMap) { - switch (sharedPtr.type) { - case CallbackSharedDataPointer::Variant: - (*sharedPtr.variantCallback)(QVariant()); - break; - case CallbackSharedDataPointer::String: - (*sharedPtr.stringCallback)(QString()); - break; - case CallbackSharedDataPointer::Bool: - (*sharedPtr.boolCallback)(false); - break; - default: - Q_UNREACHABLE(); - } - } -} - -void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<VariantCallback> &callback) -{ - m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); -} - -void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<StringCallback> &callback) -{ - m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); -} - -void CallbackDirectory::registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<BoolCallback> &callback) -{ - m_callbackMap.insert(requestId, CallbackSharedDataPointer(callback.data())); -} - -void CallbackDirectory::invoke(quint64 requestId, const QVariant &result) -{ - CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); - if (sharedPtr) { - Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::Variant); - (*sharedPtr.variantCallback)(result); - } -} - -void CallbackDirectory::invoke(quint64 requestId, const QString &result) -{ - CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); - if (sharedPtr) { - Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::String); - (*sharedPtr.stringCallback)(result); - } -} - -void CallbackDirectory::invoke(quint64 requestId, bool result) -{ - CallbackSharedDataPointer sharedPtr = m_callbackMap.take(requestId); - if (sharedPtr) { - Q_ASSERT(sharedPtr.type == CallbackSharedDataPointer::Bool); - (*sharedPtr.boolCallback)(result); - } -} - -void CallbackDirectory::CallbackSharedDataPointer::doRef() -{ - switch (type) { - case None: - break; - case Variant: - variantCallback->ref.ref(); - break; - case String: - stringCallback->ref.ref(); - break; - case Bool: - boolCallback->ref.ref(); - break; - } -} - -void CallbackDirectory::CallbackSharedDataPointer::doDeref() -{ - switch (type) { - case None: - break; - case Variant: - if (!variantCallback->ref.deref()) - delete variantCallback; - break; - case String: - if (!stringCallback->ref.deref()) - delete stringCallback; - break; - case Bool: - if (!boolCallback->ref.deref()) - delete boolCallback; - break; - } -} - QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) : adapter(new WebContentsAdapter) , history(new QWebEngineHistory(new QWebEngineHistoryPrivate(this))) @@ -814,12 +714,10 @@ void QWebEnginePage::findText(const QString &subString, FindFlags options, const Q_D(QWebEnginePage); if (subString.isEmpty()) { d->adapter->stopFinding(); - if (resultCallback.d) - (*resultCallback.d)(false); + d->m_callbacks.invokeEmpty(resultCallback); } else { quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); - if (resultCallback.d) - d->m_callbacks.registerCallback(requestId, resultCallback.d); + d->m_callbacks.registerCallback(requestId, resultCallback); } } @@ -1087,14 +985,14 @@ void QWebEnginePage::toHtml(const QWebEngineCallback<const QString &> &resultCal { Q_D(const QWebEnginePage); quint64 requestId = d->adapter->fetchDocumentMarkup(); - d->m_callbacks.registerCallback(requestId, resultCallback.d); + d->m_callbacks.registerCallback(requestId, resultCallback); } void QWebEnginePage::toPlainText(const QWebEngineCallback<const QString &> &resultCallback) const { Q_D(const QWebEnginePage); quint64 requestId = d->adapter->fetchDocumentInnerText(); - d->m_callbacks.registerCallback(requestId, resultCallback.d); + d->m_callbacks.registerCallback(requestId, resultCallback); } void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl) @@ -1161,7 +1059,7 @@ void QWebEnginePage::runJavaScript(const QString& scriptSource, const QWebEngine { Q_D(QWebEnginePage); quint64 requestId = d->adapter->runJavaScriptCallbackResult(scriptSource); - d->m_callbacks.registerCallback(requestId, resultCallback.d); + d->m_callbacks.registerCallback(requestId, resultCallback); } /*! diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 4281a70a0b52ffadf97ff5e8f56bf2253da39360..16b33a1961bf154bf12aab71bc2cc278d1fcd699 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -39,6 +39,7 @@ #include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h> #include <QtWebEngineWidgets/qwebenginecertificateerror.h> +#include <QtWebEngineCore/qwebenginecallback.h> #include <QtCore/qobject.h> #include <QtCore/qurl.h> @@ -56,37 +57,6 @@ class QWebEngineProfile; class QWebEngineScriptCollection; class QWebEngineSettings; -namespace QtWebEnginePrivate { - -template <typename T> -class QWebEngineCallbackPrivateBase : public QSharedData { -public: - 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() { } -private: - QExplicitlySharedDataPointer<QtWebEnginePrivate::QWebEngineCallbackPrivateBase<T> > d; - friend class QWebEnginePage; -}; - class QWEBENGINEWIDGETS_EXPORT QWebEnginePage : public QObject { Q_OBJECT Q_PROPERTY(QString selectedText READ selectedText) diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index 62ca16415e14288e6f684f24c806542effbe34ba..a5ede1a8e8dabf75ef5832cee72b12820240133f 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -39,10 +39,10 @@ #include "qwebenginepage.h" +#include "qwebenginecallback_p.h" #include "qwebenginescriptcollection.h" #include "web_contents_adapter_client.h" #include <QtCore/qcompilerdetection.h> -#include <QSharedData> namespace QtWebEngineCore { class RenderWidgetHostViewQtDelegate; @@ -56,49 +56,6 @@ class QWebEngineProfile; class QWebEngineSettings; class QWebEngineView; -class CallbackDirectory { -public: - typedef QtWebEnginePrivate::QWebEngineCallbackPrivateBase<const QVariant&> VariantCallback; - typedef QtWebEnginePrivate::QWebEngineCallbackPrivateBase<const QString&> StringCallback; - typedef QtWebEnginePrivate::QWebEngineCallbackPrivateBase<bool> BoolCallback; - - ~CallbackDirectory(); - void registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<VariantCallback> &callback); - void registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<StringCallback> &callback); - void registerCallback(quint64 requestId, const QExplicitlySharedDataPointer<BoolCallback> &callback); - void invoke(quint64 requestId, const QVariant &result); - void invoke(quint64 requestId, const QString &result); - void invoke(quint64 requestId, bool result); - -private: - struct CallbackSharedDataPointer { - enum { - None, - Variant, - String, - Bool - } type; - union { - VariantCallback *variantCallback; - StringCallback *stringCallback; - BoolCallback *boolCallback; - }; - CallbackSharedDataPointer() : type(None) { } - CallbackSharedDataPointer(VariantCallback *callback) : type(Variant), variantCallback(callback) { callback->ref.ref(); } - CallbackSharedDataPointer(StringCallback *callback) : type(String), stringCallback(callback) { callback->ref.ref(); } - CallbackSharedDataPointer(BoolCallback *callback) : type(Bool), boolCallback(callback) { callback->ref.ref(); } - CallbackSharedDataPointer(const CallbackSharedDataPointer &other) : type(other.type), variantCallback(other.variantCallback) { doRef(); } - ~CallbackSharedDataPointer() { doDeref(); } - operator bool () const { return type != None; } - - private: - void doRef(); - void doDeref(); - }; - - QHash<quint64, CallbackSharedDataPointer> m_callbackMap; -}; - class QWebEnginePagePrivate : public QtWebEngineCore::WebContentsAdapterClient { public: @@ -171,7 +128,7 @@ public: bool isLoading; QWebEngineScriptCollection scriptCollection; - mutable CallbackDirectory m_callbacks; + mutable QtWebEngineCore::CallbackDirectory m_callbacks; mutable QAction *actions[QWebEnginePage::WebActionCount]; };