diff options
Diffstat (limited to 'src/core/content_browser_client_qt.cpp')
-rw-r--r-- | src/core/content_browser_client_qt.cpp | 404 |
1 files changed, 260 insertions, 144 deletions
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index bede258f3..28ed6ef7c 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -1,52 +1,16 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 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 #include "content_browser_client_qt.h" #include "base/files/file_util.h" -#include "base/task/post_task.h" #include "chrome/browser/tab_contents/form_interaction_tab_helper.h" +#include "components/autofill/content/browser/content_autofill_driver_factory.h" #include "components/custom_handlers/protocol_handler_registry.h" +#include "components/embedder_support/user_agent_utils.h" #include "components/error_page/common/error.h" #include "components/error_page/common/localized_error.h" #include "components/navigation_interception/intercept_navigation_throttle.h" -#include "components/navigation_interception/navigation_params.h" #include "components/network_hints/browser/simple_network_hints_handler_impl.h" #include "components/performance_manager/embedder/performance_manager_lifetime.h" #include "components/performance_manager/embedder/performance_manager_registry.h" @@ -58,24 +22,31 @@ #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/file_url_loader.h" #include "content/public/browser/media_observer.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/shared_cors_origin_access_list.h" +#include "content/public/browser/url_loader_request_interceptor.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.h" +#include "content/public/browser/web_contents_view_delegate.h" #include "content/public/browser/web_ui_url_loader_factory.h" #include "content/public/common/content_switches.h" #include "content/public/common/main_function_params.h" +#include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" +#include "pdf/buildflags.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_store.h" #include "net/ssl/ssl_private_key.h" +#include "printing/buildflags/buildflags.h" #include "services/device/public/cpp/geolocation/geolocation_manager.h" #include "services/network/network_service.h" #include "services/network/public/cpp/web_sandbox_flags.h" +#include "services/network/public/mojom/websocket.mojom.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "ui/base/resource/resource_bundle.h" @@ -83,7 +54,6 @@ #include "url/url_util_qt.h" #include "qtwebengine/common/renderer_configuration.mojom.h" -#include "qtwebengine/grit/qt_webengine_resources.h" #include "profile_adapter.h" #include "browser_main_parts_qt.h" @@ -92,6 +62,7 @@ #include "client_cert_select_controller.h" #include "custom_handlers/protocol_handler_registry_factory.h" #include "devtools_manager_delegate_qt.h" +#include "file_system_access/file_system_access_permission_request_manager_qt.h" #include "login_delegate_qt.h" #include "media_capture_devices_dispatcher.h" #include "net/cookie_monster_delegate_qt.h" @@ -99,11 +70,9 @@ #include "net/proxying_restricted_cookie_manager_qt.h" #include "net/proxying_url_loader_factory_qt.h" #include "net/system_network_context_manager.h" -#include "ozone/gl_share_context_qt.h" #include "platform_notification_service_qt.h" #include "profile_qt.h" #include "profile_io_data_qt.h" -#include "quota_permission_context_qt.h" #include "renderer_host/user_resource_controller_host.h" #include "select_file_dialog_factory_qt.h" #include "type_conversion.h" @@ -114,27 +83,23 @@ #include "web_engine_context.h" #include "web_engine_library_info.h" #include "web_engine_settings.h" +#include "authenticator_request_client_delegate_qt.h" #include "api/qwebenginecookiestore.h" #include "api/qwebenginecookiestore_p.h" - -#if QT_CONFIG(opengl) -#include <QOpenGLContext> -#include <QOpenGLExtraFunctions> -#endif +#include "api/qwebengineurlrequestinfo_p.h" #if QT_CONFIG(webengine_geolocation) #include "base/memory/ptr_util.h" #include "location_provider_qt.h" #endif -#if QT_CONFIG(webengine_pepper_plugins) -#include "content/public/browser/browser_ppapi_host.h" -#include "ppapi/host/ppapi_host.h" -#endif - #if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" +#include "components/spellcheck/browser/pref_names.h" #include "components/spellcheck/common/spellcheck.mojom.h" +#include "components/spellcheck/common/spellcheck_features.h" #endif #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) @@ -148,13 +113,14 @@ #if BUILDFLAG(ENABLE_EXTENSIONS) #include "common/extensions/extensions_client_qt.h" #include "components/guest_view/browser/guest_view_base.h" +#include "extensions/browser/api/messaging/messaging_api_message_filter.h" #include "extensions/browser/api/mime_handler_private/mime_handler_private.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_message_filter.h" #include "extensions/browser/extension_protocols.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_util.h" -#include "extensions/browser/guest_view/extensions_guest_view_message_filter.h" +#include "extensions/browser/guest_view/extensions_guest_view.h" #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "extensions/browser/process_map.h" @@ -164,7 +130,6 @@ #include "extensions/common/manifest_handlers/mime_types_handler.h" #include "extensions/extension_web_contents_observer_qt.h" #include "extensions/extensions_browser_client_qt.h" -#include "extensions/pdf_iframe_navigation_throttle_qt.h" #include "net/plugin_response_interceptor_url_loader_throttle.h" #endif @@ -174,16 +139,24 @@ #endif #if BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) +#include "printing/pdf_stream_delegate_qt.h" #include "printing/print_view_manager_qt.h" #endif +#if BUILDFLAG(ENABLE_PDF) +#include "components/pdf/browser/pdf_navigation_throttle.h" +#include "components/pdf/browser/pdf_url_loader_request_interceptor.h" +#include "components/pdf/browser/pdf_document_helper.h" + +#include "printing/pdf_document_helper_client_qt.h" +#endif + +#if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) +#include "extensions/pdf_iframe_navigation_throttle_qt.h" +#endif + #include <QGuiApplication> #include <QStandardPaths> -#include <qpa/qplatformnativeinterface.h> - -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE // Implement IsHandledProtocol as declared in //url/url_util_qt.h. namespace url { @@ -236,7 +209,7 @@ ContentBrowserClientQt::~ContentBrowserClientQt() { } -std::unique_ptr<content::BrowserMainParts> ContentBrowserClientQt::CreateBrowserMainParts(content::MainFunctionParams) +std::unique_ptr<content::BrowserMainParts> ContentBrowserClientQt::CreateBrowserMainParts(bool) { Q_ASSERT(!m_browserMainParts); auto browserMainParts = std::make_unique<BrowserMainPartsQt>(); @@ -249,6 +222,11 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost const int id = host->GetID(); Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); +#if QT_CONFIG(webengine_spellchecker) + if (spellcheck::UseBrowserSpellChecker() && !profile->GetPrefs()->GetBoolean(spellcheck::prefs::kSpellCheckEnable)) + SpellcheckServiceFactory::GetForContext(profile)->InitForRenderer(host); +#endif + #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) WebRtcLoggingController::AttachToRenderProcessHost(host, WebEngineContext::current()->webRtcLogUploader()); #endif @@ -265,7 +243,7 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost host->AddFilter(new BrowserMessageFilterQt(id, profile)); #if BUILDFLAG(ENABLE_EXTENSIONS) host->AddFilter(new extensions::ExtensionMessageFilter(id, profile)); - host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(id, profile)); + host->AddFilter(new extensions::MessagingAPIMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS bool is_incognito_process = profile->IsOffTheRecord(); @@ -274,13 +252,6 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost renderer_configuration->SetInitialConfiguration(is_incognito_process); } -gl::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() -{ - if (!m_shareGroupQt.get()) - m_shareGroupQt = new ShareGroupQt; - return m_shareGroupQt.get(); -} - content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() { return MediaCaptureDevicesDispatcher::GetInstance(); @@ -301,34 +272,31 @@ void ContentBrowserClientQt::OverrideWebkitPrefs(content::WebContents *webConten delegate->overrideWebPreferences(webContents, web_prefs); } -scoped_refptr<content::QuotaPermissionContext> ContentBrowserClientQt::CreateQuotaPermissionContext() -{ - return new QuotaPermissionContextQt; -} - void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webContents, int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, - bool /* is_main_frame_request */, + bool is_main_frame_request, bool strict_enforcement, base::OnceCallback<void(content::CertificateRequestResultType)> callback) { WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); QSharedPointer<CertificateErrorController> errorController(new CertificateErrorController( - cert_error, ssl_info, request_url, strict_enforcement, std::move(callback))); + cert_error, ssl_info, request_url, is_main_frame_request, strict_enforcement, std::move(callback))); contentsDelegate->allowCertificateError(errorController); } -base::OnceClosure ContentBrowserClientQt::SelectClientCertificate(content::WebContents *webContents, +base::OnceClosure ContentBrowserClientQt::SelectClientCertificate(content::BrowserContext *browser_context, + content::WebContents *webContents, net::SSLCertRequestInfo *certRequestInfo, net::ClientCertIdentityList clientCerts, std::unique_ptr<content::ClientCertificateDelegate> delegate) { + Q_UNUSED(browser_context); if (!clientCerts.empty()) { - WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); QSharedPointer<ClientCertSelectController> certSelectController( new ClientCertSelectController(certRequestInfo, std::move(clientCerts), std::move(delegate))); @@ -465,7 +433,6 @@ void ContentBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( content::RenderFrameHost *render_frame_host, mojo::BinderMapWithContext<content::RenderFrameHost *> *map) { - Q_UNUSED(render_frame_host); map->Add<network_hints::mojom::NetworkHintsHandler>(base::BindRepeating(&BindNetworkHintsHandler)); #if BUILDFLAG(ENABLE_EXTENSIONS) map->Add<extensions::mime_handler::MimeHandlerService>(base::BindRepeating(&BindMimeHandlerService)); @@ -482,6 +449,8 @@ void ContentBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( extensions::ExtensionsBrowserClient::Get()->RegisterBrowserInterfaceBindersForFrame(map, render_frame_host, extension); +#else + Q_UNUSED(render_frame_host); #endif } @@ -492,42 +461,62 @@ void ContentBrowserClientQt::ExposeInterfacesToRenderer(service_manager::BinderR if (auto *manager = performance_manager::PerformanceManagerRegistry::GetInstance()) manager->CreateProcessNodeAndExposeInterfacesToRendererProcess(registry, render_process_host); #if BUILDFLAG(ENABLE_EXTENSIONS) - associated_registry->AddInterface(base::BindRepeating(&extensions::EventRouter::BindForRenderer, - render_process_host->GetID())); + associated_registry->AddInterface<extensions::mojom::EventRouter>( + base::BindRepeating(&extensions::EventRouter::BindForRenderer, render_process_host->GetID())); + associated_registry->AddInterface<guest_view::mojom::GuestViewHost>( + base::BindRepeating(&extensions::ExtensionsGuestView::CreateForComponents, render_process_host->GetID())); + associated_registry->AddInterface<extensions::mojom::GuestView>( + base::BindRepeating(&extensions::ExtensionsGuestView::CreateForExtensions, render_process_host->GetID())); #else Q_UNUSED(associated_registry); #endif } -bool ContentBrowserClientQt::BindAssociatedReceiverFromFrame(content::RenderFrameHost *rfh, - const std::string &interface_name, - mojo::ScopedInterfaceEndpointHandle *handle) +void ContentBrowserClientQt::RegisterAssociatedInterfaceBindersForRenderFrameHost( + content::RenderFrameHost &rfh, + blink::AssociatedInterfaceRegistry &associated_registry) { #if QT_CONFIG(webengine_webchannel) - if (interface_name == qtwebchannel::mojom::WebChannelTransportHost::Name_) { - auto *web_contents = content::WebContents::FromRenderFrameHost(rfh); - auto *adapter = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->webContentsAdapter(); - adapter->webChannelTransport()->BindReceiver( - mojo::PendingAssociatedReceiver<qtwebchannel::mojom::WebChannelTransportHost>(std::move(*handle)), rfh); - return true; - } + associated_registry.AddInterface<qtwebchannel::mojom::WebChannelTransportHost>( + base::BindRepeating( + [](content::RenderFrameHost *render_frame_host, + mojo::PendingAssociatedReceiver<qtwebchannel::mojom::WebChannelTransportHost> receiver) { + auto *web_contents = content::WebContents::FromRenderFrameHost(render_frame_host); + auto *adapter = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->webContentsAdapter(); + adapter->webChannelTransport()->BindReceiver(std::move(receiver), render_frame_host); + }, &rfh)); #endif #if BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) - if (interface_name == printing::mojom::PrintManagerHost::Name_) { - mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost> receiver(std::move(*handle)); - PrintViewManagerQt::BindPrintManagerHost(std::move(receiver), rfh); - return true; - } + associated_registry.AddInterface<printing::mojom::PrintManagerHost>( + base::BindRepeating( + [](content::RenderFrameHost* render_frame_host, + mojo::PendingAssociatedReceiver<printing::mojom::PrintManagerHost> receiver) { + PrintViewManagerQt::BindPrintManagerHost(std::move(receiver), render_frame_host); + }, &rfh)); #endif #if BUILDFLAG(ENABLE_EXTENSIONS) - if (interface_name == extensions::mojom::LocalFrameHost::Name_) { - extensions::ExtensionWebContentsObserverQt::BindLocalFrameHost( - mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost>(std::move(*handle)), rfh); - return true; - } + associated_registry.AddInterface<extensions::mojom::LocalFrameHost>( + base::BindRepeating( + [](content::RenderFrameHost *render_frame_host, + mojo::PendingAssociatedReceiver<extensions::mojom::LocalFrameHost> receiver) { + extensions::ExtensionWebContentsObserverQt::BindLocalFrameHost(std::move(receiver), render_frame_host); + }, &rfh)); #endif - DCHECK(!ContentBrowserClient::BindAssociatedReceiverFromFrame(rfh, interface_name, handle)); - return false; + associated_registry.AddInterface<autofill::mojom::AutofillDriver>( + base::BindRepeating( + [](content::RenderFrameHost *render_frame_host, + mojo::PendingAssociatedReceiver<autofill::mojom::AutofillDriver> receiver) { + autofill::ContentAutofillDriverFactory::BindAutofillDriver(std::move(receiver), render_frame_host); + }, &rfh)); +#if BUILDFLAG(ENABLE_PDF) + associated_registry.AddInterface<pdf::mojom::PdfService>( + base::BindRepeating( + [](content::RenderFrameHost *render_frame_host, + mojo::PendingAssociatedReceiver<pdf::mojom::PdfService> receiver) { + pdf::PDFDocumentHelper::BindPdfService(std::move(receiver), render_frame_host, std::make_unique<PDFDocumentHelperClientQt>()); + }, &rfh)); +#endif // BUILDFLAG(ENABLE_PDF) + ContentBrowserClient::RegisterAssociatedInterfaceBindersForRenderFrameHost(rfh, associated_registry); } bool ContentBrowserClientQt::CanCreateWindow( @@ -581,7 +570,7 @@ std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystem device::GeolocationManager *ContentBrowserClientQt::GetGeolocationManager() { -#if defined(OS_MAC) +#if BUILDFLAG(IS_MAC) return m_browserMainParts->GetGeolocationManager(); #else return nullptr; @@ -686,7 +675,7 @@ static void LaunchURL(const GURL& url, has_user_gesture); if (!allowed) { - content::RenderFrameHost *rfh = webContents->GetMainFrame(); + content::RenderFrameHost *rfh = webContents->GetPrimaryMainFrame(); if (!base::CommandLine::ForCurrentProcess()->HasSwitch("disable-sandbox-external-protocols")) { rfh->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError, "Navigation to external protocol blocked by sandbox."); @@ -702,29 +691,31 @@ static void LaunchURL(const GURL& url, bool ContentBrowserClientQt::HandleExternalProtocol(const GURL &url, base::RepeatingCallback<content::WebContents*()> web_contents_getter, - int child_id, int frame_tree_node_id, content::NavigationUIData *navigation_data, - bool is_main_frame, + bool is_primary_main_frame, + bool is_in_fenced_frame_tree, network::mojom::WebSandboxFlags sandbox_flags, ui::PageTransition page_transition, bool has_user_gesture, const absl::optional<url::Origin> &initiating_origin, + content::RenderFrameHost *initiator_document, mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory) { - Q_UNUSED(child_id); Q_UNUSED(frame_tree_node_id); + Q_UNUSED(is_in_fenced_frame_tree); Q_UNUSED(navigation_data); Q_UNUSED(initiating_origin); + Q_UNUSED(initiator_document); Q_UNUSED(out_factory); - base::PostTask(FROM_HERE, {content::BrowserThread::UI}, + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, base::BindOnce(&LaunchURL, url, std::move(web_contents_getter), page_transition, sandbox_flags, - is_main_frame, + is_primary_main_frame, has_user_gesture)); return true; } @@ -811,18 +802,14 @@ WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::Page } } -static bool navigationThrottleCallback(content::WebContents *source, - const navigation_interception::NavigationParams ¶ms) +static bool navigationThrottleCallback(content::NavigationHandle *handle) { // We call navigationRequested later in launchExternalUrl for external protocols. // The is_external_protocol parameter here is not fully accurate though, // and doesn't know about profile specific custom URL schemes. + content::WebContents *source = handle->GetWebContents(); ProfileQt *profile = static_cast<ProfileQt *>(source->GetBrowserContext()); - if (params.is_external_protocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(params.url().scheme()))) - return false; - - WebContentsViewQt *view = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView()); - if (!view->client()) + if (handle->IsExternalProtocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(handle->GetURL().scheme()))) return false; bool navigationAccepted = true; @@ -833,14 +820,15 @@ static bool navigationThrottleCallback(content::WebContents *source, return false; // Redirects might not be reflected in transition_type at this point (see also chrome/.../web_navigation_api_helpers.cc) - auto transition_type = params.transition_type(); - if (params.is_redirect()) + auto transition_type = handle->GetPageTransition(); + if (handle->WasServerRedirect()) transition_type = ui::PageTransitionFromInt(transition_type | ui::PAGE_TRANSITION_SERVER_REDIRECT); client->navigationRequested(pageTransitionToNavigationType(transition_type), - toQt(params.url()), + toQt(handle->GetURL()), navigationAccepted, - params.is_main_frame()); + handle->IsInPrimaryMainFrame(), + handle->IsFormSubmission()); return !navigationAccepted; } @@ -853,9 +841,12 @@ std::vector<std::unique_ptr<content::NavigationThrottle>> ContentBrowserClientQt base::BindRepeating(&navigationThrottleCallback), navigation_interception::SynchronyMode::kSync)); -#if BUILDFLAG(ENABLE_EXTENSIONS) - MaybeAddThrottle(extensions::PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(navigation_handle), &throttles); -#endif +#if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) + MaybeAddThrottle( + extensions::PDFIFrameNavigationThrottleQt::MaybeCreateThrottleFor(navigation_handle), + &throttles); + MaybeAddThrottle(pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(navigation_handle, std::make_unique<PdfStreamDelegateQt>()), &throttles); +#endif // BUILDFLAG(ENABLE_PDF) && BUIDLFLAG(ENABLE_EXTENSIONS) return throttles; } @@ -975,7 +966,16 @@ void ContentBrowserClientQt::OverrideURLLoaderFactoryParams(content::BrowserCont std::string ContentBrowserClientQt::getUserAgent() { // Mention the Chromium version we're based on to get passed stupid UA-string-based feature detection (several WebRTC demos need this) - return content::BuildUserAgentFromProduct("QtWebEngine/" QTWEBENGINECORE_VERSION_STR " Chrome/" CHROMIUM_VERSION); + return content::BuildUserAgentFromProduct("QtWebEngine/" + std::string(qWebEngineVersion()) + + " Chrome/" + + std::string(qWebEngineChromiumVersion())); +} + +blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata() +{ + // Implemented only for safe-keeping. It will be overridden on WebContents level. + static blink::UserAgentMetadata userAgentMetadata(embedder_support::GetUserAgentMetadata()); + return userAgentMetadata; } std::string ContentBrowserClientQt::GetProduct() @@ -1085,8 +1085,10 @@ void ContentBrowserClientQt::RegisterNonNetworkServiceWorkerUpdateURLLoaderFacto } void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, + const absl::optional<url::Origin> &request_initiator_origin, NonNetworkURLLoaderFactoryMap *factories) { + Q_UNUSED(request_initiator_origin); content::RenderProcessHost *process_host = content::RenderProcessHost::FromID(render_process_id); Profile *profile = Profile::FromBrowserContext(process_host->GetBrowserContext()); ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); @@ -1178,6 +1180,9 @@ base::flat_set<std::string> ContentBrowserClientQt::GetPluginMimeTypesWithExtern } } #endif +#if BUILDFLAG(ENABLE_PDF) + mime_types.insert("application/x-google-chrome-pdf"); +#endif return mime_types; } @@ -1193,7 +1198,8 @@ bool ContentBrowserClientQt::WillCreateURLLoaderFactory( mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient> *header_client, bool *bypass_redirect_checks, bool *disable_secure_dns, - network::mojom::URLLoaderFactoryOverridePtr *factory_override) + network::mojom::URLLoaderFactoryOverridePtr *factory_override, + scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) { Q_UNUSED(render_process_id); Q_UNUSED(type); @@ -1209,47 +1215,125 @@ bool ContentBrowserClientQt::WillCreateURLLoaderFactory( mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_url_loader_factory; *factory_receiver = pending_url_loader_factory.InitWithNewPipeAndPassReceiver(); // Will manage its own lifetime + // FIXME: use navigation_response_task_runner? new ProxyingURLLoaderFactoryQt(adapter, frame ? frame->GetFrameTreeNodeId() : content::RenderFrameHost::kNoFrameTreeNodeId, std::move(proxied_receiver), std::move(pending_url_loader_factory)); return true; } -void ContentBrowserClientQt::SiteInstanceGotProcess(content::SiteInstance *site_instance) +std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>> +ContentBrowserClientQt::WillCreateURLLoaderRequestInterceptors(content::NavigationUIData* navigation_ui_data, + int frame_tree_node_id, int64_t navigation_id, + scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) { -#if BUILDFLAG(ENABLE_EXTENSIONS) - content::BrowserContext *context = site_instance->GetBrowserContext(); - extensions::ExtensionRegistry *registry = extensions::ExtensionRegistry::Get(context); - const extensions::Extension *extension = registry->enabled_extensions().GetExtensionOrAppByURL(site_instance->GetSiteURL()); - if (!extension) - return; + std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>> interceptors; +#if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) + { + std::unique_ptr<content::URLLoaderRequestInterceptor> pdf_interceptor = + pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor( + frame_tree_node_id, std::make_unique<PdfStreamDelegateQt>()); + if (pdf_interceptor) + interceptors.push_back(std::move(pdf_interceptor)); + } +#endif // BUILDFLAG(ENABLE_PDF) && BUIDLFLAG(ENABLE_EXTENSIONS) - extensions::ProcessMap *processMap = extensions::ProcessMap::Get(context); - processMap->Insert(extension->id(), site_instance->GetProcess()->GetID(), site_instance->GetId()); -#endif + return interceptors; } -void ContentBrowserClientQt::SiteInstanceDeleting(content::SiteInstance *site_instance) +bool ContentBrowserClientQt::WillInterceptWebSocket(content::RenderFrameHost *frame) { -#if BUILDFLAG(ENABLE_EXTENSIONS) - // Don't do anything if we're shutting down. - if (content::BrowserMainRunner::ExitedMainMessageLoop() || !site_instance->HasProcess()) - return; + return frame != nullptr; +} + +QWebEngineUrlRequestInterceptor *getProfileInterceptorFromFrame(content::RenderFrameHost *frame) +{ + ProfileQt *profile = static_cast<ProfileQt *>(frame->GetBrowserContext()); + if (profile) + return profile->profileAdapter()->requestInterceptor(); + return nullptr; +} + +QWebEngineUrlRequestInterceptor *getPageInterceptor(content::WebContents *web_contents) +{ + if (web_contents) { + auto view = static_cast<content::WebContentsImpl *>(web_contents)->GetView(); + if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client()) + return client->webContentsAdapter()->requestInterceptor(); + } + return nullptr; +} +void ContentBrowserClientQt::CreateWebSocket( + content::RenderFrameHost *frame, + WebSocketFactory factory, + const GURL &url, + const net::SiteForCookies &site_for_cookies, + const absl::optional<std::string> &user_agent, + mojo::PendingRemote<network::mojom::WebSocketHandshakeClient> handshake_client) +{ + QWebEngineUrlRequestInterceptor *profileInterceptor = getProfileInterceptorFromFrame(frame); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame); + QWebEngineUrlRequestInterceptor *pageInterceptor = getPageInterceptor(web_contents); + std::vector<network::mojom::HttpHeaderPtr> headers; + GURL to_url = url; + bool addedUserAgent = false; + if (profileInterceptor || pageInterceptor) { + QUrl initiator = web_contents ? toQt(web_contents->GetURL()) : QUrl(); + auto *infoPrivate = new QWebEngineUrlRequestInfoPrivate( + QWebEngineUrlRequestInfo::ResourceTypeWebSocket, + QWebEngineUrlRequestInfo::NavigationTypeOther, + toQt(url), toQt(site_for_cookies.first_party_url()), initiator, + QByteArrayLiteral("GET")); + QWebEngineUrlRequestInfo requestInfo(infoPrivate); + if (profileInterceptor) { + profileInterceptor->interceptRequest(requestInfo); + pageInterceptor = getPageInterceptor(web_contents); + } + if (pageInterceptor && !requestInfo.changed()) + pageInterceptor->interceptRequest(requestInfo); + if (infoPrivate->shouldBlockRequest) + return; // ### should we call OnFailure on handshake_client? + if (infoPrivate->shouldRedirectRequest) + to_url = toGurl(infoPrivate->url); + for (auto header = infoPrivate->extraHeaders.constBegin(); header != infoPrivate->extraHeaders.constEnd(); ++header) { + std::string h = header.key().toStdString(); + if (base::EqualsCaseInsensitiveASCII(h, net::HttpRequestHeaders::kUserAgent)) + addedUserAgent = true; + headers.push_back(network::mojom::HttpHeader::New(h, header.value().toStdString())); + } + } + if (!addedUserAgent && user_agent) + headers.push_back(network::mojom::HttpHeader::New(net::HttpRequestHeaders::kUserAgent, *user_agent)); + + std::move(factory).Run(to_url, std::move(headers), std::move(handshake_client), mojo::NullRemote(), mojo::NullRemote()); +} + +void ContentBrowserClientQt::SiteInstanceGotProcess(content::SiteInstance *site_instance) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) content::BrowserContext *context = site_instance->GetBrowserContext(); extensions::ExtensionRegistry *registry = extensions::ExtensionRegistry::Get(context); - const extensions::Extension *extension = registry->enabled_extensions().GetExtensionOrAppByURL(site_instance->GetSiteURL()); + if (!registry) + return; + if (site_instance->IsGuest()) + return; + auto site_url = site_instance->GetSiteURL(); + if (!site_url.SchemeIs(extensions::kExtensionScheme)) + return; + const extensions::Extension *extension = registry->enabled_extensions().GetByID(site_url.host()); if (!extension) return; extensions::ProcessMap *processMap = extensions::ProcessMap::Get(context); - processMap->Remove(extension->id(), site_instance->GetProcess()->GetID(), site_instance->GetId()); + processMap->Insert(extension->id(), site_instance->GetProcess()->GetID()); #endif } -content::WebContentsViewDelegate *ContentBrowserClientQt::GetWebContentsViewDelegate(content::WebContents *web_contents) +std::unique_ptr<content::WebContentsViewDelegate> ContentBrowserClientQt::GetWebContentsViewDelegate(content::WebContents *web_contents) { FormInteractionTabHelper::CreateForWebContents(web_contents); + FileSystemAccessPermissionRequestManagerQt::CreateForWebContents(web_contents); if (auto *registry = performance_manager::PerformanceManagerRegistry::GetInstance()) registry->MaybeCreatePageNodeForWebContents(web_contents); @@ -1265,4 +1349,36 @@ ContentBrowserClientQt::AllowWebBluetooth(content::BrowserContext *browser_conte return content::ContentBrowserClient::AllowWebBluetoothResult::BLOCK_GLOBALLY_DISABLED; } +content::WebAuthenticationDelegate *ContentBrowserClientQt::GetWebAuthenticationDelegate() +{ + static base::NoDestructor<WebAuthenticationDelegateQt> delegate; + return delegate.get(); +} + +#if !BUILDFLAG(IS_ANDROID) +std::unique_ptr<content::AuthenticatorRequestClientDelegate> +ContentBrowserClientQt::GetWebAuthenticationRequestDelegate( + content::RenderFrameHost *render_frame_host) +{ + return std::make_unique<AuthenticatorRequestClientDelegateQt>(render_frame_host); +} +#endif + +void ContentBrowserClientQt::GetMediaDeviceIDSalt(content::RenderFrameHost *rfh, + const net::SiteForCookies & /*site_for_cookies*/, + const blink::StorageKey & /*storage_key*/, + base::OnceCallback<void(bool, const std::string&)> callback) +{ +#if BUILDFLAG(ENABLE_WEBRTC) + content::BrowserContext *browser_context = rfh->GetBrowserContext(); + if (!browser_context->IsOffTheRecord()) { + ProfileQt *profile = static_cast<ProfileQt *>(browser_context); + std::string mediaId = profile->GetMediaDeviceIDSalt(); + std::move(callback).Run(true, mediaId); + return; + } +#endif + std::move(callback).Run(false, ""); +} + } // namespace QtWebEngineCore |