summaryrefslogtreecommitdiffstats
path: root/src/core/favicon_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/favicon_manager.cpp')
-rw-r--r--src/core/favicon_manager.cpp437
1 files changed, 0 insertions, 437 deletions
diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp
deleted file mode 100644
index 3cb417c4f..000000000
--- a/src/core/favicon_manager.cpp
+++ /dev/null
@@ -1,437 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://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 https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "favicon_manager.h"
-#include "type_conversion.h"
-#include "web_contents_adapter_client.h"
-#include "web_engine_settings.h"
-
-#include "base/bind.h"
-#include "content/public/browser/favicon_status.h"
-#include "content/public/browser/navigation_entry.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/url_constants.h"
-#include "net/base/data_url.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
-#include "ui/gfx/geometry/size.h"
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-#include <qiconengine.h>
-#include <private/qicon_p.h>
-#endif
-
-namespace QtWebEngineCore {
-
-static inline bool isResourceUrl(const QUrl &url)
-{
- return !url.scheme().compare(QLatin1String("qrc"));
-}
-
-static inline bool isDataUrl(const QUrl &url)
-{
- return !url.scheme().compare(QLatin1String(url::kDataScheme));
-}
-
-static inline unsigned area(const QSize &size)
-{
- return size.width() * size.height();
-}
-
-
-FaviconManager::FaviconManager(content::WebContents *webContents, WebContentsAdapterClient *viewClient)
- : m_webContents(webContents)
- , m_viewClient(viewClient)
- , m_candidateCount(0)
- , m_weakFactory(new base::WeakPtrFactory<FaviconManager>(this))
-{
-}
-
-FaviconManager::~FaviconManager()
-{
-}
-
-int FaviconManager::downloadIcon(const QUrl &url)
-{
- static const uint32_t maxSize = 256;
- static int fakeId = 0;
- int id;
-
- bool cached = m_icons.contains(url);
- if (isResourceUrl(url) || isDataUrl(url) || cached) {
- id = --fakeId;
- m_pendingRequests.insert(id, url);
- } else {
- id = m_webContents->DownloadImage(
- toGurl(url),
- true, // is_favicon
- 0, // preferred_size
- maxSize,
- false, // normal cache policy
- base::Bind(&FaviconManager::iconDownloadFinished, m_weakFactory->GetWeakPtr()));
- }
-
- Q_ASSERT(!m_inProgressRequests.contains(id));
- m_inProgressRequests.insert(id, url);
-
- return id;
-}
-
-void FaviconManager::iconDownloadFinished(int id,
- int status,
- const GURL &url,
- const std::vector<SkBitmap> &bitmaps,
- const std::vector<gfx::Size> &original_bitmap_sizes)
-{
- Q_UNUSED(status);
- Q_UNUSED(url);
- Q_UNUSED(original_bitmap_sizes);
-
- storeIcon(id, toQIcon(bitmaps));
-}
-
-/* Pending requests are used to mark icons that are already downloaded (cached icons or icons
- * stored in qrc). These requests are also stored in the m_inProgressRequests but the corresponding
- * icons are stored in m_icons explicitly by this function. It is necessary to avoid
- * m_inProgressRequests being emptied right before the next icon is added by a downloadIcon() call.
- */
-void FaviconManager::downloadPendingRequests()
-{
- for (auto it = m_pendingRequests.cbegin(), end = m_pendingRequests.cend(); it != end; ++it) {
- QIcon icon;
-
- QUrl requestUrl = it.value();
- if (!m_icons.contains(requestUrl)) {
- if (isResourceUrl(requestUrl)) {
- icon = QIcon(requestUrl.toString().remove(0, 3));
- } else if (isDataUrl(requestUrl)) {
- std::string mime_type, char_set, data;
- if (net::DataURL::Parse(toGurl(requestUrl), &mime_type, &char_set, &data) && !data.empty()) {
- const unsigned char *src_data = reinterpret_cast<const unsigned char *>(data.data());
- QImage image = QImage::fromData(src_data, data.size());
- icon.addPixmap(QPixmap::fromImage(image).copy());
- }
- }
- }
-
- storeIcon(it.key(), icon);
- }
-
- m_pendingRequests.clear();
-}
-
-void FaviconManager::storeIcon(int id, const QIcon &icon)
-{
-
- // Icon download has been interrupted
- if (!m_inProgressRequests.contains(id))
- return;
-
- QUrl requestUrl = m_inProgressRequests[id];
- FaviconInfo &faviconInfo = m_faviconInfoMap[requestUrl];
-
- unsigned iconCount = 0;
- if (!icon.isNull())
- iconCount = icon.availableSizes().count();
-
- if (iconCount > 0) {
- m_icons.insert(requestUrl, icon);
-
- faviconInfo.size = icon.availableSizes().at(0);
- if (iconCount > 1) {
- faviconInfo.multiSize = true;
- unsigned bestArea = area(faviconInfo.size);
- for (unsigned i = 1; i < iconCount; ++i) {
- QSize iconSize = icon.availableSizes().at(i);
- if (bestArea < area(iconSize)) {
- faviconInfo.size = iconSize;
- bestArea = area(iconSize);
- }
- }
- }
- } else if (id >= 0) {
- // Reset size if icon cannot be downloaded
- faviconInfo.size = QSize(0, 0);
- }
-
- m_inProgressRequests.remove(id);
- if (m_inProgressRequests.isEmpty()) {
- QWebEngineSettings *settings = m_viewClient->webEngineSettings();
- bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
-
- generateCandidateIcon(touchIconsEnabled);
- const QUrl &iconUrl = candidateIconUrl(touchIconsEnabled);
- propagateIcon(iconUrl);
- }
-}
-
-void FaviconManager::propagateIcon(const QUrl &iconUrl) const
-{
- content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
- if (entry) {
- content::FaviconStatus &favicon = entry->GetFavicon();
- favicon.url = toGurl(iconUrl);
- favicon.valid = true;
- }
-
- m_viewClient->iconChanged(iconUrl);
-}
-
-QIcon FaviconManager::getIcon(const QUrl &url) const
-{
- if (url.isEmpty())
- return m_candidateIcon;
-
- if (!m_icons.contains(url))
- return QIcon();
-
- return m_icons[url];
-}
-
-FaviconInfo FaviconManager::getFaviconInfo(const QUrl &url) const
-{
- Q_ASSERT(m_faviconInfoMap.contains(url));
- return m_faviconInfoMap[url];
-}
-
-QList<FaviconInfo> FaviconManager::getFaviconInfoList(bool candidatesOnly) const
-{
- QList<FaviconInfo> faviconInfoList = m_faviconInfoMap.values();
-
- if (candidatesOnly) {
- const auto hasNoCandidate = [](const FaviconInfo &info) { return !info.candidate; };
- faviconInfoList.erase(std::remove_if(faviconInfoList.begin(), faviconInfoList.end(),
- hasNoCandidate),
- faviconInfoList.end());
- }
-
- return faviconInfoList;
-}
-
-void FaviconManager::update(const QList<FaviconInfo> &candidates)
-{
- updateCandidates(candidates);
-
- QWebEngineSettings *settings = m_viewClient->webEngineSettings();
- if (!settings->testAttribute(QWebEngineSettings::AutoLoadIconsForPage)) {
- m_viewClient->iconChanged(QUrl());
- return;
- }
-
- bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
-
- const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
- for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
- continue;
-
- if (it->isValid())
- downloadIcon(it->url);
- }
-
- downloadPendingRequests();
-
- // Reset icon if nothing was downloaded
- if (m_inProgressRequests.isEmpty()) {
- content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
- if (entry && !entry->GetFavicon().valid)
- m_viewClient->iconChanged(QUrl());
- }
-}
-
-void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
-{
- // Invalidate types of the already stored candidate icons because it might differ
- // among pages.
- for (FaviconInfo candidateFaviconInfo : candidates) {
- const QUrl &candidateUrl = candidateFaviconInfo.url;
- if (m_faviconInfoMap.contains(candidateUrl))
- m_faviconInfoMap[candidateUrl].type = FaviconInfo::InvalidIcon;
- }
-
- m_candidateCount = candidates.count();
- for (FaviconInfo candidateFaviconInfo : candidates) {
- const QUrl &candidateUrl = candidateFaviconInfo.url;
-
- if (!m_faviconInfoMap.contains(candidateUrl))
- m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
- else {
- // The same icon URL can be used for different types.
- m_faviconInfoMap[candidateUrl].type |= candidateFaviconInfo.type;
- }
-
- m_faviconInfoMap[candidateUrl].candidate = true;
- }
-}
-
-void FaviconManager::resetCandidates()
-{
- // Interrupt in progress icon downloads
- m_pendingRequests.clear();
- m_inProgressRequests.clear();
-
- m_candidateCount = 0;
- m_candidateIcon = QIcon();
- for (auto it = m_faviconInfoMap.begin(), end = m_faviconInfoMap.end(); it != end; ++it)
- it->candidate = false;
-}
-
-bool FaviconManager::hasCandidate() const
-{
- return (m_candidateCount > 0);
-}
-
-QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const
-{
- QUrl iconUrl;
- const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
-
- unsigned bestArea = 0;
- for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
- continue;
-
- if (it->isValid() && bestArea < area(it->size)) {
- iconUrl = it->url;
- bestArea = area(it->size);
- }
- }
-
- return iconUrl;
-}
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-static QPixmap getUnscaledPixmap(QIcon icon, const QSize &size)
-{
- QPixmap pixmap = icon.data_ptr()->engine->pixmap(size, QIcon::Normal, QIcon::Off);
- pixmap.setDevicePixelRatio(1.0);
- return pixmap;
-}
-#else
-static QPixmap getUnscaledPixmap(const QIcon &icon, const QSize &size)
-{
- return icon.pixmap(size, 1.0);
-}
-#endif
-
-void FaviconManager::generateCandidateIcon(bool touchIconsEnabled)
-{
- Q_ASSERT(m_candidateCount);
-
- m_candidateIcon = QIcon();
- const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
-
- for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
- continue;
-
- if (!it->isValid() || !it->isDownloaded())
- continue;
-
- const QIcon &icon = getIcon(it->url);
-
- if (!it->multiSize) {
- if (!m_candidateIcon.availableSizes().contains(it->size))
- m_candidateIcon.addPixmap(getUnscaledPixmap(icon, it->size));
-
- continue;
- }
-
- const auto sizes = icon.availableSizes();
- for (const QSize &size : sizes) {
- if (!m_candidateIcon.availableSizes().contains(size))
- m_candidateIcon.addPixmap(getUnscaledPixmap(icon, size));
- }
- }
-}
-
-void FaviconManager::copyStateFrom(FaviconManager *source)
-{
- m_faviconInfoMap = source->m_faviconInfoMap;
- m_icons = source->m_icons;
-}
-
-FaviconInfo::FaviconInfo()
- : url(QUrl())
- , type(FaviconInfo::InvalidIcon)
- , size(QSize(0, 0))
- , candidate(false)
- , multiSize(false)
-{
-}
-
-FaviconInfo::FaviconInfo(const FaviconInfo &other)
- : url(other.url)
- , type(other.type)
- , size(other.size)
- , candidate(other.candidate)
- , multiSize(other.multiSize)
-{
-}
-
-FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconTypeFlags type)
- : url(url)
- , type(type)
- , size(QSize(0, 0))
- , candidate(false)
- , multiSize(false)
-{
-}
-
-FaviconInfo::~FaviconInfo()
-{
-}
-
-bool FaviconInfo::isValid() const
-{
- if (type == FaviconInfo::InvalidIcon)
- return false;
-
- if (url.isEmpty() || !url.isValid())
- return false;
-
- return true;
-}
-
-bool FaviconInfo::isDownloaded() const
-{
- return area(size) > 0;
-}
-
-} // namespace QtWebEngineCore