diff options
Diffstat (limited to 'src/core/favicon_driver_qt.cpp')
-rw-r--r-- | src/core/favicon_driver_qt.cpp | 201 |
1 files changed, 108 insertions, 93 deletions
diff --git a/src/core/favicon_driver_qt.cpp b/src/core/favicon_driver_qt.cpp index a3bbd5939..bb4a734b4 100644 --- a/src/core/favicon_driver_qt.cpp +++ b/src/core/favicon_driver_qt.cpp @@ -1,41 +1,10 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +// Based on components/favicon/content/content_favicon_driver.cc: +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "favicon_driver_qt.h" #include "type_conversion.h" @@ -48,22 +17,14 @@ #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" +#include "content/public/browser/page.h" +#include "content/public/browser/render_frame_host.h" +#include "third_party/blink/public/mojom/manifest/manifest.mojom.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); @@ -79,7 +40,7 @@ FaviconStatusQt::FaviconStatusQt() // static void FaviconDriverQt::CreateForWebContents(content::WebContents *webContents, - favicon::FaviconService *faviconService, + favicon::CoreFaviconService *faviconService, WebContentsAdapterClient *viewClient) { if (FromWebContents(webContents)) @@ -91,9 +52,10 @@ void FaviconDriverQt::CreateForWebContents(content::WebContents *webContents, } FaviconDriverQt::FaviconDriverQt(content::WebContents *webContents, - favicon::FaviconService *faviconService, + favicon::CoreFaviconService *faviconService, WebContentsAdapterClient *viewClient) : content::WebContentsObserver(webContents) + , content::WebContentsUserData<FaviconDriverQt>(*webContents) , m_faviconService(faviconService) , m_viewClient(viewClient) { @@ -163,6 +125,13 @@ GURL FaviconDriverQt::GetActiveURL() return entry ? entry->GetURL() : GURL(); } +GURL FaviconDriverQt::GetManifestURL(content::RenderFrameHost *rfh) +{ + DocumentManifestData *document_data = DocumentManifestData::GetOrCreateForCurrentDocument(rfh); + return document_data->has_manifest_url ? rfh->GetPage().GetManifestUrl().value_or(GURL()) + : GURL(); +} + GURL FaviconDriverQt::GetFaviconURL() const { content::NavigationController &controller = web_contents()->GetController(); @@ -173,20 +142,62 @@ GURL FaviconDriverQt::GetFaviconURL() const return GURL(); } +FaviconDriverQt::DocumentManifestData::DocumentManifestData(content::RenderFrameHost *rfh) + : content::DocumentUserData<DocumentManifestData>(rfh) +{ +} + +FaviconDriverQt::DocumentManifestData::~DocumentManifestData() = default; + +FaviconDriverQt::NavigationManifestData::NavigationManifestData( + content::NavigationHandle &navigation_handle) +{ +} + +FaviconDriverQt::NavigationManifestData::~NavigationManifestData() = default; + +void FaviconDriverQt::OnDidDownloadManifest(ManifestDownloadCallback callback, + const GURL &manifest_url, + blink::mojom::ManifestPtr manifest) +{ + Q_UNUSED(manifest_url); + + // ~WebContentsImpl triggers running any pending callbacks for manifests. + // As we're about to be destroyed ignore the request. To do otherwise may + // result in calling back to this and attempting to use the WebContents, which + // will crash. + if (!web_contents()) + return; + + std::vector<favicon::FaviconURL> candidates; + if (manifest) { + for (const auto &icon : manifest->icons) { + candidates.emplace_back(icon.src, favicon_base::IconType::kWebManifestIcon, icon.sizes); + } + } + std::move(callback).Run(candidates); +} + 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)); + const gfx::Size preferred_size(max_image_size, max_image_size); + return web_contents()->DownloadImage(url, true, preferred_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))); + // TODO(crbug.com/1201237): This appears to be reachable from pages other + // than the primary page. This code should likely be refactored so that either + // this is unreachable from other pages, or the correct page is plumbed in + // here. + web_contents()->GetPrimaryPage().GetManifest(base::BindOnce( + &FaviconDriverQt::OnDidDownloadManifest, base::Unretained(this), std::move(callback))); } bool FaviconDriverQt::IsOffTheRecord() @@ -243,88 +254,95 @@ void FaviconDriverQt::OnHandlerCompleted(favicon::FaviconHandler *handler) } void FaviconDriverQt::DidUpdateFaviconURL( - content::RenderFrameHost *render_frame_host, - const std::vector<blink::mojom::FaviconURLPtr> &candidates) + content::RenderFrameHost *rfh, 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; + std::vector<blink::mojom::FaviconURLPtr> faviconUrls; for (const auto &candidate : candidates) - faviconUrls.push_back(*candidate); - m_faviconUrls = faviconUrls; + faviconUrls.push_back(candidate.Clone()); + m_faviconUrls = std::move(faviconUrls); - if (!m_documentOnLoadCompleted) + if (!rfh->IsDocumentOnLoadCompletedInMainFrame()) return; - OnUpdateCandidates(entry->GetURL(), - favicon::FaviconURLsFromContentFaviconURLs( - m_faviconUrls.value_or(std::vector<blink::mojom::FaviconURL>())), - m_manifestUrl); + OnUpdateCandidates(rfh->GetLastCommittedURL(), + favicon::FaviconURLsFromContentFaviconURLs(candidates), GetManifestURL(rfh)); } -void FaviconDriverQt::DidUpdateWebManifestURL(content::RenderFrameHost *target_frame, - const base::Optional<GURL> &manifest_url) +void FaviconDriverQt::DidUpdateWebManifestURL(content::RenderFrameHost *rfh, + const GURL &manifest_url) { - Q_UNUSED(target_frame); + Q_UNUSED(manifest_url); // 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) + if (!entry || !rfh->IsDocumentOnLoadCompletedInMainFrame()) return; - m_manifestUrl = manifest_url.value_or(GURL()); + DocumentManifestData *document_data = DocumentManifestData::GetOrCreateForCurrentDocument(rfh); + document_data->has_manifest_url = true; // 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); + if (!rfh->FaviconURLs().empty()) { + OnUpdateCandidates(rfh->GetLastCommittedURL(), + favicon::FaviconURLsFromContentFaviconURLs(rfh->FaviconURLs()), + GetManifestURL(rfh)); } } void FaviconDriverQt::DidStartNavigation(content::NavigationHandle *navigation_handle) { - if (!navigation_handle->IsInMainFrame()) + if (!navigation_handle->IsInPrimaryMainFrame()) return; - m_faviconUrls.reset(); - m_completedHandlersCount = 0; - m_latestFavicon = FaviconStatusQt(); - if (!navigation_handle->IsSameDocument()) { - m_documentOnLoadCompleted = false; - m_manifestUrl = GURL(); + m_completedHandlersCount = 0; + m_latestFavicon = FaviconStatusQt(); + m_viewClient->iconChanged(QUrl()); } - m_viewClient->iconChanged(QUrl()); - content::ReloadType reload_type = navigation_handle->GetReloadType(); if (reload_type == content::ReloadType::NONE || IsOffTheRecord()) return; - m_bypassCachePageURL = navigation_handle->GetURL(); + if (!navigation_handle->IsSameDocument()) { + NavigationManifestData *navigation_data = + NavigationManifestData::GetOrCreateForNavigationHandle(*navigation_handle); + navigation_data->has_manifest_url = false; + } + + if (reload_type == content::ReloadType::BYPASSING_CACHE) + 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() + if (!navigation_handle->IsInPrimaryMainFrame() || !navigation_handle->HasCommitted() || navigation_handle->IsErrorPage()) { return; } + // Transfer in-flight navigation data to the document user data. + NavigationManifestData *navigation_data = + NavigationManifestData::GetOrCreateForNavigationHandle(*navigation_handle); + DocumentManifestData *document_data = DocumentManifestData::GetOrCreateForCurrentDocument( + navigation_handle->GetRenderFrameHost()); + document_data->has_manifest_url = navigation_data->has_manifest_url; + // 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 @@ -340,11 +358,6 @@ void FaviconDriverQt::DidFinishNavigation(content::NavigationHandle *navigation_ FetchFavicon(url, navigation_handle->IsSameDocument()); } -void FaviconDriverQt::DocumentOnLoadCompletedInMainFrame() -{ - m_documentOnLoadCompleted = true; -} - void FaviconDriverQt::SetFaviconOutOfDateForPage(const GURL &url, bool force_reload) { if (m_faviconService) { @@ -402,6 +415,8 @@ void FaviconDriverQt::emitIconChangedIfNeeded() m_viewClient->iconChanged(toQt(m_latestFavicon.url)); } -WEB_CONTENTS_USER_DATA_KEY_IMPL(FaviconDriverQt) +NAVIGATION_HANDLE_USER_DATA_KEY_IMPL(FaviconDriverQt::NavigationManifestData); +DOCUMENT_USER_DATA_KEY_IMPL(FaviconDriverQt::DocumentManifestData); +WEB_CONTENTS_USER_DATA_KEY_IMPL(FaviconDriverQt); } // namespace QtWebEngineCore |