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];
 };