summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2020-06-19 11:17:50 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-06-28 11:52:05 +0000
commitd411328f2a7ff9993bcce5b1db74280a39c90981 (patch)
tree2b9ccabfa204ce5796c20e8f90c99b577e1a7154 /src/core
parent45099f1e9e51aeec2266c46b63fa1ecf8670be5a (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.cpp9
-rw-r--r--src/core/api/qwebengineprofile.cpp66
-rw-r--r--src/core/api/qwebengineprofile.h3
-rw-r--r--src/core/profile_adapter.cpp99
-rw-r--r--src/core/profile_adapter.h11
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)
};