diff options
Diffstat (limited to 'src/core/favicon_manager.cpp')
-rw-r--r-- | src/core/favicon_manager.cpp | 437 |
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 |