summaryrefslogtreecommitdiffstats
path: root/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/webenginequick/api/qquickwebenginefaviconprovider.cpp')
-rw-r--r--src/webenginequick/api/qquickwebenginefaviconprovider.cpp179
1 files changed, 155 insertions, 24 deletions
diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
index 23397003e..d19954620 100644
--- a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
+++ b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
@@ -39,10 +39,13 @@
#include "qquickwebenginefaviconprovider_p_p.h"
-#include "qquickwebengineview_p.h"
+#include "profile_adapter.h"
+#include "qquickwebenginesettings_p.h"
#include "qquickwebengineview_p_p.h"
#include "web_contents_adapter.h"
+#include <QtCore/QMimeDatabase>
+#include <QtCore/QTimer>
#include <QtGui/QIcon>
#include <QtGui/QPixmap>
@@ -95,14 +98,155 @@ static QPixmap extractPixmap(const QIcon &icon, const QSize &requestedSize)
return iconPixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation).copy();
}
+static bool isIconURL(const QUrl &url)
+{
+ QMimeType mimeType = QMimeDatabase().mimeTypeForFile(url.path(), QMimeDatabase::MatchExtension);
+
+ // Check file extension.
+ if (mimeType.name().startsWith(QLatin1String("image")))
+ return true;
+
+ // Check if it is an image data: URL.
+ if (url.scheme() == QLatin1String("data") && url.path().startsWith(QLatin1String("image")))
+ return true;
+
+ return false;
+}
+
static QQuickWebEngineView *findViewById(const QString &id, QList<QQuickWebEngineView *> *views)
{
+ QQuickWebEngineView *result = nullptr;
for (QQuickWebEngineView *view : *views) {
- if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(QUrl(id)))
- return view;
+ if (isIconURL(QUrl(id))) {
+ if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(QUrl(id))) {
+ result = view;
+ break;
+ }
+ } else if (view->url() == QUrl(id)) {
+ result = view;
+ break;
+ }
+ }
+
+ return result;
+}
+
+FaviconImageResponseRunnable::FaviconImageResponseRunnable(const QString &id,
+ const QSize &requestedSize,
+ QList<QQuickWebEngineView *> *views)
+ : m_id(id), m_requestedSize(requestedSize), m_views(views)
+{
+}
+
+void FaviconImageResponseRunnable::run()
+{
+ if (tryNextView() == -1) {
+ // There is no non-otr view to access icon database.
+ Q_EMIT done(QPixmap());
+ }
+}
+
+void FaviconImageResponseRunnable::iconRequestDone(const QIcon &icon)
+{
+ if (icon.isNull()) {
+ if (tryNextView() == -1) {
+ // Ran out of views.
+ Q_EMIT done(QPixmap());
+ }
+ return;
+ }
+
+ Q_EMIT done(extractPixmap(icon, m_requestedSize).copy());
+}
+
+int FaviconImageResponseRunnable::tryNextView()
+{
+ for (; m_nextViewIndex < m_views->size(); ++m_nextViewIndex) {
+ QQuickWebEngineView *view = m_views->at(m_nextViewIndex);
+ if (view->profile()->isOffTheRecord())
+ continue;
+
+ requestIconOnUIThread(view);
+
+ return m_nextViewIndex++;
}
- return nullptr;
+ return -1;
+}
+
+void FaviconImageResponseRunnable::requestIconOnUIThread(QQuickWebEngineView *view)
+{
+ QTimer *timer = new QTimer();
+ timer->moveToThread(qApp->thread());
+ timer->setSingleShot(true);
+ QObject::connect(timer, &QTimer::timeout, [=]() {
+ QtWebEngineCore::ProfileAdapter *profileAdapter = view->d_ptr->profileAdapter();
+ bool touchIconsEnabled = view->profile()->settings()->touchIconsEnabled();
+ if (isIconURL(QUrl(m_id))) {
+ profileAdapter->requestIconForIconURL(QUrl(m_id),
+ qMax(m_requestedSize.width(), m_requestedSize.height()),
+ touchIconsEnabled,
+ [this](const QIcon &icon, const QUrl &) { iconRequestDone(icon); });
+ } else {
+ profileAdapter->requestIconForPageURL(QUrl(m_id),
+ qMax(m_requestedSize.width(), m_requestedSize.height()),
+ touchIconsEnabled,
+ [this](const QIcon &icon, const QUrl &, const QUrl &) { iconRequestDone(icon); });
+ }
+ timer->deleteLater();
+ });
+ QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
+}
+
+FaviconImageResponse::FaviconImageResponse()
+{
+ Q_EMIT finished();
+}
+
+FaviconImageResponse::FaviconImageResponse(const QString &id, const QSize &requestedSize,
+ QList<QQuickWebEngineView *> *views, QThreadPool *pool)
+{
+ if (QQuickWebEngineView *view = findViewById(id, views)) {
+ QTimer *timer = new QTimer();
+ timer->moveToThread(qApp->thread());
+ timer->setSingleShot(true);
+ QObject::connect(timer, &QTimer::timeout, [=]() {
+ QIcon icon = view->d_ptr->adapter->icon();
+ if (icon.isNull())
+ startRunnable(id, requestedSize, views, pool);
+ else
+ handleDone(extractPixmap(icon, requestedSize).copy());
+ timer->deleteLater();
+ });
+ QMetaObject::invokeMethod(timer, "start", Qt::QueuedConnection, Q_ARG(int, 0));
+ } else {
+ startRunnable(id, requestedSize, views, pool);
+ }
+}
+
+FaviconImageResponse::~FaviconImageResponse() { }
+
+void FaviconImageResponse::handleDone(QPixmap pixmap)
+{
+ if (m_runnable)
+ delete m_runnable;
+ m_image = pixmap.toImage();
+ Q_EMIT finished();
+}
+
+QQuickTextureFactory *FaviconImageResponse::textureFactory() const
+{
+ return QQuickTextureFactory::textureFactoryForImage(m_image);
+}
+
+void FaviconImageResponse::startRunnable(const QString &id, const QSize &requestedSize,
+ QList<QQuickWebEngineView *> *views, QThreadPool *pool)
+{
+ m_runnable = new FaviconImageResponseRunnable(id, requestedSize, views);
+ m_runnable->setAutoDelete(false);
+ connect(m_runnable, &FaviconImageResponseRunnable::done, this,
+ &FaviconImageResponse::handleDone);
+ pool->start(m_runnable);
}
QString QQuickWebEngineFaviconProvider::identifier()
@@ -128,31 +272,18 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url)
return providerUrl;
}
-QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider()
- : QQuickImageProvider(QQuickImageProvider::Pixmap)
-{
-}
+QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider() { }
QQuickWebEngineFaviconProvider::~QQuickWebEngineFaviconProvider() { }
-QPixmap QQuickWebEngineFaviconProvider::requestPixmap(const QString &id, QSize *size,
- const QSize &requestedSize)
+QQuickImageResponse *
+QQuickWebEngineFaviconProvider::requestImageResponse(const QString &id, const QSize &requestedSize)
{
- Q_UNUSED(size);
- Q_UNUSED(requestedSize);
-
- if (m_views.isEmpty())
- return QPixmap();
-
- QQuickWebEngineView *view = findViewById(id, &m_views);
- if (!view)
- return QPixmap();
-
- QIcon icon = view->d_ptr->adapter->icon();
- if (icon.isNull())
- return QPixmap();
+ if (m_views.empty())
+ return new FaviconImageResponse;
- return extractPixmap(icon, requestedSize).copy();
+ FaviconImageResponse *response = new FaviconImageResponse(id, requestedSize, &m_views, &m_pool);
+ return response;
}
QT_END_NAMESPACE