diff options
Diffstat (limited to 'src/webenginequick/api/qquickwebenginefaviconprovider.cpp')
-rw-r--r-- | src/webenginequick/api/qquickwebenginefaviconprovider.cpp | 179 |
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 |