summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPeter Varga <pvarga@inf.u-szeged.hu>2020-06-19 11:17:50 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-06-04 18:41:41 +0200
commit881339e9d9054c46f2621119246de7a13c83761a (patch)
tree77db7d7188c4ac61cab939c2ccd7a9610d4a01f4 /src
parent4d67b9f639114ddec0521980495ba27921800e39 (diff)
Replace FaviconManager with Chromium's Favicon Component
Task-number: QTBUG-51184 Change-Id: Ie050cb23f2c86841a66ec384bfbcdf0713cffa7c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt3
-rw-r--r--src/core/api/qwebenginepage.cpp5
-rw-r--r--src/core/content_browser_client_qt.cpp1
-rw-r--r--src/core/extensions/plugin_service_filter_qt.cpp1
-rw-r--r--src/core/favicon_driver_qt.cpp407
-rw-r--r--src/core/favicon_driver_qt.h168
-rw-r--r--src/core/favicon_manager.cpp437
-rw-r--r--src/core/favicon_manager.h151
-rw-r--r--src/core/favicon_service_factory_qt.cpp193
-rw-r--r--src/core/favicon_service_factory_qt.h146
-rw-r--r--src/core/net/plugin_response_interceptor_url_loader_throttle.cpp1
-rw-r--r--src/core/profile_adapter.cpp33
-rw-r--r--src/core/profile_adapter.h1
-rw-r--r--src/core/profile_qt.cpp18
-rw-r--r--src/core/profile_qt.h1
-rw-r--r--src/core/qtwebengine.gni2
-rw-r--r--src/core/type_conversion.cpp46
-rw-r--r--src/core/type_conversion.h5
-rw-r--r--src/core/visited_links_manager_qt.cpp17
-rw-r--r--src/core/web_contents_adapter.cpp28
-rw-r--r--src/core/web_contents_adapter.h2
-rw-r--r--src/core/web_contents_delegate_qt.cpp29
-rw-r--r--src/core/web_contents_delegate_qt.h4
-rw-r--r--src/core/web_engine_library_info.cpp1
-rw-r--r--src/webenginequick/api/qquickwebenginefaviconprovider.cpp184
-rw-r--r--src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h19
-rw-r--r--src/webenginequick/api/qquickwebengineview.cpp31
-rw-r--r--src/webenginequick/api/qquickwebengineview_p.h1
-rw-r--r--src/webenginequick/api/qquickwebengineview_p_p.h2
29 files changed, 1104 insertions, 833 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2a545f5b2..b32415028 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -91,7 +91,8 @@ foreach(config ${configs})
devtools_frontend_qt.cpp devtools_frontend_qt.h
devtools_manager_delegate_qt.cpp devtools_manager_delegate_qt.h
download_manager_delegate_qt.cpp download_manager_delegate_qt.h
- favicon_manager.cpp favicon_manager.h
+ favicon_driver_qt.cpp favicon_driver_qt.h
+ favicon_service_factory_qt.cpp favicon_service_factory_qt.h
file_picker_controller.cpp file_picker_controller.h
find_text_helper.cpp find_text_helper.h
global_descriptors_qt.h
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index 6e2b37514..64b4f4d99 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -44,7 +44,6 @@
#include "authentication_dialog_controller.h"
#include "profile_adapter.h"
#include "color_chooser_controller.h"
-#include "favicon_manager.h"
#include "find_text_helper.h"
#include "file_picker_controller.h"
#include "javascript_dialog_controller.h"
@@ -255,7 +254,7 @@ void QWebEnginePagePrivate::iconChanged(const QUrl &url)
return;
iconUrl = url;
Q_EMIT q->iconUrlChanged(iconUrl);
- Q_EMIT q->iconChanged(adapter->faviconManager()->getIcon());
+ Q_EMIT q->iconChanged(iconUrl.isEmpty() ? QIcon() : adapter->icon());
}
void QWebEnginePagePrivate::loadProgressChanged(int progress)
@@ -1980,7 +1979,7 @@ QIcon QWebEnginePage::icon() const
if (d->iconUrl.isEmpty() || !d->adapter->isInitialized())
return QIcon();
- return d->adapter->faviconManager()->getIcon();
+ return d->adapter->icon();
}
qreal QWebEnginePage::zoomFactor() const
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index d68cad2b0..fdcd98024 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -113,6 +113,7 @@
#include "web_contents_view_qt.h"
#include "web_engine_context.h"
#include "web_engine_library_info.h"
+#include "web_engine_settings.h"
#include "api/qwebenginecookiestore.h"
#include "api/qwebenginecookiestore_p.h"
diff --git a/src/core/extensions/plugin_service_filter_qt.cpp b/src/core/extensions/plugin_service_filter_qt.cpp
index 94cf5cb27..778f803c3 100644
--- a/src/core/extensions/plugin_service_filter_qt.cpp
+++ b/src/core/extensions/plugin_service_filter_qt.cpp
@@ -43,6 +43,7 @@
#include "content/public/browser/web_contents.h"
#include "web_contents_delegate_qt.h"
+#include "web_engine_settings.h"
using namespace QtWebEngineCore;
diff --git a/src/core/favicon_driver_qt.cpp b/src/core/favicon_driver_qt.cpp
new file mode 100644
index 000000000..a3bbd5939
--- /dev/null
+++ b/src/core/favicon_driver_qt.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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_driver_qt.h"
+#include "type_conversion.h"
+#include "web_contents_adapter_client.h"
+#include "web_engine_settings.h"
+
+#include "components/favicon/content/favicon_url_util.h"
+#include "components/favicon/core/favicon_service.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+
+namespace QtWebEngineCore {
+
+namespace {
+
+void ExtractManifestIcons(FaviconDriverQt::ManifestDownloadCallback callback,
+ const GURL &manifest_url, const blink::Manifest &manifest)
+{
+ std::vector<favicon::FaviconURL> candidates;
+ for (const auto &icon : manifest.icons) {
+ candidates.emplace_back(icon.src, favicon_base::IconType::kWebManifestIcon, icon.sizes);
+ }
+ std::move(callback).Run(candidates);
+}
+
+int activeHandlersCount(QWebEngineSettings *settings)
+{
+ bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
+ return touchIconsEnabled ? 2 : 1;
+}
+
+} // namespace
+
+FaviconStatusQt::FaviconStatusQt()
+ : FaviconStatus(), source(favicon::FaviconDriverObserver::NON_TOUCH_16_DIP)
+{
+}
+
+// static
+void FaviconDriverQt::CreateForWebContents(content::WebContents *webContents,
+ favicon::FaviconService *faviconService,
+ WebContentsAdapterClient *viewClient)
+{
+ if (FromWebContents(webContents))
+ return;
+
+ webContents->SetUserData(
+ UserDataKey(),
+ base::WrapUnique(new FaviconDriverQt(webContents, faviconService, viewClient)));
+}
+
+FaviconDriverQt::FaviconDriverQt(content::WebContents *webContents,
+ favicon::FaviconService *faviconService,
+ WebContentsAdapterClient *viewClient)
+ : content::WebContentsObserver(webContents)
+ , m_faviconService(faviconService)
+ , m_viewClient(viewClient)
+{
+ if (!m_faviconService)
+ return;
+
+ m_handlers.push_back(std::make_unique<favicon::FaviconHandler>(
+ m_faviconService, this, favicon::FaviconDriverObserver::NON_TOUCH_16_DIP));
+ m_handlers.push_back(std::make_unique<favicon::FaviconHandler>(
+ m_faviconService, this, favicon::FaviconDriverObserver::NON_TOUCH_LARGEST));
+ m_handlers.push_back(std::make_unique<favicon::FaviconHandler>(
+ m_faviconService, this, favicon::FaviconDriverObserver::TOUCH_LARGEST));
+}
+
+void FaviconDriverQt::FetchFavicon(const GURL &page_url, bool is_same_document)
+{
+ QWebEngineSettings *settings = m_viewClient->webEngineSettings();
+ bool iconsEnabled = settings->testAttribute(QWebEngineSettings::AutoLoadIconsForPage);
+ bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
+
+ if (!iconsEnabled)
+ return;
+
+ for (const std::unique_ptr<favicon::FaviconHandler> &handler : m_handlers) {
+ switch (handler->Type()) {
+ case favicon::FaviconDriverObserver::NON_TOUCH_16_DIP:
+ if (touchIconsEnabled)
+ continue;
+ break;
+ case favicon::FaviconDriverObserver::NON_TOUCH_LARGEST:
+ case favicon::FaviconDriverObserver::TOUCH_LARGEST:
+ if (!touchIconsEnabled)
+ continue;
+ break;
+ }
+
+ handler->FetchFavicon(page_url, is_same_document);
+ }
+}
+
+gfx::Image FaviconDriverQt::GetFavicon() const
+{
+ // Like GetTitle(), we also want to use the favicon for the last committed
+ // entry rather than a pending navigation entry.
+ content::NavigationController &controller = web_contents()->GetController();
+
+ content::NavigationEntry *entry = controller.GetLastCommittedEntry();
+ if (entry)
+ return entry->GetFavicon().image;
+ return gfx::Image();
+}
+
+bool FaviconDriverQt::FaviconIsValid() const
+{
+ content::NavigationController &controller = web_contents()->GetController();
+
+ content::NavigationEntry *entry = controller.GetLastCommittedEntry();
+ if (entry)
+ return entry->GetFavicon().valid;
+
+ return false;
+}
+
+GURL FaviconDriverQt::GetActiveURL()
+{
+ content::NavigationEntry *entry = web_contents()->GetController().GetLastCommittedEntry();
+ return entry ? entry->GetURL() : GURL();
+}
+
+GURL FaviconDriverQt::GetFaviconURL() const
+{
+ content::NavigationController &controller = web_contents()->GetController();
+
+ content::NavigationEntry *entry = controller.GetLastCommittedEntry();
+ if (entry)
+ return entry->GetFavicon().url;
+ return GURL();
+}
+
+int FaviconDriverQt::DownloadImage(const GURL &url, int max_image_size,
+ ImageDownloadCallback callback)
+{
+ bool bypass_cache = (m_bypassCachePageURL == GetActiveURL());
+ m_bypassCachePageURL = GURL();
+
+ return web_contents()->DownloadImage(url, true, /*preferred_size=*/max_image_size,
+ /*max_bitmap_size=*/max_image_size, bypass_cache,
+ std::move(callback));
+}
+
+void FaviconDriverQt::DownloadManifest(const GURL &url, ManifestDownloadCallback callback)
+{
+ web_contents()->GetManifest(base::BindOnce(&ExtractManifestIcons, std::move(callback)));
+}
+
+bool FaviconDriverQt::IsOffTheRecord()
+{
+ DCHECK(web_contents());
+ return web_contents()->GetBrowserContext()->IsOffTheRecord();
+}
+
+void FaviconDriverQt::OnFaviconUpdated(
+ const GURL &page_url,
+ favicon::FaviconDriverObserver::NotificationIconType notification_icon_type,
+ const GURL &icon_url, bool icon_url_changed, const gfx::Image &image)
+{
+ Q_UNUSED(page_url);
+
+ QWebEngineSettings *settings = m_viewClient->webEngineSettings();
+ bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
+
+ // Prefer touch icons over favicons if touch icons are enabled.
+ if (!touchIconsEnabled
+ || m_latestFavicon.source != favicon::FaviconDriverObserver::TOUCH_LARGEST
+ || notification_icon_type == favicon::FaviconDriverObserver::TOUCH_LARGEST) {
+ m_latestFavicon.valid = true;
+ m_latestFavicon.url = icon_url;
+ m_latestFavicon.image = image;
+ m_latestFavicon.source = notification_icon_type;
+ }
+
+ NotifyFaviconUpdatedObservers(notification_icon_type, icon_url, icon_url_changed, image);
+ emitIconChangedIfNeeded();
+}
+
+void FaviconDriverQt::OnFaviconDeleted(
+ const GURL &page_url,
+ favicon::FaviconDriverObserver::NotificationIconType notification_icon_type)
+{
+ content::NavigationEntry *entry = web_contents()->GetController().GetLastCommittedEntry();
+ DCHECK(entry && entry->GetURL() == page_url);
+
+ entry->GetFavicon() = FaviconStatusQt();
+ web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB);
+
+ NotifyFaviconUpdatedObservers(notification_icon_type, /*icon_url=*/GURL(),
+ /*icon_url_changed=*/true, FaviconStatusQt().image);
+}
+
+void FaviconDriverQt::OnHandlerCompleted(favicon::FaviconHandler *handler)
+{
+ Q_UNUSED(handler);
+
+ if (activeHandlersCount(m_viewClient->webEngineSettings()) > m_completedHandlersCount)
+ ++m_completedHandlersCount;
+ emitIconChangedIfNeeded();
+}
+
+void FaviconDriverQt::DidUpdateFaviconURL(
+ content::RenderFrameHost *render_frame_host,
+ const std::vector<blink::mojom::FaviconURLPtr> &candidates)
+{
+ Q_UNUSED(render_frame_host);
+
+ // Ignore the update if there is no last committed navigation entry. This can
+ // occur when loading an initially blank page.
+ content::NavigationEntry *entry = web_contents()->GetController().GetLastCommittedEntry();
+ if (!entry)
+ return;
+
+ // We update |m_faviconUrls| even if the list is believed to be partial
+ // (checked below), because callers of our getter favicon_urls() expect so.
+ std::vector<blink::mojom::FaviconURL> faviconUrls;
+ for (const auto &candidate : candidates)
+ faviconUrls.push_back(*candidate);
+ m_faviconUrls = faviconUrls;
+
+ if (!m_documentOnLoadCompleted)
+ return;
+
+ OnUpdateCandidates(entry->GetURL(),
+ favicon::FaviconURLsFromContentFaviconURLs(
+ m_faviconUrls.value_or(std::vector<blink::mojom::FaviconURL>())),
+ m_manifestUrl);
+}
+
+void FaviconDriverQt::DidUpdateWebManifestURL(content::RenderFrameHost *target_frame,
+ const base::Optional<GURL> &manifest_url)
+{
+ Q_UNUSED(target_frame);
+
+ // Ignore the update if there is no last committed navigation entry. This can
+ // occur when loading an initially blank page.
+ content::NavigationEntry *entry = web_contents()->GetController().GetLastCommittedEntry();
+ if (!entry || !m_documentOnLoadCompleted)
+ return;
+
+ m_manifestUrl = manifest_url.value_or(GURL());
+
+ // On regular page loads, DidUpdateManifestURL() is guaranteed to be called
+ // before DidUpdateFaviconURL(). However, a page can update the favicons via
+ // javascript.
+ if (m_faviconUrls.has_value()) {
+ OnUpdateCandidates(entry->GetURL(),
+ favicon::FaviconURLsFromContentFaviconURLs(*m_faviconUrls),
+ m_manifestUrl);
+ }
+}
+
+void FaviconDriverQt::DidStartNavigation(content::NavigationHandle *navigation_handle)
+{
+ if (!navigation_handle->IsInMainFrame())
+ return;
+
+ m_faviconUrls.reset();
+ m_completedHandlersCount = 0;
+ m_latestFavicon = FaviconStatusQt();
+
+ if (!navigation_handle->IsSameDocument()) {
+ m_documentOnLoadCompleted = false;
+ m_manifestUrl = GURL();
+ }
+
+ m_viewClient->iconChanged(QUrl());
+
+ content::ReloadType reload_type = navigation_handle->GetReloadType();
+ if (reload_type == content::ReloadType::NONE || IsOffTheRecord())
+ return;
+
+ m_bypassCachePageURL = navigation_handle->GetURL();
+ SetFaviconOutOfDateForPage(navigation_handle->GetURL(),
+ reload_type == content::ReloadType::BYPASSING_CACHE);
+}
+
+void FaviconDriverQt::DidFinishNavigation(content::NavigationHandle *navigation_handle)
+{
+ if (!navigation_handle->IsInMainFrame() || !navigation_handle->HasCommitted()
+ || navigation_handle->IsErrorPage()) {
+ return;
+ }
+
+ // Wait till the user navigates to a new URL to start checking the cache
+ // again. The cache may be ignored for non-reload navigations (e.g.
+ // history.replace() in-page navigation). This is allowed to increase the
+ // likelihood that "reloading a page ignoring the cache" redownloads the
+ // favicon. In particular, a page may do an in-page navigation before
+ // FaviconHandler has the time to determine that the favicon needs to be
+ // redownloaded.
+ GURL url = navigation_handle->GetURL();
+ if (url != m_bypassCachePageURL)
+ m_bypassCachePageURL = GURL();
+
+ // Get the favicon, either from history or request it from the net.
+ FetchFavicon(url, navigation_handle->IsSameDocument());
+}
+
+void FaviconDriverQt::DocumentOnLoadCompletedInMainFrame()
+{
+ m_documentOnLoadCompleted = true;
+}
+
+void FaviconDriverQt::SetFaviconOutOfDateForPage(const GURL &url, bool force_reload)
+{
+ if (m_faviconService) {
+ m_faviconService->SetFaviconOutOfDateForPage(url);
+ if (force_reload)
+ m_faviconService->ClearUnableToDownloadFavicons();
+ }
+}
+
+void FaviconDriverQt::OnUpdateCandidates(const GURL &page_url,
+ const std::vector<favicon::FaviconURL> &candidates,
+ const GURL &manifest_url)
+{
+ QWebEngineSettings *settings = m_viewClient->webEngineSettings();
+ bool touchIconsEnabled = settings->testAttribute(QWebEngineSettings::TouchIconsEnabled);
+ for (const std::unique_ptr<favicon::FaviconHandler> &handler : m_handlers) {
+ switch (handler->Type()) {
+ case favicon::FaviconDriverObserver::NON_TOUCH_16_DIP:
+ if (touchIconsEnabled)
+ continue;
+ break;
+ case favicon::FaviconDriverObserver::NON_TOUCH_LARGEST:
+ case favicon::FaviconDriverObserver::TOUCH_LARGEST:
+ if (!touchIconsEnabled)
+ continue;
+ break;
+ }
+
+ // We feed in the Web Manifest URL (if any) to the instance handling type
+ // kWebManifestIcon, because those compete which each other (i.e. manifest
+ // icons override inline touch icons).
+ handler->OnUpdateCandidates(
+ page_url, candidates,
+ (handler->icon_types().count(favicon_base::IconType::kWebManifestIcon) != 0)
+ ? manifest_url
+ : GURL::EmptyGURL());
+ }
+}
+
+void FaviconDriverQt::emitIconChangedIfNeeded()
+{
+ if (activeHandlersCount(m_viewClient->webEngineSettings()) != m_completedHandlersCount)
+ return;
+
+ content::NavigationEntry *entry = web_contents()->GetController().GetLastCommittedEntry();
+ DCHECK(entry);
+
+ if (entry->GetFavicon().url != m_latestFavicon.url) {
+ entry->GetFavicon().valid = m_latestFavicon.valid;
+ entry->GetFavicon().url = m_latestFavicon.url;
+ entry->GetFavicon().image = m_latestFavicon.image;
+ web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB);
+ }
+
+ m_viewClient->iconChanged(toQt(m_latestFavicon.url));
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(FaviconDriverQt)
+
+} // namespace QtWebEngineCore
diff --git a/src/core/favicon_driver_qt.h b/src/core/favicon_driver_qt.h
new file mode 100644
index 000000000..b49017946
--- /dev/null
+++ b/src/core/favicon_driver_qt.h
@@ -0,0 +1,168 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FAVICON_DRIVER_QT_H
+#define FAVICON_DRIVER_QT_H
+
+#include "qtwebenginecoreglobal_p.h"
+
+#include "components/favicon/core/favicon_driver.h"
+#include "components/favicon/core/favicon_handler.h"
+#include "content/public/browser/favicon_status.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
+
+namespace content {
+class WebContents;
+}
+
+namespace favicon {
+class FaviconService;
+}
+
+namespace QtWebEngineCore {
+
+class WebContentsAdapterClient;
+
+struct FaviconStatusQt : public content::FaviconStatus
+{
+ FaviconStatusQt();
+
+ // Type of the favicon::FaviconHandler that provided this icon.
+ favicon::FaviconDriverObserver::NotificationIconType source;
+};
+
+class FaviconDriverQt : public favicon::FaviconDriver,
+ public favicon::FaviconHandler::Delegate,
+ public content::WebContentsObserver,
+ public content::WebContentsUserData<FaviconDriverQt>
+{
+public:
+ static void CreateForWebContents(content::WebContents *webContents,
+ favicon::FaviconService *faviconService,
+ WebContentsAdapterClient *viewClient);
+
+ // FaviconDriver implementation.
+ void FetchFavicon(const GURL &page_url, bool is_same_document) override;
+ gfx::Image GetFavicon() const override;
+ bool FaviconIsValid() const override;
+ GURL GetActiveURL() override;
+
+ GURL GetFaviconURL() const;
+
+protected:
+ FaviconDriverQt(content::WebContents *webContent, favicon::FaviconService *faviconService,
+ WebContentsAdapterClient *viewClient);
+
+private:
+ friend class content::WebContentsUserData<FaviconDriverQt>;
+
+ // FaviconHandler::Delegate implementation.
+ int DownloadImage(const GURL &url, int max_image_size, ImageDownloadCallback callback) override;
+ void DownloadManifest(const GURL &url, ManifestDownloadCallback callback) override;
+ bool IsOffTheRecord() override;
+ void OnFaviconUpdated(const GURL &page_url,
+ favicon::FaviconDriverObserver::NotificationIconType icon_type,
+ const GURL &icon_url, bool icon_url_changed,
+ const gfx::Image &image) override;
+ void OnFaviconDeleted(
+ const GURL &page_url,
+ favicon::FaviconDriverObserver::NotificationIconType notification_icon_type) override;
+ void OnHandlerCompleted(favicon::FaviconHandler *handler) override;
+
+ // content::WebContentsObserver implementation.
+ void DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host,
+ const std::vector<blink::mojom::FaviconURLPtr> &candidates) override;
+ void DidUpdateWebManifestURL(content::RenderFrameHost *target_frame,
+ const base::Optional<GURL> &manifest_url) override;
+ void DidStartNavigation(content::NavigationHandle *navigation_handle) override;
+ void DidFinishNavigation(content::NavigationHandle *navigation_handle) override;
+ void DocumentOnLoadCompletedInMainFrame() override;
+
+ // Informs FaviconService that the favicon for |url| is out of date. If
+ // |force_reload| is true, then discard information about favicon download
+ // failures.
+ void SetFaviconOutOfDateForPage(const GURL &url, bool force_reload);
+
+ // Broadcasts new favicon URL candidates to FaviconHandlers.
+ void OnUpdateCandidates(const GURL &page_url,
+ const std::vector<favicon::FaviconURL> &candidates,
+ const GURL &manifest_url);
+
+ void emitIconChangedIfNeeded();
+
+ // KeyedService used by FaviconDriverImpl. It may be null during testing,
+ // but if it is defined, it must outlive the FaviconDriverImpl.
+ favicon::FaviconService *m_faviconService;
+
+ WebContentsAdapterClient *m_viewClient;
+
+ // FaviconHandlers used to download the different kind of favicons.
+ std::vector<std::unique_ptr<favicon::FaviconHandler>> m_handlers;
+
+ GURL m_bypassCachePageURL;
+ bool m_documentOnLoadCompleted = false;
+
+ // nullopt until the actual list is reported via DidUpdateFaviconURL().
+ base::Optional<std::vector<blink::mojom::FaviconURL>> m_faviconUrls;
+ // Web Manifest URL or empty URL if none.
+ GURL m_manifestUrl;
+
+ int m_completedHandlersCount = 0;
+ FaviconStatusQt m_latestFavicon;
+
+ WEB_CONTENTS_USER_DATA_KEY_DECL();
+ DISALLOW_COPY_AND_ASSIGN(FaviconDriverQt);
+};
+
+} // namespace QtWebEngineCore
+
+#endif // FAVICON_DRIVER_QT_H
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
diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h
deleted file mode 100644
index a6e5822a9..000000000
--- a/src/core/favicon_manager.h
+++ /dev/null
@@ -1,151 +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$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#ifndef FAVICON_MANAGER_H
-#define FAVICON_MANAGER_H
-
-#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
-#include <memory>
-#include <QtCore/QMap>
-#include <QtCore/QObject>
-#include <QtCore/QSize>
-#include <QtCore/QUrl>
-#include <QtGui/QIcon>
-
-#include "web_engine_settings.h"
-
-class GURL;
-class SkBitmap;
-
-namespace gfx {
-class Size;
-}
-
-namespace content {
-class WebContents;
-}
-
-namespace base {
-template<class T>
-class WeakPtrFactory;
-}
-
-namespace QtWebEngineCore {
-
-class WebContentsAdapterClient;
-
-// Based on src/3rdparty/chromium/content/public/common/favicon_url.h
-class Q_WEBENGINECORE_PRIVATE_EXPORT FaviconInfo {
-public:
- enum FaviconTypeFlag {
- InvalidIcon = 0,
- Favicon = 1 << 0,
- TouchIcon = 1 << 1,
- TouchPrecomposedIcon = 1 << 2
- };
- Q_DECLARE_FLAGS(FaviconTypeFlags, FaviconTypeFlag)
-
- FaviconInfo();
- FaviconInfo(const FaviconInfo &);
- FaviconInfo(const QUrl &, FaviconInfo::FaviconTypeFlags);
- ~FaviconInfo();
-
- bool isValid() const;
- bool isDownloaded() const;
-
- QUrl url;
- FaviconTypeFlags type;
- // Stores the largest size in case of multi-size icon
- QSize size;
- bool candidate;
- bool multiSize;
-};
-
-
-class Q_WEBENGINECORE_PRIVATE_EXPORT FaviconManager {
-
-public:
- FaviconManager(content::WebContents *, WebContentsAdapterClient *);
- ~FaviconManager();
-
- QIcon getIcon(const QUrl &url = QUrl()) const;
- FaviconInfo getFaviconInfo(const QUrl &) const;
- QList<FaviconInfo> getFaviconInfoList(bool) const;
- void copyStateFrom(FaviconManager *source);
-
-private:
- void update(const QList<FaviconInfo> &);
- void updateCandidates(const QList<FaviconInfo> &);
- void resetCandidates();
- bool hasCandidate() const;
- QUrl candidateIconUrl(bool touchIconsEnabled) const;
- void generateCandidateIcon(bool touchIconsEnabled);
- int downloadIcon(const QUrl &);
- void iconDownloadFinished(int, int, const GURL &, const std::vector<SkBitmap> &, const std::vector<gfx::Size> &);
- void storeIcon(int, const QIcon &);
- void downloadPendingRequests();
- void propagateIcon(const QUrl &) const;
-
-private:
- content::WebContents *m_webContents;
- WebContentsAdapterClient *m_viewClient;
- QMap<QUrl, FaviconInfo> m_faviconInfoMap;
- int m_candidateCount;
- QIcon m_candidateIcon;
- QMap<QUrl, QIcon> m_icons;
- QMap<int, QUrl> m_inProgressRequests;
- QMap<int, QUrl> m_pendingRequests;
- std::unique_ptr<base::WeakPtrFactory<FaviconManager>> m_weakFactory;
- friend class WebContentsDelegateQt;
-};
-
-} // namespace QtWebEngineCore
-
-#endif // FAVICON_MANAGER_H
diff --git a/src/core/favicon_service_factory_qt.cpp b/src/core/favicon_service_factory_qt.cpp
new file mode 100644
index 000000000..898882486
--- /dev/null
+++ b/src/core/favicon_service_factory_qt.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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_service_factory_qt.h"
+
+#include "base/files/file_util.h"
+#include "components/favicon/core/favicon_service_impl.h"
+#include "components/history/content/browser/content_visit_delegate.h"
+#include "components/history/content/browser/history_database_helper.h"
+#include "components/history/core/browser/history_backend_client.h"
+#include "components/history/core/browser/history_database_params.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
+#include "content/public/browser/browser_context.h"
+#include "url/gurl.h"
+
+namespace QtWebEngineCore {
+
+void HistoryClientQt::OnHistoryServiceCreated(history::HistoryService *history_service)
+{
+ Q_UNUSED(history_service);
+}
+
+void HistoryClientQt::Shutdown() { }
+
+bool HistoryClientQt::CanAddURL(const GURL &url)
+{
+ Q_UNUSED(url);
+ return true;
+}
+
+void HistoryClientQt::NotifyProfileError(sql::InitStatus init_status,
+ const std::string &diagnostics)
+{
+ Q_UNUSED(init_status);
+ Q_UNUSED(diagnostics);
+}
+
+std::unique_ptr<history::HistoryBackendClient> HistoryClientQt::CreateBackendClient()
+{
+ return nullptr;
+}
+
+// static
+history::HistoryService *
+HistoryServiceFactoryQt::GetForBrowserContext(content::BrowserContext *context)
+{
+ if (context->IsOffTheRecord())
+ return nullptr;
+
+ if (!base::PathExists(context->GetPath()))
+ return nullptr;
+
+ return static_cast<history::HistoryService *>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+HistoryServiceFactoryQt *HistoryServiceFactoryQt::GetInstance()
+{
+ return base::Singleton<HistoryServiceFactoryQt>::get();
+}
+
+HistoryServiceFactoryQt::HistoryServiceFactoryQt()
+ : BrowserContextKeyedServiceFactory("HistoryService",
+ BrowserContextDependencyManager::GetInstance())
+{
+}
+
+HistoryServiceFactoryQt::~HistoryServiceFactoryQt() { }
+
+content::BrowserContext *
+HistoryServiceFactoryQt::GetBrowserContextToUse(content::BrowserContext *context) const
+{
+ return context;
+}
+
+KeyedService *
+HistoryServiceFactoryQt::BuildServiceInstanceFor(content::BrowserContext *context) const
+{
+ Q_ASSERT(!context->IsOffTheRecord());
+ Q_ASSERT(base::PathExists(context->GetPath()));
+
+ std::unique_ptr<history::HistoryService> historyService(
+ new history::HistoryService(std::make_unique<HistoryClientQt>(), nullptr));
+ if (!historyService->Init(history::HistoryDatabaseParamsForPath(context->GetPath()))) {
+ return nullptr;
+ }
+ return historyService.release();
+}
+
+bool FaviconClientQt::IsNativeApplicationURL(const GURL &url)
+{
+ Q_UNUSED(url);
+ return false;
+}
+
+bool FaviconClientQt::IsReaderModeURL(const GURL &url)
+{
+ Q_UNUSED(url)
+ return false;
+}
+
+const GURL FaviconClientQt::GetOriginalUrlFromReaderModeUrl(const GURL &url)
+{
+ return url;
+}
+
+base::CancelableTaskTracker::TaskId FaviconClientQt::GetFaviconForNativeApplicationURL(
+ const GURL &url, const std::vector<int> &desired_sizes_in_pixel,
+ favicon_base::FaviconResultsCallback callback, base::CancelableTaskTracker *tracker)
+{
+ Q_UNUSED(url);
+ Q_UNUSED(desired_sizes_in_pixel);
+ Q_UNUSED(callback);
+ Q_UNUSED(tracker);
+
+ return base::CancelableTaskTracker::kBadTaskId;
+}
+
+// static
+favicon::FaviconService *
+FaviconServiceFactoryQt::GetForBrowserContext(content::BrowserContext *context)
+{
+ return static_cast<favicon::FaviconService *>(
+ GetInstance()->GetServiceForBrowserContext(context, true));
+}
+
+// static
+FaviconServiceFactoryQt *FaviconServiceFactoryQt::GetInstance()
+{
+ return base::Singleton<FaviconServiceFactoryQt>::get();
+}
+
+FaviconServiceFactoryQt::FaviconServiceFactoryQt()
+ : BrowserContextKeyedServiceFactory("FaviconService",
+ BrowserContextDependencyManager::GetInstance())
+{
+}
+
+FaviconServiceFactoryQt::~FaviconServiceFactoryQt() { }
+
+content::BrowserContext *
+FaviconServiceFactoryQt::GetBrowserContextToUse(content::BrowserContext *context) const
+{
+ return context;
+}
+
+KeyedService *
+FaviconServiceFactoryQt::BuildServiceInstanceFor(content::BrowserContext *context) const
+{
+ history::HistoryService *historyService = static_cast<history::HistoryService *>(
+ HistoryServiceFactoryQt::GetInstance()->GetForBrowserContext(context));
+ return new favicon::FaviconServiceImpl(std::make_unique<FaviconClientQt>(), historyService);
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/favicon_service_factory_qt.h b/src/core/favicon_service_factory_qt.h
new file mode 100644
index 000000000..1ba0db076
--- /dev/null
+++ b/src/core/favicon_service_factory_qt.h
@@ -0,0 +1,146 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 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$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef FAVICON_SERVICE_FACTORY_QT_H
+#define FAVICON_SERVICE_FACTORY_QT_H
+
+#include "qtwebenginecoreglobal_p.h"
+
+#include "base/memory/singleton.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "components/favicon/core/favicon_client.h"
+#include "components/history/core/browser/history_client.h"
+#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
+
+class GURL;
+
+namespace content {
+class BrowserContext;
+}
+
+namespace favicon {
+class FaviconService;
+}
+
+namespace history {
+class HistoryBackendClient;
+class HistoryService;
+}
+
+namespace QtWebEngineCore {
+
+class HistoryClientQt : public history::HistoryClient
+{
+public:
+ HistoryClientQt() { }
+ virtual ~HistoryClientQt() { }
+
+ void OnHistoryServiceCreated(history::HistoryService *history_service) override;
+ void Shutdown() override;
+ bool CanAddURL(const GURL &url) override;
+ void NotifyProfileError(sql::InitStatus init_status, const std::string &diagnostics) override;
+ std::unique_ptr<history::HistoryBackendClient> CreateBackendClient() override;
+};
+
+class HistoryServiceFactoryQt : public BrowserContextKeyedServiceFactory
+{
+public:
+ static history::HistoryService *GetForBrowserContext(content::BrowserContext *context);
+ static HistoryServiceFactoryQt *GetInstance();
+
+private:
+ friend struct base::DefaultSingletonTraits<HistoryServiceFactoryQt>;
+
+ HistoryServiceFactoryQt();
+ ~HistoryServiceFactoryQt() override;
+
+ // BrowserContextKeyedServiceFactory:
+ content::BrowserContext *
+ GetBrowserContextToUse(content::BrowserContext *context) const override;
+ KeyedService *BuildServiceInstanceFor(content::BrowserContext *context) const override;
+};
+
+class FaviconClientQt : public favicon::FaviconClient
+{
+public:
+ FaviconClientQt() { }
+ virtual ~FaviconClientQt() { }
+
+ bool IsNativeApplicationURL(const GURL &url) override;
+ bool IsReaderModeURL(const GURL &url) override;
+ const GURL GetOriginalUrlFromReaderModeUrl(const GURL &url) override;
+ base::CancelableTaskTracker::TaskId
+ GetFaviconForNativeApplicationURL(const GURL &url,
+ const std::vector<int> &desired_sizes_in_pixel,
+ favicon_base::FaviconResultsCallback callback,
+ base::CancelableTaskTracker *tracker) override;
+};
+
+class FaviconServiceFactoryQt : public BrowserContextKeyedServiceFactory
+{
+public:
+ static favicon::FaviconService *GetForBrowserContext(content::BrowserContext *context);
+ static FaviconServiceFactoryQt *GetInstance();
+
+private:
+ friend struct base::DefaultSingletonTraits<FaviconServiceFactoryQt>;
+
+ FaviconServiceFactoryQt();
+ ~FaviconServiceFactoryQt() override;
+
+ // BrowserContextKeyedServiceFactory:
+ content::BrowserContext *
+ GetBrowserContextToUse(content::BrowserContext *context) const override;
+ KeyedService *BuildServiceInstanceFor(content::BrowserContext *context) const override;
+};
+
+} // namespace QtWebEngineCore
+
+#endif // FAVICON_SERVICE_FACTORY_QT_H
diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
index bca059ae6..e01e82aa9 100644
--- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
+++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
@@ -56,6 +56,7 @@
#include "extensions/extension_system_qt.h"
#include "web_contents_delegate_qt.h"
+#include "web_engine_settings.h"
#include <string>
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 9a6275a84..204974c28 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -39,6 +39,10 @@
#include "profile_adapter.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"
+#include "components/history/core/browser/history_service.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
@@ -51,6 +55,7 @@
#include "api/qwebengineurlscheme.h"
#include "content_browser_client_qt.h"
#include "download_manager_delegate_qt.h"
+#include "favicon_service_factory_qt.h"
#include "permission_manager_qt.h"
#include "profile_adapter_client.h"
#include "profile_io_data_qt.h"
@@ -151,6 +156,8 @@ void ProfileAdapter::setStorageName(const QString &storageName)
m_profile->m_profileIOData->resetNetworkContext();
if (m_visitedLinksManager)
resetVisitedLinksManager();
+
+ reinitializeHistoryService();
}
}
@@ -164,6 +171,14 @@ void ProfileAdapter::setOffTheRecord(bool offTheRecord)
m_profile->m_profileIOData->resetNetworkContext();
if (m_visitedLinksManager)
resetVisitedLinksManager();
+
+ if (offTheRecord) {
+ favicon::FaviconService *faviconService =
+ FaviconServiceFactoryQt::GetForBrowserContext(m_profile.data());
+ faviconService->SetHistoryService(nullptr);
+ } else if (!m_name.isEmpty()) {
+ reinitializeHistoryService();
+ }
}
ProfileQt *ProfileAdapter::profile()
@@ -273,6 +288,9 @@ void ProfileAdapter::setDataPath(const QString &path)
m_profile->m_profileIOData->resetNetworkContext();
if (!m_offTheRecord && m_visitedLinksManager)
resetVisitedLinksManager();
+
+ if (!m_offTheRecord)
+ reinitializeHistoryService();
}
void ProfileAdapter::setDownloadPath(const QString &path)
@@ -652,6 +670,21 @@ void ProfileAdapter::resetVisitedLinksManager()
m_visitedLinksManager.reset(new VisitedLinksManagerQt(m_profile.data(), persistVisitedLinks()));
}
+void ProfileAdapter::reinitializeHistoryService()
+{
+ Q_ASSERT(!m_profile->IsOffTheRecord());
+ if (m_profile->ensureDirectoryExists()) {
+ favicon::FaviconService *faviconService =
+ FaviconServiceFactoryQt::GetForBrowserContext(m_profile.data());
+ history::HistoryService *historyService = static_cast<history::HistoryService *>(
+ HistoryServiceFactoryQt::GetInstance()->GetForBrowserContext(m_profile.data()));
+ Q_ASSERT(historyService);
+ faviconService->SetHistoryService(historyService);
+ } else {
+ qWarning("Favicon database is not available for this profile.");
+ }
+}
+
void ProfileAdapter::setUseForGlobalCertificateVerification(bool enable)
{
if (m_usedForGlobalCertificateVerification == enable)
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index fecb338ad..979316b4a 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -220,6 +220,7 @@ private:
void updateCustomUrlSchemeHandlers();
void resetVisitedLinksManager();
bool persistVisitedLinks() const;
+ void reinitializeHistoryService();
QString m_name;
bool m_offTheRecord;
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index 36303605f..ae1169558 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -58,6 +58,7 @@
#include "content/public/browser/storage_partition.h"
#include "base/base_paths.h"
+#include "base/files/file_util.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_service.h"
@@ -298,4 +299,21 @@ content::PlatformNotificationService *ProfileQt::platformNotificationService()
return m_platformNotificationService.get();
}
+bool ProfileQt::ensureDirectoryExists()
+{
+ const base::FilePath &path = GetPath();
+
+ if (base::PathExists(path))
+ return true;
+
+ base::File::Error error;
+ if (base::CreateDirectoryAndGetError(path, &error))
+ return true;
+
+ std::string errorstr = base::File::ErrorToString(error);
+ qWarning("Cannot create directory %s. Error: %s.", path.AsUTF8Unsafe().c_str(),
+ errorstr.c_str());
+ return false;
+}
+
} // namespace QtWebEngineCore
diff --git a/src/core/profile_qt.h b/src/core/profile_qt.h
index 11b567b97..349532939 100644
--- a/src/core/profile_qt.h
+++ b/src/core/profile_qt.h
@@ -119,6 +119,7 @@ public:
PrefServiceAdapter &prefServiceAdapter();
const PrefServiceAdapter &prefServiceAdapter() const;
+ bool ensureDirectoryExists();
private:
friend class ContentBrowserClientQt;
diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni
index 49217603f..8f3cac727 100644
--- a/src/core/qtwebengine.gni
+++ b/src/core/qtwebengine.gni
@@ -19,6 +19,8 @@ deps = [
"//base",
"//components/cdm/renderer",
"//components/error_page/common",
+ "//components/favicon/content",
+ "//components/history/content/browser",
"//components/keyed_service/content",
"//components/navigation_interception",
"//components/network_hints/browser",
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index a4cc57b76..e8f8131b6 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -39,9 +39,11 @@
#include "type_conversion.h"
+#include <components/favicon_base/favicon_util.h>
#include <net/cert/x509_certificate.h>
#include <net/cert/x509_util.h>
#include <ui/events/event_constants.h>
+#include <ui/gfx/image/image.h>
#include <ui/gfx/image/image_skia.h>
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h"
@@ -216,6 +218,23 @@ SkBitmap toSkBitmap(const QImage &image)
return bitmapCopy;
}
+QIcon toQIcon(const gfx::Image &image)
+{
+ // Based on ExtractSkBitmapsToStore in chromium/components/favicon/core/favicon_service_impl.cc
+ gfx::ImageSkia image_skia = image.AsImageSkia();
+ image_skia.EnsureRepsForSupportedScales();
+ const std::vector<gfx::ImageSkiaRep> &image_reps = image_skia.image_reps();
+ std::vector<SkBitmap> bitmaps;
+ const std::vector<float> favicon_scales = favicon_base::GetFaviconScales();
+ for (size_t i = 0; i < image_reps.size(); ++i) {
+ // Don't save if the scale isn't one of supported favicon scales.
+ if (!base::Contains(favicon_scales, image_reps[i].scale()))
+ continue;
+ bitmaps.push_back(image_reps[i].GetBitmap());
+ }
+ return toQIcon(bitmaps);
+}
+
QIcon toQIcon(const std::vector<SkBitmap> &bitmaps)
{
if (!bitmaps.size())
@@ -257,33 +276,6 @@ int flagsFromModifiers(Qt::KeyboardModifiers modifiers)
return modifierFlags;
}
-FaviconInfo::FaviconTypeFlags toQt(blink::mojom::FaviconIconType type)
-{
- switch (type) {
- case blink::mojom::FaviconIconType::kFavicon:
- return FaviconInfo::Favicon;
- case blink::mojom::FaviconIconType::kTouchIcon:
- return FaviconInfo::TouchIcon;
- case blink::mojom::FaviconIconType::kTouchPrecomposedIcon:
- return FaviconInfo::TouchPrecomposedIcon;
- case blink::mojom::FaviconIconType::kInvalid:
- return FaviconInfo::InvalidIcon;
- }
- Q_UNREACHABLE();
- return FaviconInfo::InvalidIcon;
-}
-
-FaviconInfo toFaviconInfo(const blink::mojom::FaviconURLPtr &favicon_url)
-{
- FaviconInfo info;
- info.url = toQt(favicon_url->icon_url);
- info.type = toQt(favicon_url->icon_type);
- // TODO: Add support for rel sizes attribute (favicon_url.icon_sizes):
- // http://www.w3schools.com/tags/att_link_sizes.asp
- info.size = QSize(0, 0);
- return info;
-}
-
void convertToQt(const SkMatrix44 &m, QMatrix4x4 &c)
{
QMatrix4x4 qtMatrix(
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index 85fd763b4..fff130218 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -52,7 +52,6 @@
#include <base/strings/nullable_string16.h>
#include "base/files/file_path.h"
#include "base/time/time.h"
-#include "favicon_manager.h"
#include "net/cookies/canonical_cookie.h"
#include "third_party/blink/public/mojom/favicon/favicon_url.mojom-forward.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -68,6 +67,7 @@ QT_FORWARD_DECLARE_CLASS(QMatrix4x4)
QT_FORWARD_DECLARE_CLASS(QSslCertificate)
namespace gfx {
+class Image;
class ImageSkiaRep;
}
@@ -222,6 +222,7 @@ QImage toQImage(const SkBitmap &bitmap);
QImage toQImage(const gfx::ImageSkiaRep &imageSkiaRep);
SkBitmap toSkBitmap(const QImage &image);
+QIcon toQIcon(const gfx::Image &image);
QIcon toQIcon(const std::vector<SkBitmap> &bitmaps);
void convertToQt(const SkMatrix44 &m, QMatrix4x4 &c);
@@ -272,8 +273,6 @@ inline QStringList fromVector(const std::vector<base::string16> &vector)
return result;
}
-FaviconInfo toFaviconInfo(const blink::mojom::FaviconURLPtr &favicon_url);
-
QList<QSslCertificate> toCertificateChain(net::X509Certificate *certificate);
Qt::InputMethodHints toQtInputMethodHints(ui::TextInputType inputType);
diff --git a/src/core/visited_links_manager_qt.cpp b/src/core/visited_links_manager_qt.cpp
index 37343cc39..15f655012 100644
--- a/src/core/visited_links_manager_qt.cpp
+++ b/src/core/visited_links_manager_qt.cpp
@@ -90,27 +90,12 @@ bool VisitedLinksManagerQt::containsUrl(const QUrl &url) const
return m_visitedLinkWriter->IsVisited(toGurl(url));
}
-static void ensureDirectoryExists(const base::FilePath &path)
-{
- if (base::PathExists(path))
- return;
-
- base::File::Error error;
- if (base::CreateDirectoryAndGetError(path, &error))
- return;
-
- std::string errorstr = base::File::ErrorToString(error);
- qWarning("Cannot create directory %s. Error: %s.",
- path.AsUTF8Unsafe().c_str(),
- errorstr.c_str());
-}
-
VisitedLinksManagerQt::VisitedLinksManagerQt(ProfileQt *profile, bool persistVisitedLinks)
: m_delegate(new VisitedLinkDelegateQt)
{
Q_ASSERT(profile);
if (persistVisitedLinks)
- ensureDirectoryExists(profile->GetPath());
+ profile->ensureDirectoryExists();
m_visitedLinkWriter.reset(new visitedlink::VisitedLinkWriter(profile, m_delegate.data(), persistVisitedLinks));
m_visitedLinkWriter->Init();
}
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index f5656f571..16e91e6c7 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -45,6 +45,8 @@
#include "devtools_frontend_qt.h"
#include "download_manager_delegate_qt.h"
+#include "favicon_driver_qt.h"
+#include "favicon_service_factory_qt.h"
#include "media_capture_devices_dispatcher.h"
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/print_view_manager_qt.h"
@@ -69,6 +71,7 @@
#include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h"
#include "base/values.h"
#include "chrome/browser/tab_contents/form_interaction_tab_helper.h"
+#include "components/favicon/core/favicon_service.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/text_input_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -532,6 +535,10 @@ void WebContentsAdapter::initialize(content::SiteInstance *site)
extensions::ExtensionWebContentsObserverQt::CreateForWebContents(webContents());
#endif
+ content::BrowserContext *context = webContents()->GetBrowserContext();
+ FaviconDriverQt::CreateForWebContents(
+ webContents(), FaviconServiceFactoryQt::GetForBrowserContext(context), m_adapterClient);
+
// Create an instance of WebEngineVisitedLinksManager to catch the first
// content::NOTIFICATION_RENDERER_PROCESS_CREATED event. This event will
// force to initialize visited links in VisitedLinkSlave.
@@ -818,12 +825,15 @@ QUrl WebContentsAdapter::requestedUrl() const
QUrl WebContentsAdapter::iconUrl() const
{
CHECK_INITIALIZED(QUrl());
- if (content::NavigationEntry* entry = m_webContents->GetController().GetVisibleEntry()) {
- content::FaviconStatus &favicon = entry->GetFavicon();
- if (favicon.valid)
- return toQt(favicon.url);
- }
- return QUrl();
+ FaviconDriverQt *driver = FaviconDriverQt::FromWebContents(webContents());
+ return toQt(driver->GetFaviconURL());
+}
+
+QIcon WebContentsAdapter::icon() const
+{
+ CHECK_INITIALIZED(QIcon());
+ FaviconDriverQt *driver = FaviconDriverQt::FromWebContents(webContents());
+ return toQIcon(driver->GetFavicon());
}
QString WebContentsAdapter::pageTitle() const
@@ -1805,12 +1815,6 @@ WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) {
return status;
}
-FaviconManager *WebContentsAdapter::faviconManager()
-{
- CHECK_INITIALIZED(nullptr);
- return m_webContentsDelegate->faviconManager();
-}
-
FindTextHelper *WebContentsAdapter::findTextHelper()
{
CHECK_INITIALIZED(nullptr);
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index b05ddeb4d..f4905e1d4 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -138,6 +138,7 @@ public:
QString pageTitle() const;
QString selectedText() const;
QUrl iconUrl() const;
+ QIcon icon() const;
void undo();
void redo();
@@ -212,7 +213,6 @@ public:
QWebChannel *webChannel() const;
void setWebChannel(QWebChannel *, uint worldId);
#endif
- FaviconManager *faviconManager();
FindTextHelper *findTextHelper();
QPointF lastScrollOffset() const;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 5d11f43c3..34e1f7ad1 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -46,7 +46,6 @@
#include "profile_adapter.h"
#include "color_chooser_controller.h"
#include "color_chooser_qt.h"
-#include "favicon_manager.h"
#include "file_picker_controller.h"
#include "media_capture_devices_dispatcher.h"
#include "profile_qt.h"
@@ -102,7 +101,6 @@ static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptCo
WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient)
: m_viewClient(adapterClient)
- , m_faviconManager(new FaviconManager(webContents, adapterClient))
, m_findTextHelper(new FindTextHelper(webContents, adapterClient))
, m_loadingState(determineLoadingState(webContents))
, m_didStartLoadingSeen(m_loadingState == LoadingState::Loading)
@@ -362,8 +360,6 @@ void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *naviga
if (!navigation_handle->IsInMainFrame() || !web_contents()->IsLoadingToDifferentDocument())
return;
- m_faviconManager->resetCandidates();
-
m_loadingInfo.url = toQt(navigation_handle->GetURL());
// IsErrorPage is only set after navigation commit, so check it otherwise: error page shouldn't have navigation entry
bool isErrorPage = m_loadingInfo.triggersErrorPage && !navigation_handle->GetNavigationEntry();
@@ -426,7 +422,6 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig
// The load will succede as an error-page load later, and we reported the original error above
if (navigation_handle->IsErrorPage()) {
// Now report we are starting to load an error-page.
- m_faviconManager->resetCandidates();
emitLoadStarted(true);
// If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call.
@@ -533,9 +528,6 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame
return;
}
- if (!m_faviconManager->hasCandidate())
- m_viewClient->iconChanged(QUrl());
-
content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry();
int http_statuscode = entry ? entry->GetHttpStatusCode() : 0;
bool errorPageEnabled = webEngineSettings()->testAttribute(QWebEngineSettings::ErrorPageEnabled);
@@ -547,21 +539,6 @@ void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame
m_loadingInfo.triggersErrorPage = triggersErrorPage;
}
-void WebContentsDelegateQt::DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host, const std::vector<blink::mojom::FaviconURLPtr> &candidates)
-{
- QList<FaviconInfo> faviconCandidates;
- faviconCandidates.reserve(static_cast<int>(candidates.size()));
- for (const blink::mojom::FaviconURLPtr &candidate : candidates) {
- // Store invalid candidates too for later debugging via API
- faviconCandidates.append(toFaviconInfo(candidate));
- }
-
- // Favicon URL can be changed from JavaScript too. Thus we need to reset
- // the current candidate icon list to not handle previous icon as a candidate.
- m_faviconManager->resetCandidates();
- m_faviconManager->update(faviconCandidates);
-}
-
void WebContentsDelegateQt::WebContentsCreated(content::WebContents * /*source_contents*/,
int /*opener_render_process_id*/, int /*opener_render_frame_id*/,
const std::string &/*frame_name*/,
@@ -867,11 +844,6 @@ void WebContentsDelegateQt::ResourceLoadComplete(content::RenderFrameHost* rende
}
}
-FaviconManager *WebContentsDelegateQt::faviconManager()
-{
- return m_faviconManager.data();
-}
-
FindTextHelper *WebContentsDelegateQt::findTextHelper()
{
return m_findTextHelper.data();
@@ -890,7 +862,6 @@ void WebContentsDelegateQt::copyStateFrom(WebContentsDelegateQt *source)
{
m_title = source->m_title;
NavigationStateChanged(web_contents(), content::INVALIDATE_TYPE_URL);
- m_faviconManager->copyStateFrom(source->m_faviconManager.data());
}
WebContentsDelegateQt::LoadingState WebContentsDelegateQt::determineLoadingState(content::WebContents *contents)
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index c3676d996..d6adcd77c 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -49,7 +49,6 @@
#include "base/callback.h"
#include "color_chooser_controller.h"
-#include "favicon_manager.h"
#include "find_text_helper.h"
#include "javascript_dialog_manager_qt.h"
#include <QtCore/qlist.h>
@@ -166,7 +165,6 @@ public:
void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code) override;
void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override;
void BeforeUnloadFired(bool proceed, const base::TimeTicks& proceed_time) override;
- void DidUpdateFaviconURL(content::RenderFrameHost *render_frame_host, const std::vector<blink::mojom::FaviconURLPtr> &candidates) override;
void OnVisibilityChanged(content::Visibility visibility) override;
void DidFirstVisuallyNonEmptyPaint() override;
void ActivateContents(content::WebContents* contents) override;
@@ -180,7 +178,6 @@ public:
void selectClientCert(const QSharedPointer<ClientCertSelectController> &);
void requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin);
void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture);
- FaviconManager *faviconManager();
FindTextHelper *findTextHelper();
void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; }
@@ -221,7 +218,6 @@ private:
int &streamCount(blink::mojom::MediaStreamType type);
WebContentsAdapterClient *m_viewClient;
- QScopedPointer<FaviconManager> m_faviconManager;
QScopedPointer<FindTextHelper> m_findTextHelper;
SavePageInfo m_savePageInfo;
QSharedPointer<FilePickerController> m_filePickerController;
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index 249f50613..6b11cf0cd 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -38,6 +38,7 @@
**
****************************************************************************/
+#include "qtwebenginecoreglobal_p.h"
#include "web_engine_library_info.h"
#include "base/base_paths.h"
diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
index f817e4016..23397003e 100644
--- a/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
+++ b/src/webenginequick/api/qquickwebenginefaviconprovider.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -39,7 +39,6 @@
#include "qquickwebenginefaviconprovider_p_p.h"
-#include "favicon_manager.h"
#include "qquickwebengineview_p.h"
#include "qquickwebengineview_p_p.h"
#include "web_contents_adapter.h"
@@ -47,21 +46,65 @@
#include <QtGui/QIcon>
#include <QtGui/QPixmap>
-#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
-#include <QtGui/qiconengine.h>
-#include <QtGui/private/qicon_p.h>
-#endif
-
QT_BEGIN_NAMESPACE
-using QtWebEngineCore::FaviconInfo;
-using QtWebEngineCore::FaviconManager;
-
static inline unsigned area(const QSize &size)
{
return size.width() * size.height();
}
+static QSize largestSize(const QList<QSize> &availableSizes)
+{
+ QSize result;
+ for (const QSize &size : availableSizes) {
+ if (area(size) > area(result))
+ result = size;
+ }
+
+ return result;
+}
+
+static QSize fitSize(const QList<QSize> &availableSizes, const QSize &requestedSize)
+{
+ Q_ASSERT(availableSizes.count());
+ QSize result = largestSize(availableSizes);
+ if (availableSizes.count() == 1 || area(requestedSize) >= area(result))
+ return result;
+
+ for (const QSize &size : availableSizes) {
+ if (area(size) == area(requestedSize))
+ return size;
+
+ if (area(requestedSize) < area(size) && area(size) < area(result))
+ result = size;
+ }
+
+ return result;
+}
+
+static QPixmap extractPixmap(const QIcon &icon, const QSize &requestedSize)
+{
+ Q_ASSERT(!icon.isNull());
+
+ // If source size is not specified, use the largest icon
+ if (!requestedSize.isValid())
+ return icon.pixmap(largestSize(icon.availableSizes()), 1.0).copy();
+
+ const QSize &size = fitSize(icon.availableSizes(), requestedSize);
+ const QPixmap &iconPixmap = icon.pixmap(size, 1.0);
+ return iconPixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation).copy();
+}
+
+static QQuickWebEngineView *findViewById(const QString &id, QList<QQuickWebEngineView *> *views)
+{
+ for (QQuickWebEngineView *view : *views) {
+ if (view->icon() == QQuickWebEngineFaviconProvider::faviconProviderUrl(QUrl(id)))
+ return view;
+ }
+
+ return nullptr;
+}
+
QString QQuickWebEngineFaviconProvider::identifier()
{
return QStringLiteral("favicon");
@@ -75,7 +118,8 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url)
QUrl providerUrl;
providerUrl.setScheme(QStringLiteral("image"));
providerUrl.setHost(identifier());
- providerUrl.setPath(QStringLiteral("/%1").arg(url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment)));
+ providerUrl.setPath(
+ QStringLiteral("/%1").arg(url.toString(QUrl::RemoveQuery | QUrl::RemoveFragment)));
if (url.hasQuery())
providerUrl.setQuery(url.query(QUrl::FullyDecoded));
if (url.hasFragment())
@@ -86,125 +130,29 @@ QUrl QQuickWebEngineFaviconProvider::faviconProviderUrl(const QUrl &url)
QQuickWebEngineFaviconProvider::QQuickWebEngineFaviconProvider()
: QQuickImageProvider(QQuickImageProvider::Pixmap)
- , m_latestView(0)
{
}
-QQuickWebEngineFaviconProvider::~QQuickWebEngineFaviconProvider()
-{
- qDeleteAll(m_iconUrlMap);
-}
+QQuickWebEngineFaviconProvider::~QQuickWebEngineFaviconProvider() { }
-QUrl QQuickWebEngineFaviconProvider::attach(QQuickWebEngineView *view, const QUrl &iconUrl)
-{
- if (iconUrl.isEmpty())
- return QUrl();
-
- m_latestView = view;
-
- if (!m_iconUrlMap.contains(view))
- m_iconUrlMap.insert(view, new QList<QUrl>());
-
- QList<QUrl> *iconUrls = m_iconUrlMap[view];
- if (!iconUrls->contains(iconUrl))
- iconUrls->append(iconUrl);
-
- return faviconProviderUrl(iconUrl);
-}
-
-void QQuickWebEngineFaviconProvider::detach(QQuickWebEngineView *view)
-{
- QList<QUrl> *iconUrls = m_iconUrlMap.take(view);
- delete iconUrls;
-}
-
-#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
-
-QPixmap QQuickWebEngineFaviconProvider::requestPixmap(const QString &id, QSize *size, const QSize &requestedSize)
+QPixmap QQuickWebEngineFaviconProvider::requestPixmap(const QString &id, QSize *size,
+ const QSize &requestedSize)
{
Q_UNUSED(size);
Q_UNUSED(requestedSize);
- QUrl iconUrl(id);
- QQuickWebEngineView *view = viewForIconUrl(iconUrl);
-
- if (!view || iconUrl.isEmpty())
+ if (m_views.isEmpty())
return QPixmap();
- FaviconManager *faviconManager = view->d_ptr->adapter->faviconManager();
-
- Q_ASSERT(faviconManager);
- const FaviconInfo &faviconInfo = faviconManager->getFaviconInfo(iconUrl);
- const QIcon &icon = faviconManager->getIcon(faviconInfo.candidate ? QUrl() : iconUrl);
-
- Q_ASSERT(!icon.isNull());
- const QSize &bestSize = faviconInfo.size;
-
- // If source size is not specified, use the best quality
- if (!requestedSize.isValid()) {
- if (size)
- *size = bestSize;
-
- return getUnscaledPixmap(icon, bestSize).copy();
- }
-
- const QSize &fitSize = findFitSize(icon.availableSizes(), requestedSize, bestSize);
- const QPixmap &iconPixmap = getUnscaledPixmap(icon, fitSize);
-
- if (size)
- *size = iconPixmap.size();
-
- return iconPixmap.scaled(requestedSize, Qt::KeepAspectRatio, Qt::SmoothTransformation).copy();
-}
-
-QQuickWebEngineView *QQuickWebEngineFaviconProvider::viewForIconUrl(const QUrl &iconUrl) const
-{
- // The most common use case is that the requested iconUrl belongs to the
- // latest WebEngineView which was raised an iconChanged signal.
- if (m_latestView) {
- QList<QUrl> *iconUrls = m_iconUrlMap[m_latestView];
- if (iconUrls && iconUrls->contains(iconUrl))
- return m_latestView;
- }
-
- for (auto it = m_iconUrlMap.cbegin(), end = m_iconUrlMap.cend(); it != end; ++it) {
- if (it.value()->contains(iconUrl))
- return it.key();
- }
-
- return 0;
-}
-
-QSize QQuickWebEngineFaviconProvider::findFitSize(const QList<QSize> &availableSizes,
- const QSize &requestedSize,
- const QSize &bestSize) const
-{
- Q_ASSERT(availableSizes.count());
- if (availableSizes.count() == 1 || area(requestedSize) >= area(bestSize))
- return bestSize;
-
- QSize fitSize = bestSize;
- for (const QSize &size : availableSizes) {
- if (area(size) == area(requestedSize))
- return size;
+ QQuickWebEngineView *view = findViewById(id, &m_views);
+ if (!view)
+ return QPixmap();
- if (area(requestedSize) < area(size) && area(size) < area(fitSize))
- fitSize = size;
- }
+ QIcon icon = view->d_ptr->adapter->icon();
+ if (icon.isNull())
+ return QPixmap();
- return fitSize;
+ return extractPixmap(icon, requestedSize).copy();
}
QT_END_NAMESPACE
diff --git a/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
index 80d2f65f2..d284a73d5 100644
--- a/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
+++ b/src/webenginequick/api/qquickwebenginefaviconprovider_p_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -52,15 +52,15 @@
//
#include <QtWebEngineQuick/private/qtwebengineglobal_p.h>
+#include <QtCore/QList>
#include <QtQuick/QQuickImageProvider>
-#include <QtCore/QMap>
-
QT_BEGIN_NAMESPACE
class QQuickWebEngineView;
-class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFaviconProvider : public QQuickImageProvider {
+class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineFaviconProvider : public QQuickImageProvider
+{
public:
static QString identifier();
static QUrl faviconProviderUrl(const QUrl &);
@@ -68,18 +68,13 @@ public:
QQuickWebEngineFaviconProvider();
~QQuickWebEngineFaviconProvider();
- QUrl attach(QQuickWebEngineView *, const QUrl &);
- void detach(QQuickWebEngineView *);
-
+ void attach(QQuickWebEngineView *view) { m_views.append(view); }
+ void detach(QQuickWebEngineView *view) { m_views.removeAll(view); }
QPixmap requestPixmap(const QString &, QSize *, const QSize &) override;
private:
- QQuickWebEngineView *viewForIconUrl(const QUrl &) const;
- QSize findFitSize(const QList<QSize> &, const QSize &, const QSize &) const;
-
- QMap<QQuickWebEngineView *, QList<QUrl> *> m_iconUrlMap;
- QQuickWebEngineView *m_latestView;
+ QList<QQuickWebEngineView *> m_views;
};
QT_END_NAMESPACE
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index 5524b8954..2e6a2f428 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -132,7 +132,6 @@ QQuickWebEngineViewPrivate::QQuickWebEngineViewPrivate()
, m_testSupport(0)
#endif
, contextMenuExtraItems(0)
- , faviconProvider(0)
, loadProgress(0)
, m_fullscreenMode(false)
, isLoading(false)
@@ -179,8 +178,8 @@ QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate()
{
Q_ASSERT(m_profileInitialized);
m_profile->d_ptr->removeWebContentsAdapterClient(this);
- if (faviconProvider)
- faviconProvider->detach(q_ptr);
+ if (m_faviconProvider)
+ m_faviconProvider->detach(q_ptr);
// q_ptr->d_ptr might be null due to destroy()
if (q_ptr->d_ptr)
bindViewAndWidget(q_ptr, nullptr);
@@ -408,20 +407,7 @@ void QQuickWebEngineViewPrivate::iconChanged(const QUrl &url)
if (iconUrl == QQuickWebEngineFaviconProvider::faviconProviderUrl(url))
return;
- if (!faviconProvider) {
- QQmlEngine *engine = qmlEngine(q);
-
- // TODO: this is a workaround for QTBUG-65044
- if (!engine)
- return;
-
- Q_ASSERT(engine);
- faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>(
- engine->imageProvider(QQuickWebEngineFaviconProvider::identifier()));
- Q_ASSERT(faviconProvider);
- }
-
- iconUrl = faviconProvider->attach(q, url);
+ iconUrl = QQuickWebEngineFaviconProvider::faviconProviderUrl(url);
m_history->reset();
QTimer::singleShot(0, q, &QQuickWebEngineView::iconChanged);
}
@@ -904,6 +890,17 @@ void QQuickWebEngineViewPrivate::ensureContentsAdapter()
else
adapter->loadDefault();
}
+
+ if (!m_faviconProvider) {
+ QQmlEngine *engine = qmlEngine(q_ptr);
+ // TODO: this is a workaround for QTBUG-65044
+ if (!engine)
+ return;
+ m_faviconProvider = static_cast<QQuickWebEngineFaviconProvider *>(
+ engine->imageProvider(QQuickWebEngineFaviconProvider::identifier()));
+ m_faviconProvider->attach(q_ptr);
+ Q_ASSERT(m_faviconProvider);
+ }
}
void QQuickWebEngineViewPrivate::initializationFinished()
diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h
index ca3b5349e..5b8231cbf 100644
--- a/src/webenginequick/api/qquickwebengineview_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p.h
@@ -70,7 +70,6 @@ class QQuickWebEngineAction;
class QQuickWebEngineAuthenticationDialogRequest;
class QQuickWebEngineClientCertificateSelection;
class QQuickWebEngineColorDialogRequest;
-class QQuickWebEngineFaviconProvider;
class QQuickWebEngineFileDialogRequest;
class QQuickWebEngineHistory;
class QQuickWebEngineJavaScriptDialogRequest;
diff --git a/src/webenginequick/api/qquickwebengineview_p_p.h b/src/webenginequick/api/qquickwebengineview_p_p.h
index 115c13e06..1b50de26a 100644
--- a/src/webenginequick/api/qquickwebengineview_p_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p_p.h
@@ -196,7 +196,6 @@ public:
QUrl m_url;
QString m_html;
QUrl iconUrl;
- QQuickWebEngineFaviconProvider *faviconProvider;
int loadProgress;
bool m_fullscreenMode;
bool isLoading;
@@ -230,6 +229,7 @@ private:
QWebEngineContextMenuRequest *m_contextMenuRequest;
LoadVisuallyCommittedState m_loadVisuallyCommittedState = NotCommitted;
QScopedPointer<QQuickWebEngineScriptCollection> m_scriptCollection;
+ QQuickWebEngineFaviconProvider *m_faviconProvider = nullptr;
};
#ifndef QT_NO_ACCESSIBILITY