diff options
author | Peter Varga <pvarga@inf.u-szeged.hu> | 2020-06-19 11:17:50 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-06-28 11:52:05 +0000 |
commit | d411328f2a7ff9993bcce5b1db74280a39c90981 (patch) | |
tree | 2b9ccabfa204ce5796c20e8f90c99b577e1a7154 /src/core | |
parent | 45099f1e9e51aeec2266c46b63fa1ecf8670be5a (diff) |
Add API for favicon database
[ChangeLog][QtWebEngineCore][QWebEngineProfile] Add new API
to access icon database asynchronously.
[ChangeLog][QtWebEngineQuick] image:/favicon/ URLs now can be used to access
icon database.
Task-number: QTBUG-51184
Change-Id: I6096ad9a4210670ed59458c4fa099a02595e8a1e
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
(cherry picked from commit 2ad450018e8ae22f4c426a421fa5c0995feb1e16)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/api/qwebenginepage.cpp | 9 | ||||
-rw-r--r-- | src/core/api/qwebengineprofile.cpp | 66 | ||||
-rw-r--r-- | src/core/api/qwebengineprofile.h | 3 | ||||
-rw-r--r-- | src/core/profile_adapter.cpp | 99 | ||||
-rw-r--r-- | src/core/profile_adapter.h | 11 |
5 files changed, 184 insertions, 4 deletions
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 3028c38f5..12dcc867b 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -1987,11 +1987,12 @@ QUrl QWebEnginePage::iconUrl() const \brief The icon associated with the page currently viewed. \since 5.7 - By default, this property contains a null icon. If the web page specifies more than one icon, - the \c{icon} property encapsulates the available candidate icons in a single, - scalable \c{QIcon}. + By default, this property contains a null icon. If touch icons are disabled + (see \c QWebEngineSettings::TouchIconsEnabled), the favicon is provided in two sizes + (16x16 and 32x32 pixels) encapsulated in \c{QIcon}. Otherwise, single icon is provided + with the largest available size. - \sa iconChanged(), iconUrl(), iconUrlChanged() + \sa iconChanged(), iconUrl(), iconUrlChanged(), QWebEngineSettings::TouchIconsEnabled */ QIcon QWebEnginePage::icon() const { diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index 4074a4c31..13ad0f992 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -873,4 +873,70 @@ QWebEngineClientCertificateStore *QWebEngineProfile::clientCertificateStore() #endif } +/*! + * Requests an icon for a previously loaded page with this profile from the database. Each profile + * has its own icon database and it is stored in the persistent storage thus the stored icons + * can be accessed without network connection too. The icon must be previously loaded to be + * stored in the database. + * + * \a url specifies the URL of the page what the icon is requested for. In case of more than one + * available icons the one with the size closest to \a desiredSizeInPixel will be returned. + * The result icon is resized to \a desiredSizeInPixel. If desiredSizeInPixel is 0 the largest + * available icon is returned. + * + * This function is asynchronous and the result is returned by \a iconAvailableCallback. + * The callback is called if a request for an icon is performed. If the requested icon is + * available, the first parameter (with type QIcon) is the result. Otherwise, it is null. + * + * The second parameter stores the URL of the requested icon. It is empty if the icon can't be + * fetched. + * + * The third parameter stores the URL of the page which the icon is assigned. + * + * \note Icons can't be requested with an off-the-record profile. + * + * \since 6.2 + * \sa requestIconForIconURL() + */ +void QWebEngineProfile::requestIconForPageURL(const QUrl &url, int desiredSizeInPixel, + std::function<void(const QIcon &, const QUrl &, const QUrl &)> iconAvailableCallback) const +{ + Q_D(const QWebEngineProfile); + d->profileAdapter()->requestIconForPageURL(url, desiredSizeInPixel, + settings()->testAttribute(QWebEngineSettings::TouchIconsEnabled), + iconAvailableCallback); +} + +/*! + * Requests an icon with the specified \a url from the database. Each profile has its + * own icon database and it is stored in the persistent storage thus the stored icons + * can be accessed without network connection too. The icon must be previously loaded to be + * stored in the database. + * + * \a url specifies the URL of the icon. In case of more than one + * available icons the one with the size closest to \a desiredSizeInPixel will be returned. + * The result icon is resized to \a desiredSizeInPixel. If desiredSizeInPixel is 0 the largest + * available icon is returned. + * + * This function is asynchronous and the result is returned by \a iconAvailableCallback. + * The callback is called if a request for an icon is performed. If the requested icon is + * available, the first parameter (with type QIcon) is the result. Otherwise, it is null. + * + * The second parameter stores the URL of the requested icon. It is empty if the icon can't be + * fetched. + * + * \note Icons can't be requested with an off-the-record profile. + * + * \since 6.2 + * \sa requestIconForPageURL() + */ +void QWebEngineProfile::requestIconForIconURL(const QUrl &url, int desiredSizeInPixel, + std::function<void(const QIcon &, const QUrl &)> iconAvailableCallback) const +{ + Q_D(const QWebEngineProfile); + d->profileAdapter()->requestIconForIconURL(url, desiredSizeInPixel, + settings()->testAttribute(QWebEngineSettings::TouchIconsEnabled), + iconAvailableCallback); +} + QT_END_NAMESPACE diff --git a/src/core/api/qwebengineprofile.h b/src/core/api/qwebengineprofile.h index 63ac3a9b9..618576664 100644 --- a/src/core/api/qwebengineprofile.h +++ b/src/core/api/qwebengineprofile.h @@ -142,6 +142,9 @@ public: QWebEngineClientCertificateStore *clientCertificateStore(); + void requestIconForPageURL(const QUrl &url, int desiredSizeInPixel, std::function<void(const QIcon &, const QUrl &, const QUrl &)> iconAvailableCallback) const; + void requestIconForIconURL(const QUrl &url, int desiredSizeInPixel, std::function<void(const QIcon &, const QUrl &)> iconAvailableCallback) const; + static QWebEngineProfile *defaultProfile(); Q_SIGNALS: diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 204974c28..0072eea50 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -39,6 +39,7 @@ #include "profile_adapter.h" +#include "base/task/cancelable_task_tracker.h" #include "components/favicon/core/favicon_service.h" #include "components/history/content/browser/history_database_helper.h" #include "components/history/core/browser/history_database_params.h" @@ -125,6 +126,7 @@ ProfileAdapter::ProfileAdapter(const QString &storageName): std::vector<network::mojom::CorsOriginPatternPtr> list; list.push_back(std::move(pattern)); m_profile->GetSharedCorsOriginAccessList()->SetForOrigin(qrc, std::move(list), {}, base::BindOnce([]{})); + m_cancelableTaskTracker.reset(new base::CancelableTaskTracker()); } ProfileAdapter::~ProfileAdapter() @@ -747,4 +749,101 @@ QWebEngineClientCertificateStore *ProfileAdapter::clientCertificateStore() } #endif +static void callbackOnIconAvailableForPageURL(std::function<void (const QIcon &, const QUrl &, const QUrl &)> iconAvailableCallback, + const QUrl &pageUrl, + const favicon_base::FaviconRawBitmapResult &result) +{ + if (!result.is_valid()) { + iconAvailableCallback(QIcon(), toQt(result.icon_url), pageUrl); + return; + } + QPixmap pixmap(toQt(result.pixel_size)); + pixmap.loadFromData(result.bitmap_data->data(), result.bitmap_data->size()); + iconAvailableCallback(QIcon(pixmap), toQt(result.icon_url), pageUrl); +} + +void ProfileAdapter::requestIconForPageURL(const QUrl &pageUrl, + int desiredSizeInPixel, + bool touchIconsEnabled, + std::function<void (const QIcon &, const QUrl &, const QUrl &)> iconAvailableCallback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + favicon::FaviconService *service = FaviconServiceFactoryQt::GetForBrowserContext(m_profile.data()); + + if (!service->HistoryService()) { + callbackOnIconAvailableForPageURL(iconAvailableCallback, pageUrl, + favicon_base::FaviconRawBitmapResult()); + return; + } + + favicon_base::IconTypeSet types = { favicon_base::IconType::kFavicon }; + if (touchIconsEnabled) { + types.insert(favicon_base::IconType::kTouchIcon); + types.insert(favicon_base::IconType::kTouchPrecomposedIcon); + types.insert(favicon_base::IconType::kWebManifestIcon); + } + service->GetRawFaviconForPageURL( + toGurl(pageUrl), types, desiredSizeInPixel, true /* fallback_to_host */, + base::BindOnce(&callbackOnIconAvailableForPageURL, iconAvailableCallback, pageUrl), + m_cancelableTaskTracker.get()); +} + +static void callbackOnIconAvailableForIconURL(std::function<void (const QIcon &, const QUrl &)> iconAvailableCallback, + ProfileAdapter *profileAdapter, + const QUrl &iconUrl, int iconType, + int desiredSizeInPixel, + bool touchIconsEnabled, + const favicon_base::FaviconRawBitmapResult &result) +{ + if (!result.is_valid()) { + // If touch icons are disabled there is no need to try further icon types. + if (!touchIconsEnabled) { + iconAvailableCallback(QIcon(), iconUrl); + return; + } + if (static_cast<favicon_base::IconType>(iconType) != favicon_base::IconType::kMax) { + //Q_ASSERT(profileAdapter->profile()); + favicon::FaviconService *service = FaviconServiceFactoryQt::GetForBrowserContext(profileAdapter->profile()); + service->GetRawFavicon(toGurl(iconUrl), + static_cast<favicon_base::IconType>(iconType + 1), + desiredSizeInPixel, + base::BindOnce(&callbackOnIconAvailableForIconURL, iconAvailableCallback, + profileAdapter, iconUrl, iconType + 1, desiredSizeInPixel, + touchIconsEnabled), + profileAdapter->cancelableTaskTracker()); + return; + } + iconAvailableCallback(QIcon(), iconUrl); + return; + } + QPixmap pixmap(toQt(result.pixel_size)); + pixmap.loadFromData(result.bitmap_data->data(), result.bitmap_data->size()); + iconAvailableCallback(QIcon(pixmap), toQt(result.icon_url)); +} + +void ProfileAdapter::requestIconForIconURL(const QUrl &iconUrl, + int desiredSizeInPixel, + bool touchIconsEnabled, + std::function<void (const QIcon &, const QUrl &)> iconAvailableCallback) +{ + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + favicon::FaviconService *service = FaviconServiceFactoryQt::GetForBrowserContext(m_profile.data()); + + if (!service->HistoryService()) { + callbackOnIconAvailableForIconURL(iconAvailableCallback, + this, + iconUrl, + static_cast<int>(favicon_base::IconType::kMax), 0, + touchIconsEnabled, + favicon_base::FaviconRawBitmapResult()); + return; + } + service->GetRawFavicon( + toGurl(iconUrl), favicon_base::IconType::kFavicon, desiredSizeInPixel, + base::BindOnce(&callbackOnIconAvailableForIconURL, iconAvailableCallback, this, iconUrl, + static_cast<int>(favicon_base::IconType::kFavicon), desiredSizeInPixel, + touchIconsEnabled), + m_cancelableTaskTracker.get()); +} + } // namespace QtWebEngineCore diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h index 979316b4a..d88834d7c 100644 --- a/src/core/profile_adapter.h +++ b/src/core/profile_adapter.h @@ -67,6 +67,10 @@ QT_FORWARD_DECLARE_CLASS(QObject) +namespace base { +class CancelableTaskTracker; +} + namespace QtWebEngineCore { class UserNotificationController; @@ -215,6 +219,12 @@ public: QString determineDownloadPath(const QString &downloadDirectory, const QString &suggestedFilename, const time_t &startTime); + void requestIconForPageURL(const QUrl &pageUrl, int desiredSizeInPixel, bool touchIconsEnabled, + std::function<void (const QIcon &, const QUrl &, const QUrl &)> iconAvailableCallback); + void requestIconForIconURL(const QUrl &iconUrl, int desiredSizeInPixel, bool touchIconsEnabled, + std::function<void (const QIcon &, const QUrl &)> iconAvailableCallback); + base::CancelableTaskTracker *cancelableTaskTracker() { return m_cancelableTaskTracker.get(); } + static QPointer<ProfileAdapter> s_profileForGlobalCertificateVerification; private: void updateCustomUrlSchemeHandlers(); @@ -251,6 +261,7 @@ private: QList<WebContentsAdapterClient *> m_webContentsAdapterClients; int m_httpCacheMaxSize; QrcUrlSchemeHandler m_qrcHandler; + std::unique_ptr<base::CancelableTaskTracker> m_cancelableTaskTracker; Q_DISABLE_COPY(ProfileAdapter) }; |