diff options
Diffstat (limited to 'src/core/content_browser_client_qt.cpp')
-rw-r--r-- | src/core/content_browser_client_qt.cpp | 1538 |
1 files changed, 1055 insertions, 483 deletions
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index ee420d258..28ed6ef7c 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -1,254 +1,207 @@ -/**************************************************************************** -** -** 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/memory/ptr_util.h" -#include "base/optional.h" -#include "base/strings/utf_string_conversions.h" -#include "base/message_loop/message_loop.h" -#include "base/task/post_task.h" -#include "base/threading/thread_restrictions.h" -#if QT_CONFIG(webengine_spellchecker) -#include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" -#endif -#include "components/guest_view/browser/guest_view_base.h" -#include "components/network_hints/browser/network_hints_message_filter.h" -#include "content/browser/renderer_host/render_view_host_delegate.h" -#include "content/common/url_schemes.h" -#include "content/public/browser/browser_task_traits.h" +#include "base/files/file_util.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/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" +#include "components/performance_manager/public/performance_manager.h" +#include "content/browser/web_contents/web_contents_impl.h" +#include "content/public/browser/browser_main_runner.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/child_process_security_policy.h" #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/resource_dispatcher_host.h" -#include "content/public/browser/resource_dispatcher_host_delegate.h" -#include "content/public/browser/storage_partition.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/service_manager_connection.h" -#include "content/public/common/service_names.mojom.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" -#include "media/media_buildflags.h" #include "extensions/buildflags/buildflags.h" -#include "mojo/public/cpp/bindings/binding.h" -#include "mojo/public/cpp/bindings/binding_set.h" -#include "printing/buildflags/buildflags.h" -#include "qtwebengine/browser/qtwebengine_content_browser_overlay_manifest.h" -#include "qtwebengine/browser/qtwebengine_content_renderer_overlay_manifest.h" -#include "qtwebengine/browser/qtwebengine_packaged_service_manifest.h" -#include "qtwebengine/browser/qtwebengine_renderer_manifest.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 "services/proxy_resolver/proxy_resolver_service.h" -#include "services/service_manager/public/cpp/connector.h" -#include "services/service_manager/public/cpp/service.h" -#include "services/service_manager/sandbox/switches.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/mojom/insecure_input/insecure_input_service.mojom.h" +#include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_switches.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_share_group.h" -#include "ui/gl/gpu_timing.h" #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" #include "browser_message_filter_qt.h" #include "certificate_error_controller.h" -#include "certificate_error_controller_p.h" #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/network_delegate_qt.h" -#include "net/url_request_context_getter_qt.h" +#include "net/cookie_monster_delegate_qt.h" +#include "net/custom_url_loader_factory.h" +#include "net/proxying_restricted_cookie_manager_qt.h" +#include "net/proxying_url_loader_factory_qt.h" +#include "net/system_network_context_manager.h" #include "platform_notification_service_qt.h" -#if QT_CONFIG(webengine_printing_and_pdf) -#include "printing/printing_message_filter_qt.h" -#endif #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 "service/service_qt.h" +#include "select_file_dialog_factory_qt.h" #include "type_conversion.h" +#include "web_contents_adapter_client.h" +#include "web_contents_adapter.h" #include "web_contents_delegate_qt.h" +#include "web_contents_view_qt.h" #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" +#include "api/qwebengineurlrequestinfo_p.h" -#if defined(Q_OS_LINUX) -#include "global_descriptors_qt.h" -#include "ui/base/resource/resource_bundle.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" -#include "renderer_host/pepper/pepper_host_factory_qt.h" +#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_geolocation) -#include "location_provider_qt.h" +#if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions) +#include "chrome/browser/media/webrtc/webrtc_logging_controller.h" +#endif + +#if defined(Q_OS_LINUX) +#include "global_descriptors_qt.h" #endif #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "extensions/extensions_browser_client_qt.h" +#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/guest_view/extensions_guest_view_message_filter.h" -#include "extensions/browser/io_thread_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.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" +#include "extensions/browser/url_loader_factory_manager.h" +#include "extensions/browser/view_type_utils.h" #include "extensions/common/constants.h" -#include "common/extensions/extensions_client_qt.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.h" +#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 "net/plugin_response_interceptor_url_loader_throttle.h" #endif -#include <QGuiApplication> -#include <QLocale> -#ifndef QT_NO_OPENGL -# include <QOpenGLContext> +#if QT_CONFIG(webengine_webchannel) +#include "qtwebengine/browser/qtwebchannel.mojom.h" +#include "renderer_host/web_channel_ipc_transport_host.h" #endif -#include <qpa/qplatformnativeinterface.h> -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE - -namespace QtWebEngineCore { - -class QtShareGLContext : public gl::GLContext { -public: - QtShareGLContext(QOpenGLContext *qtContext) - : gl::GLContext(0) - , m_handle(0) - { - QString platform = qApp->platformName().toLower(); - QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); - if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); - } else if (platform == QLatin1String("cocoa")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); - else if (platform == QLatin1String("qnx")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland") - || platform == QLatin1String("wayland-egl")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("windows")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), qtContext); - } else { - qFatal("%s platform not yet supported", platform.toLatin1().constData()); - // Add missing platforms once they work. - Q_UNREACHABLE(); - } - } - - void* GetHandle() override { return m_handle; } - bool WasAllocatedUsingRobustnessExtension() override - { -#if QT_CONFIG(opengl) - if (QOpenGLContext *context = qt_gl_global_share_context()) - return context->format().testOption(QSurfaceFormat::ResetNotification); +#if BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW) +#include "printing/pdf_stream_delegate_qt.h" +#include "printing/print_view_manager_qt.h" #endif - return false; - } - // We don't care about the rest, this context shouldn't be used except for its handle. - bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override { Q_UNREACHABLE(); return false; } - bool MakeCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - void ReleaseCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); } - bool IsCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - scoped_refptr<gl::GPUTimingClient> CreateGPUTimingClient() override - { - return nullptr; - } - const gfx::ExtensionSet& GetExtensions() override - { - static const gfx::ExtensionSet s_emptySet; - return s_emptySet; - } - void ResetExtensions() override - { - } +#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" -private: - void *m_handle; -}; +#include "printing/pdf_document_helper_client_qt.h" +#endif -class ShareGroupQtQuick : public gl::GLShareGroup { -public: - gl::GLContext* GetContext() override { return m_shareContextQtQuick.get(); } - void AboutToAddFirstContext() override; +#if BUILDFLAG(ENABLE_PDF) && BUILDFLAG(ENABLE_EXTENSIONS) +#include "extensions/pdf_iframe_navigation_throttle_qt.h" +#endif -private: - scoped_refptr<QtShareGLContext> m_shareContextQtQuick; -}; +#include <QGuiApplication> +#include <QStandardPaths> -void ShareGroupQtQuick::AboutToAddFirstContext() +// Implement IsHandledProtocol as declared in //url/url_util_qt.h. +namespace url { +bool IsHandledProtocol(base::StringPiece scheme) { -#ifndef QT_NO_OPENGL - // This currently has to be setup by ::main in all applications using QQuickWebEngineView with delegated rendering. - QOpenGLContext *shareContext = qt_gl_global_share_context(); - if (!shareContext) { - qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure to call QtWebEngine::initialize() in your main() function."); - } - m_shareContextQtQuick = new QtShareGLContext(shareContext); + static const char *const kProtocolList[] = { + url::kHttpScheme, + url::kHttpsScheme, +#if BUILDFLAG(ENABLE_WEBSOCKETS) + url::kWsScheme, + url::kWssScheme, +#endif // BUILDFLAG(ENABLE_WEBSOCKETS) + url::kFileScheme, + content::kChromeDevToolsScheme, +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::kExtensionScheme, #endif + content::kChromeUIScheme, + url::kDataScheme, + url::kAboutScheme, + url::kBlobScheme, + url::kFileSystemScheme, + url::kQrcScheme, + }; + + for (const char *protocol : kProtocolList) { + if (scheme == protocol) + return true; + } + if (const auto cs = url::CustomScheme::FindScheme(scheme)) + return true; + return false; +} +} + +namespace QtWebEngineCore { + +void MaybeAddThrottle( + std::unique_ptr<content::NavigationThrottle> maybe_throttle, + std::vector<std::unique_ptr<content::NavigationThrottle>>* throttles) { + if (maybe_throttle) + throttles->push_back(std::move(maybe_throttle)); } ContentBrowserClientQt::ContentBrowserClientQt() - : m_browserMainParts(0) { } @@ -256,67 +209,47 @@ ContentBrowserClientQt::~ContentBrowserClientQt() { } -content::BrowserMainParts *ContentBrowserClientQt::CreateBrowserMainParts(const content::MainFunctionParams&) +std::unique_ptr<content::BrowserMainParts> ContentBrowserClientQt::CreateBrowserMainParts(bool) { - m_browserMainParts = new BrowserMainPartsQt(); - return m_browserMainParts; + Q_ASSERT(!m_browserMainParts); + auto browserMainParts = std::make_unique<BrowserMainPartsQt>(); + m_browserMainParts = browserMainParts.get(); + return browserMainParts; } -void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* host, - service_manager::mojom::ServiceRequest *service_request) +void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost *host) { const int id = host->GetID(); Profile *profile = Profile::FromBrowserContext(host->GetBrowserContext()); - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&net::URLRequestContextGetter::GetURLRequestContext, base::Unretained(profile->GetRequestContext())), - base::BindOnce(&ContentBrowserClientQt::AddNetworkHintsMessageFilter, base::Unretained(this), id)); + +#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 + + // Allow requesting custom schemes. + const auto policy = content::ChildProcessSecurityPolicy::GetInstance(); + const auto profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + policy->GrantRequestScheme(id, scheme.toStdString()); // FIXME: Add a settings variable to enable/disable the file scheme. - content::ChildProcessSecurityPolicy::GetInstance()->GrantRequestScheme(id, url::kFileScheme); - static_cast<ProfileQt*>(host->GetBrowserContext())->m_profileAdapter->userResourceController()->renderProcessStartedWithHost(host); + policy->GrantRequestScheme(id, url::kFileScheme); + profileAdapter->userResourceController()->renderProcessStartedWithHost(host); host->AddFilter(new BrowserMessageFilterQt(id, profile)); -#if QT_CONFIG(webengine_printing_and_pdf) - host->AddFilter(new PrintingMessageFilterQt(host->GetID())); -#endif #if BUILDFLAG(ENABLE_EXTENSIONS) - host->AddFilter(new extensions::ExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::IOThreadExtensionMessageFilter(host->GetID(), host->GetBrowserContext())); - host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(host->GetID(), host->GetBrowserContext())); + host->AddFilter(new extensions::ExtensionMessageFilter(id, profile)); + host->AddFilter(new extensions::MessagingAPIMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS bool is_incognito_process = profile->IsOffTheRecord(); - qtwebengine::mojom::RendererConfigurationAssociatedPtr renderer_configuration; + mojo::AssociatedRemote<qtwebengine::mojom::RendererConfiguration> renderer_configuration; host->GetChannel()->GetRemoteAssociatedInterface(&renderer_configuration); renderer_configuration->SetInitialConfiguration(is_incognito_process); - - service_manager::mojom::ServicePtr service; - *service_request = mojo::MakeRequest(&service); - service_manager::mojom::PIDReceiverPtr pid_receiver; - service_manager::Identity renderer_identity = host->GetChildIdentity(); - ServiceQt::GetInstance()->connector()->RegisterServiceInstance( - service_manager::Identity("qtwebengine_renderer", - renderer_identity.instance_group(), - renderer_identity.instance_id(), - base::Token::CreateRandom()), - std::move(service), mojo::MakeRequest(&pid_receiver)); -} - -void ContentBrowserClientQt::ResourceDispatcherHostCreated() -{ -#if BUILDFLAG(ENABLE_EXTENSIONS) - m_resourceDispatcherHostDelegate.reset(new ResourceDispatcherHostDelegateQt); -#else - m_resourceDispatcherHostDelegate.reset(new content::ResourceDispatcherHostDelegate); -#endif - content::ResourceDispatcherHost::Get()->SetDelegate(m_resourceDispatcherHostDelegate.get()); -} - -gl::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() -{ - if (!m_shareGroupQtQuick.get()) - m_shareGroupQtQuick = new ShareGroupQtQuick; - return m_shareGroupQtQuick.get(); } content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() @@ -324,88 +257,46 @@ content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() return MediaCaptureDevicesDispatcher::GetInstance(); } -void ContentBrowserClientQt::OverrideWebkitPrefs(content::RenderViewHost *rvh, content::WebPreferences *web_prefs) +void ContentBrowserClientQt::OverrideWebkitPrefs(content::WebContents *webContents, blink::web_pref::WebPreferences *web_prefs) { - if (content::WebContents *webContents = rvh->GetDelegate()->GetAsWebContents()) { #if BUILDFLAG(ENABLE_EXTENSIONS) - if (guest_view::GuestViewBase::IsGuest(webContents)) - return; -#endif // BUILDFLAG(ENABLE_EXTENSIONS) - WebContentsDelegateQt* delegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); - if (delegate) - delegate->overrideWebPreferences(webContents, web_prefs); - } -} - -scoped_refptr<content::QuotaPermissionContext> ContentBrowserClientQt::CreateQuotaPermissionContext() -{ - return new QuotaPermissionContextQt; -} - -void ContentBrowserClientQt::GetQuotaSettings(content::BrowserContext* context, - content::StoragePartition* partition, - storage::OptionalQuotaSettingsCallback callback) -{ - storage::GetNominalDynamicSettings(partition->GetPath(), context->IsOffTheRecord(), storage::GetDefaultDiskInfoHelper(), std::move(callback)); -} + if (guest_view::GuestViewBase::IsGuest(webContents)) + return; -// Copied from chrome/browser/ssl/ssl_error_handler.cc: -static int IsCertErrorFatal(int cert_error) -{ - switch (cert_error) { - case net::ERR_CERT_COMMON_NAME_INVALID: - case net::ERR_CERT_DATE_INVALID: - case net::ERR_CERT_AUTHORITY_INVALID: - case net::ERR_CERT_WEAK_SIGNATURE_ALGORITHM: - case net::ERR_CERT_WEAK_KEY: - case net::ERR_CERT_NAME_CONSTRAINT_VIOLATION: - case net::ERR_CERT_VALIDITY_TOO_LONG: - case net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED: - case net::ERR_CERT_SYMANTEC_LEGACY: - return false; - case net::ERR_CERT_CONTAINS_ERRORS: - case net::ERR_CERT_REVOKED: - case net::ERR_CERT_INVALID: - case net::ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY: - case net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN: - return true; - default: - NOTREACHED(); - } - return true; + WebContentsViewQt *view = WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView()); + if (!view->client()) + return; +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + WebContentsDelegateQt* delegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); + if (delegate) + delegate->overrideWebPreferences(webContents, web_prefs); } void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webContents, int cert_error, const net::SSLInfo &ssl_info, const GURL &request_url, - content::ResourceType resource_type, + bool is_main_frame_request, bool strict_enforcement, - bool expired_previous_decision, - const base::Callback<void(content::CertificateRequestResultType)> &callback) + base::OnceCallback<void(content::CertificateRequestResultType)> callback) { WebContentsDelegateQt* contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); - QSharedPointer<CertificateErrorController> errorController( - new CertificateErrorController( - new CertificateErrorControllerPrivate( - cert_error, - ssl_info, - request_url, - resource_type, - !IsCertErrorFatal(cert_error), - strict_enforcement, - callback))); + QSharedPointer<CertificateErrorController> errorController(new CertificateErrorController( + cert_error, ssl_info, request_url, is_main_frame_request, strict_enforcement, std::move(callback))); contentsDelegate->allowCertificateError(errorController); } -void ContentBrowserClientQt::SelectClientCertificate(content::WebContents *webContents, - net::SSLCertRequestInfo *certRequestInfo, - net::ClientCertIdentityList clientCerts, - std::unique_ptr<content::ClientCertificateDelegate> delegate) + +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))); @@ -414,14 +305,16 @@ void ContentBrowserClientQt::SelectClientCertificate(content::WebContents *webCo } else { delegate->ContinueWithCertificate(nullptr, nullptr); } + // This is consistent with AwContentBrowserClient and CastContentBrowserClient: + return base::OnceClosure(); } -std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertStore(content::ResourceContext *resource_context) +std::unique_ptr<net::ClientCertStore> ContentBrowserClientQt::CreateClientCertStore(content::BrowserContext *browser_context) { - if (!resource_context) + if (!browser_context) return nullptr; - return ProfileIODataQt::FromResourceContext(resource_context)->CreateClientCertStore(); + return ProfileIODataQt::FromBrowserContext(browser_context)->CreateClientCertStore(); } std::string ContentBrowserClientQt::GetApplicationLocale() @@ -441,26 +334,43 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c url::CustomScheme::SaveSchemes(command_line); std::string processType = command_line->GetSwitchValueASCII(switches::kProcessType); - if (processType == service_manager::switches::kZygoteProcess) - command_line->AppendSwitchASCII(switches::kLang, GetApplicationLocale()); + if (processType == switches::kZygoteProcess) + command_line->AppendSwitchASCII(switches::kLang, WebEngineLibraryInfo::getApplicationLocale()); } void ContentBrowserClientQt::GetAdditionalWebUISchemes(std::vector<std::string>* additional_schemes) { + ContentBrowserClient::GetAdditionalWebUISchemes(additional_schemes); additional_schemes->push_back(content::kChromeDevToolsScheme); } void ContentBrowserClientQt::GetAdditionalViewSourceSchemes(std::vector<std::string>* additional_schemes) { - additional_schemes->push_back(content::kChromeDevToolsScheme); + ContentBrowserClient::GetAdditionalViewSourceSchemes(additional_schemes); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + additional_schemes->push_back(extensions::kExtensionScheme); +#endif +} + +void ContentBrowserClientQt::GetAdditionalAllowedSchemesForFileSystem(std::vector<std::string>* additional_schemes) +{ + ContentBrowserClient::GetAdditionalAllowedSchemesForFileSystem(additional_schemes); + additional_schemes->push_back(content::kChromeDevToolsScheme); + additional_schemes->push_back(content::kChromeUIScheme); +} + +std::unique_ptr<ui::SelectFilePolicy> +ContentBrowserClientQt::CreateSelectFilePolicy(content::WebContents *web_contents) +{ + return std::make_unique<SelectFilePolicyQt>(web_contents); } #if defined(Q_OS_LINUX) void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base::CommandLine& command_line, int child_process_id, content::PosixFileDescriptorInfo* mappings) { - const std::string &locale = GetApplicationLocale(); - const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(locale, true); - if (locale_file_path.empty()) + const base::FilePath &locale_file_path = ui::ResourceBundle::GetSharedInstance().GetLocaleFilePath(WebEngineLibraryInfo::getResolvedLocale()); + if (locale_file_path.empty() || !base::PathExists(locale_file_path)) return; // Open pak file of the current locale in the Browser process and pass its file descriptor to the sandboxed @@ -471,123 +381,142 @@ void ContentBrowserClientQt::GetAdditionalMappedFilesForChildProcess(const base: } #endif -#if QT_CONFIG(webengine_pepper_plugins) -void ContentBrowserClientQt::DidCreatePpapiPlugin(content::BrowserPpapiHost* browser_host) -{ - browser_host->GetPpapiHost()->AddHostFactoryFilter( - std::make_unique<QtWebEngineCore::PepperHostFactoryQt>(browser_host)); -} -#endif - -content::DevToolsManagerDelegate* ContentBrowserClientQt::GetDevToolsManagerDelegate() -{ - return new DevToolsManagerDelegateQt; -} - -content::PlatformNotificationService *ContentBrowserClientQt::GetPlatformNotificationService(content::BrowserContext *browser_context) +std::unique_ptr<content::DevToolsManagerDelegate> ContentBrowserClientQt::CreateDevToolsManagerDelegate() { - ProfileQt *profile = static_cast<ProfileQt *>(browser_context); - if (!profile) - return nullptr; - return profile->platformNotificationService(); + return std::make_unique<DevToolsManagerDelegateQt>(); } -// This is a really complicated way of doing absolutely nothing, but Mojo demands it: -class ServiceDriver - : public blink::mojom::InsecureInputService - , public content::WebContentsUserData<ServiceDriver> +void ContentBrowserClientQt::BindHostReceiverForRenderer(content::RenderProcessHost *render_process_host, + mojo::GenericPendingReceiver receiver) { -public: - static void CreateForRenderFrameHost(content::RenderFrameHost *renderFrameHost) - { - content::WebContents* web_contents = content::WebContents::FromRenderFrameHost(renderFrameHost); - if (!web_contents) - return; - CreateForWebContents(web_contents); - - } - static ServiceDriver* FromRenderFrameHost(content::RenderFrameHost *renderFrameHost) - { - content::WebContents* web_contents = content::WebContents::FromRenderFrameHost(renderFrameHost); - if (!web_contents) - return nullptr; - return FromWebContents(web_contents); - } - static void BindInsecureInputService(blink::mojom::InsecureInputServiceRequest request, content::RenderFrameHost *render_frame_host) - { - CreateForRenderFrameHost(render_frame_host); - ServiceDriver *driver = FromRenderFrameHost(render_frame_host); - - if (driver) - driver->BindInsecureInputServiceRequest(std::move(request)); - } - void BindInsecureInputServiceRequest(blink::mojom::InsecureInputServiceRequest request) - { - m_insecureInputServiceBindings.AddBinding(this, std::move(request)); +#if QT_CONFIG(webengine_spellchecker) + if (auto host_receiver = receiver.As<spellcheck::mojom::SpellCheckHost>()) { + SpellCheckHostChromeImpl::Create(render_process_host->GetID(), std::move(host_receiver)); + return; } - - // blink::mojom::InsecureInputService: - void DidEditFieldInInsecureContext() override - { } - -private: - WEB_CONTENTS_USER_DATA_KEY_DECL(); - explicit ServiceDriver(content::WebContents* /*web_contents*/) { } - friend class content::WebContentsUserData<ServiceDriver>; - mojo::BindingSet<blink::mojom::InsecureInputService> m_insecureInputServiceBindings; -}; - -WEB_CONTENTS_USER_DATA_KEY_IMPL(ServiceDriver) - -void ContentBrowserClientQt::InitFrameInterfaces() -{ - m_frameInterfaces = std::make_unique<service_manager::BinderRegistry>(); - m_frameInterfacesParameterized = std::make_unique<service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>>(); - m_frameInterfacesParameterized->AddInterface(base::BindRepeating(&ServiceDriver::BindInsecureInputService)); +#endif } -void ContentBrowserClientQt::BindInterfaceRequestFromFrame(content::RenderFrameHost* render_frame_host, - const std::string& interface_name, - mojo::ScopedMessagePipeHandle interface_pipe) +static void BindNetworkHintsHandler(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<network_hints::mojom::NetworkHintsHandler> receiver) { - if (!m_frameInterfaces.get() && !m_frameInterfacesParameterized.get()) - InitFrameInterfaces(); + network_hints::SimpleNetworkHintsHandlerImpl::Create(frame_host, std::move(receiver)); +} - if (!m_frameInterfacesParameterized->TryBindInterface(interface_name, &interface_pipe, render_frame_host)) - m_frameInterfaces->TryBindInterface(interface_name, &interface_pipe); +#if BUILDFLAG(ENABLE_EXTENSIONS) +static void BindMimeHandlerService(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<extensions::mime_handler::MimeHandlerService> + receiver) { + auto *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) + return; + auto *guest_view = extensions::MimeHandlerViewGuest::FromWebContents(web_contents); + if (!guest_view) + return; + extensions::MimeHandlerServiceImpl::Create(guest_view->GetStreamWeakPtr(), std::move(receiver)); } -void ContentBrowserClientQt::RegisterIOThreadServiceHandlers(content::ServiceManagerConnection *connection) -{ - connection->AddServiceRequestHandler( - "qtwebengine", - ServiceQt::GetInstance()->CreateServiceQtRequestHandler()); +static void BindBeforeUnloadControl(content::RenderFrameHost *frame_host, + mojo::PendingReceiver<extensions::mime_handler::BeforeUnloadControl> + receiver) { + auto *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + if (!web_contents) + return; + auto *guest_view = extensions::MimeHandlerViewGuest::FromWebContents(web_contents); + if (!guest_view) + return; + guest_view->FuseBeforeUnloadControl(std::move(receiver)); } +#endif -void ContentBrowserClientQt::RegisterOutOfProcessServices(content::ContentBrowserClient::OutOfProcessServiceMap *services) +void ContentBrowserClientQt::RegisterBrowserInterfaceBindersForFrame( + content::RenderFrameHost *render_frame_host, + mojo::BinderMapWithContext<content::RenderFrameHost *> *map) { - (*services)[proxy_resolver::mojom::kProxyResolverServiceName] = - base::BindRepeating(&base::ASCIIToUTF16, "V8 Proxy Resolver"); + map->Add<network_hints::mojom::NetworkHintsHandler>(base::BindRepeating(&BindNetworkHintsHandler)); +#if BUILDFLAG(ENABLE_EXTENSIONS) + map->Add<extensions::mime_handler::MimeHandlerService>(base::BindRepeating(&BindMimeHandlerService)); + map->Add<extensions::mime_handler::BeforeUnloadControl>(base::BindRepeating(&BindBeforeUnloadControl)); + const GURL &site = render_frame_host->GetSiteInstance()->GetSiteURL(); + if (!site.SchemeIs(extensions::kExtensionScheme)) + return; + content::BrowserContext *browser_context = render_frame_host->GetProcess()->GetBrowserContext(); + auto *extension = extensions::ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(site.host()); + if (!extension) + return; + extensions::ExtensionsBrowserClient::Get()->RegisterBrowserInterfaceBindersForFrame(map, + render_frame_host, + extension); +#else + Q_UNUSED(render_frame_host); +#endif } -base::Optional<service_manager::Manifest> ContentBrowserClientQt::GetServiceManifestOverlay(base::StringPiece name) +void ContentBrowserClientQt::ExposeInterfacesToRenderer(service_manager::BinderRegistry *registry, + blink::AssociatedInterfaceRegistry *associated_registry, + content::RenderProcessHost *render_process_host) { - if (name == content::mojom::kBrowserServiceName) { - return GetQtWebEngineContentBrowserOverlayManifest(); - } else if (name == content::mojom::kPackagedServicesServiceName) { - service_manager::Manifest overlay; - overlay.packaged_services = GetQtWebEnginePackagedServiceManifests(); - return overlay; - } else if (name == content::mojom::kRendererServiceName) { - return GetQtWebEngineContentRendererOverlayManifest(); - } - - return base::nullopt; + if (auto *manager = performance_manager::PerformanceManagerRegistry::GetInstance()) + manager->CreateProcessNodeAndExposeInterfacesToRendererProcess(registry, render_process_host); +#if BUILDFLAG(ENABLE_EXTENSIONS) + 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 } -std::vector<service_manager::Manifest> ContentBrowserClientQt::GetExtraServiceManifests() +void ContentBrowserClientQt::RegisterAssociatedInterfaceBindersForRenderFrameHost( + content::RenderFrameHost &rfh, + blink::AssociatedInterfaceRegistry &associated_registry) { - return std::vector<service_manager::Manifest>{GetQtWebEngineRendererManifest()}; +#if QT_CONFIG(webengine_webchannel) + 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) + 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) + 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 + 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( @@ -639,24 +568,13 @@ std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystem } #endif -scoped_refptr<net::URLRequestContextGetter> GetSystemRequestContextOnUIThread() -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return scoped_refptr<net::URLRequestContextGetter>( - ProfileAdapter::createDefaultProfileAdapter()->profile()->GetRequestContext()); -} - -void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context) +device::GeolocationManager *ContentBrowserClientQt::GetGeolocationManager() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - content::RenderProcessHost* host = content::RenderProcessHost::FromID(render_process_id); - if (!host) - return; - - content::BrowserMessageFilter *network_hints_message_filter = - new network_hints::NetworkHintsMessageFilter(render_process_id); - host->AddFilter(network_hints_message_filter); +#if BUILDFLAG(IS_MAC) + return m_browserMainParts->GetGeolocationManager(); +#else + return nullptr; +#endif } bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() @@ -666,108 +584,304 @@ bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() return false; } -bool ContentBrowserClientQt::AllowGetCookie(const GURL &url, - const GURL &first_party, - const net::CookieList & /*cookie_list*/, - content::ResourceContext *context, - int /*render_process_id*/, - int /*render_frame_id*/) +bool ContentBrowserClientQt::WillCreateRestrictedCookieManager(network::mojom::RestrictedCookieManagerRole role, + content::BrowserContext *browser_context, + const url::Origin & /*origin*/, + const net::IsolationInfo & /*isolation_info*/, + bool /*is_service_worker*/, + int /*process_id*/, + int /*routing_id*/, + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> *receiver) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(first_party), toQt(url)); -} + mojo::PendingReceiver<network::mojom::RestrictedCookieManager> orig_receiver = std::move(*receiver); -bool ContentBrowserClientQt::AllowSetCookie(const GURL &url, - const GURL &first_party, - const net::CanonicalCookie& /*cookie*/, - content::ResourceContext *context, - int /*render_process_id*/, - int /*render_frame_id*/) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canSetCookie(toQt(first_party), QByteArray(), toQt(url)); -} + mojo::PendingRemote<network::mojom::RestrictedCookieManager> target_rcm_remote; + *receiver = target_rcm_remote.InitWithNewPipeAndPassReceiver(); -bool ContentBrowserClientQt::AllowAppCache(const GURL &manifest_url, - const GURL &first_party, - content::ResourceContext *context) -{ - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(first_party), toQt(manifest_url)); + ProxyingRestrictedCookieManagerQt::CreateAndBind( + ProfileIODataQt::FromBrowserContext(browser_context), + std::move(target_rcm_remote), + std::move(orig_receiver)); + + return false; // only made a proxy, still need the actual impl to be made. } -bool ContentBrowserClientQt::AllowServiceWorker(const GURL &scope, - const GURL &first_party, - content::ResourceContext *context, - base::RepeatingCallback<content::WebContents*()> wc_getter) +content::AllowServiceWorkerResult +ContentBrowserClientQt::AllowServiceWorker(const GURL &scope, + const net::SiteForCookies &site_for_cookies, + const absl::optional<url::Origin> & /*top_frame_origin*/, + const GURL & /*script_url*/, + content::BrowserContext *context) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return content::AllowServiceWorkerResult::No(); // FIXME: Chrome also checks if javascript is enabled here to check if has been disabled since the service worker // was started. - return ProfileIODataQt::FromResourceContext(context)->canGetCookies(toQt(first_party), toQt(scope)); + return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(site_for_cookies.first_party_url()), toQt(scope)) + ? content::AllowServiceWorkerResult::Yes() + : content::AllowServiceWorkerResult::No(); } // We control worker access to FS and indexed-db using cookie permissions, this is mirroring Chromium's logic. void ContentBrowserClientQt::AllowWorkerFileSystem(const GURL &url, - content::ResourceContext *context, - const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/, - base::Callback<void(bool)> callback) + content::BrowserContext *context, + const std::vector<content::GlobalRenderFrameHostId> &/*render_frames*/, + base::OnceCallback<void(bool)> callback) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - callback.Run(ProfileIODataQt::FromResourceContext(context)->canSetCookie(toQt(url), QByteArray(), toQt(url))); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return std::move(callback).Run(false); + std::move(callback).Run( + static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url))); } bool ContentBrowserClientQt::AllowWorkerIndexedDB(const GURL &url, - content::ResourceContext *context, - const std::vector<content::GlobalFrameRoutingId> &/*render_frames*/) + content::BrowserContext *context, + const std::vector<content::GlobalRenderFrameHostId> &/*render_frames*/) { - DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - return ProfileIODataQt::FromResourceContext(context)->canSetCookie(toQt(url), QByteArray(), toQt(url)); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!context || context->ShutdownStarted()) + return false; + return static_cast<ProfileQt *>(context)->profileAdapter()->cookieStore()->d_func()->canAccessCookies(toQt(url), toQt(url)); } static void LaunchURL(const GURL& url, - const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter, - ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture) + base::RepeatingCallback<content::WebContents*()> web_contents_getter, + ui::PageTransition page_transition, + network::mojom::WebSandboxFlags sandbox_flags, + bool is_main_frame, bool has_user_gesture) { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - content::WebContents* webContents = web_contents_getter.Run(); + content::WebContents* webContents = std::move(web_contents_getter).Run(); if (!webContents) return; + + custom_handlers::ProtocolHandlerRegistry *protocolHandlerRegistry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(webContents->GetBrowserContext()); + if (protocolHandlerRegistry && protocolHandlerRegistry->IsHandledProtocol(url.scheme())) + return; + + // Sandbox flag logic from chrome/browser/chrome_content_browser_client.cc: + if (!is_main_frame) { + using SandboxFlags = network::mojom::WebSandboxFlags; + auto allow = [&](SandboxFlags flag) { + return (sandbox_flags & flag) == SandboxFlags::kNone; + }; + bool allowed = (allow(SandboxFlags::kPopups)) || + (allow(SandboxFlags::kTopNavigation)) || + (allow(SandboxFlags::kTopNavigationByUserActivation) && + has_user_gesture); + + if (!allowed) { + 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."); + return; + } + } + } + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } -bool ContentBrowserClientQt::HandleExternalProtocol( - const GURL &url, - content::ResourceRequestInfo::WebContentsGetter web_contents_getter, - int child_id, +bool ContentBrowserClientQt::HandleExternalProtocol(const GURL &url, + base::RepeatingCallback<content::WebContents*()> web_contents_getter, + 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 std::string &method, - const net::HttpRequestHeaders &headers, - network::mojom::URLLoaderFactoryRequest *factory_request, - network::mojom::URLLoaderFactory *&out_factory) + const absl::optional<url::Origin> &initiating_origin, + content::RenderFrameHost *initiator_document, + mojo::PendingRemote<network::mojom::URLLoaderFactory> *out_factory) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - Q_UNUSED(child_id); + Q_UNUSED(frame_tree_node_id); + Q_UNUSED(is_in_fenced_frame_tree); Q_UNUSED(navigation_data); - Q_UNUSED(method); - Q_UNUSED(headers); - - base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(&LaunchURL, - url, - web_contents_getter, - page_transition, - is_main_frame, - has_user_gesture)); + Q_UNUSED(initiating_origin); + Q_UNUSED(initiator_document); + Q_UNUSED(out_factory); + + content::GetUIThreadTaskRunner({})->PostTask(FROM_HERE, + base::BindOnce(&LaunchURL, + url, + std::move(web_contents_getter), + page_transition, + sandbox_flags, + is_primary_main_frame, + has_user_gesture)); return true; } +namespace { +// Copied from chrome/browser/chrome_content_browser_client.cc +class ProtocolHandlerThrottle : public blink::URLLoaderThrottle +{ +public: + explicit ProtocolHandlerThrottle(custom_handlers::ProtocolHandlerRegistry *protocol_handler_registry) + : protocol_handler_registry_(protocol_handler_registry) + { + } + ~ProtocolHandlerThrottle() override = default; + + void WillStartRequest(network::ResourceRequest *request, bool *defer) override + { + TranslateUrl(&request->url); + } + + void WillRedirectRequest(net::RedirectInfo *redirect_info, + const network::mojom::URLResponseHead &response_head, + bool *defer, + std::vector<std::string> *to_be_removed_headers, + net::HttpRequestHeaders *modified_headers, + net::HttpRequestHeaders *modified_cors_exempt_headers) override + { + TranslateUrl(&redirect_info->new_url); + } + +private: + void TranslateUrl(GURL *url) + { + if (!protocol_handler_registry_->IsHandledProtocol(url->scheme())) + return; + GURL translated_url = protocol_handler_registry_->Translate(*url); + if (!translated_url.is_empty()) + *url = translated_url; + } + + custom_handlers::ProtocolHandlerRegistry *protocol_handler_registry_; +}; +} // namespace + +std::vector<std::unique_ptr<blink::URLLoaderThrottle>> +ContentBrowserClientQt::CreateURLLoaderThrottles( + const network::ResourceRequest &request, content::BrowserContext *browser_context, + const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) +{ + std::vector<std::unique_ptr<blink::URLLoaderThrottle>> result; + result.push_back(std::make_unique<ProtocolHandlerThrottle>( + ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + request.destination, frame_tree_node_id)); +#endif + return result; +} + +WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition) +{ + if (ui::PageTransitionIsRedirect(transition)) + return WebContentsAdapterClient::RedirectNavigation; + + int32_t qualifier = ui::PageTransitionGetQualifier(transition); + + if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK) + return WebContentsAdapterClient::BackForwardNavigation; + + ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition); + + switch (strippedTransition) { + case ui::PAGE_TRANSITION_LINK: + return WebContentsAdapterClient::LinkNavigation; + case ui::PAGE_TRANSITION_TYPED: + return WebContentsAdapterClient::TypedNavigation; + case ui::PAGE_TRANSITION_FORM_SUBMIT: + return WebContentsAdapterClient::FormSubmittedNavigation; + case ui::PAGE_TRANSITION_RELOAD: + return WebContentsAdapterClient::ReloadNavigation; + default: + return WebContentsAdapterClient::OtherNavigation; + } +} + +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 (handle->IsExternalProtocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(handle->GetURL().scheme()))) + return false; + + bool navigationAccepted = true; + + WebContentsAdapterClient *client = + WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(source)->GetView())->client(); + if (!client) + return false; + + // Redirects might not be reflected in transition_type at this point (see also chrome/.../web_navigation_api_helpers.cc) + 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(handle->GetURL()), + navigationAccepted, + handle->IsInPrimaryMainFrame(), + handle->IsFormSubmission()); + return !navigationAccepted; +} + +std::vector<std::unique_ptr<content::NavigationThrottle>> ContentBrowserClientQt::CreateThrottlesForNavigation( + content::NavigationHandle *navigation_handle) +{ + std::vector<std::unique_ptr<content::NavigationThrottle>> throttles; + throttles.push_back(std::make_unique<navigation_interception::InterceptNavigationThrottle>( + navigation_handle, + base::BindRepeating(&navigationThrottleCallback), + navigation_interception::SynchronyMode::kSync)); + +#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; +} + +bool ContentBrowserClientQt::IsHandledURL(const GURL &url) +{ + return url::IsHandledProtocol(url.scheme()); +} + +bool ContentBrowserClientQt::HasCustomSchemeHandler(content::BrowserContext *browser_context, + const std::string &scheme) +{ + if (custom_handlers::ProtocolHandlerRegistry *protocol_handler_registry = + ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context)) { + return protocol_handler_registry->IsHandledProtocol(scheme); + } + + return false; +} + +bool ContentBrowserClientQt::HasErrorPage(int httpStatusCode, content::WebContents *contents) +{ + if (contents) { + WebEngineSettings *settings = nullptr; + WebContentsDelegateQt *delegate = + static_cast<WebContentsDelegateQt*>(contents->GetDelegate()); + if (delegate) + settings = delegate->webEngineSettings(); + if (settings && !settings->testAttribute(QWebEngineSettings::ErrorPageEnabled)) + return false; + } + // Use an internal error page, if we have one for the status code. + return error_page::LocalizedError::HasStrings(error_page::Error::kHttpErrorDomain, httpStatusCode); +} + std::unique_ptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegate( const net::AuthChallengeInfo &authInfo, content::WebContents *web_contents, @@ -797,16 +911,474 @@ bool ContentBrowserClientQt::ShouldUseProcessPerSite(content::BrowserContext* br return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url); } +bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserContext *browser_context, + const GURL &effective_site_url) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (effective_site_url.SchemeIs(extensions::kExtensionScheme)) + return true; +#endif + return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_context, effective_site_url); +} + +bool ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, + const GURL &site_url) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (site_url.SchemeIs(extensions::kExtensionScheme)) + return false; +#endif + return ContentBrowserClient::ShouldUseSpareRenderProcessHost(browser_context, site_url); +} + +bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, bool is_embedded_origin_secure) +{ + if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) + return true; +#if BUILDFLAG(ENABLE_EXTENSIONS) + return scheme == extensions::kExtensionScheme; +#else + return false; +#endif +} + +bool ContentBrowserClientQt::DoesSchemeAllowCrossOriginSharedWorker(const std::string &scheme) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + // Extensions are allowed to start cross-origin shared workers. + return scheme == extensions::kExtensionScheme; +#else + return false; +#endif +} + +void ContentBrowserClientQt::OverrideURLLoaderFactoryParams(content::BrowserContext *browser_context, + const url::Origin &origin, + bool is_for_isolated_world, + network::mojom::URLLoaderFactoryParams *factory_params) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::URLLoaderFactoryManager::OverrideURLLoaderFactoryParams( + browser_context, origin, is_for_isolated_world, factory_params); +#endif +} + 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())); } -std::string ContentBrowserClientQt::GetProduct() const +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() { QString productName(qApp->applicationName() % '/' % qApp->applicationVersion()); return productName.toStdString(); } +scoped_refptr<network::SharedURLLoaderFactory> ContentBrowserClientQt::GetSystemSharedURLLoaderFactory() +{ + if (!SystemNetworkContextManager::GetInstance()) + return nullptr; + return SystemNetworkContextManager::GetInstance()->GetSharedURLLoaderFactory(); +} + +network::mojom::NetworkContext *ContentBrowserClientQt::GetSystemNetworkContext() +{ + if (!SystemNetworkContextManager::GetInstance()) + return nullptr; + return SystemNetworkContextManager::GetInstance()->GetContext(); +} + +void ContentBrowserClientQt::OnNetworkServiceCreated(network::mojom::NetworkService *network_service) +{ + if (!SystemNetworkContextManager::GetInstance()) + SystemNetworkContextManager::CreateInstance(); + + // Need to set up global NetworkService state before anything else uses it. + SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(network_service); +} + +void ContentBrowserClientQt::ConfigureNetworkContextParams( + content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path, + network::mojom::NetworkContextParams *network_context_params, + cert_verifier::mojom::CertVerifierCreationParams *cert_verifier_creation_params) +{ + ProfileIODataQt::FromBrowserContext(context)->ConfigureNetworkContextParams(in_memory, relative_partition_path, + network_context_params, cert_verifier_creation_params); + + mojo::PendingRemote<network::mojom::CookieManager> cookie_manager_remote; + network_context_params->cookie_manager = cookie_manager_remote.InitWithNewPipeAndPassReceiver(); + ProfileIODataQt::FromBrowserContext(context)->cookieDelegate()->setMojoCookieManager(std::move(cookie_manager_remote)); +} + +std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDirectory() +{ + return { + toFilePath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)), + toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) }; +} + +void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, + ukm::SourceIdObj ukm_source_id, + NonNetworkURLLoaderFactoryMap *factories) +{ + content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); + Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionNavigationURLLoaderFactory(profile, ukm_source_id, + !!extensions::WebViewGuest::FromWebContents(web_contents))); +#endif +} + +void ContentBrowserClientQt::RegisterNonNetworkWorkerMainResourceURLLoaderFactories(content::BrowserContext *browser_context, + NonNetworkURLLoaderFactoryMap *factories) +{ + Profile *profile = Profile::FromBrowserContext(browser_context); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionWorkerMainResourceURLLoaderFactory(browser_context)); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) +} + +void ContentBrowserClientQt::RegisterNonNetworkServiceWorkerUpdateURLLoaderFactories(content::BrowserContext* browser_context, + NonNetworkURLLoaderFactoryMap* factories) +{ + Profile *profile = Profile::FromBrowserContext(browser_context); + ProfileAdapter *profileAdapter = static_cast<ProfileQt *>(profile)->profileAdapter(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) { + if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(scheme.toStdString())) { + if (cs->flags & url::CustomScheme::ServiceWorkersAllowed) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + } + } + +#if BUILDFLAG(ENABLE_EXTENSIONS) + factories->emplace( + extensions::kExtensionScheme, + extensions::CreateExtensionServiceWorkerScriptURLLoaderFactory(browser_context)); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) +} + +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(); + + for (const QByteArray &scheme : profileAdapter->customUrlSchemes()) + factories->emplace(scheme.toStdString(), CreateCustomURLLoaderFactory(profileAdapter)); + + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + GURL url; + if (web_contents) + url = web_contents->GetVisibleURL(); + + bool is_background_page = false; +#if BUILDFLAG(ENABLE_EXTENSIONS) + is_background_page = extensions::GetViewType(web_contents) == extensions::mojom::ViewType::kExtensionBackgroundPage; +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + + // Install file scheme if necessary: + bool install_file_scheme = false; + if (web_contents && !is_background_page) { + const std::string scheme = url.scheme(); + install_file_scheme = base::Contains(url::GetLocalSchemes(), scheme); + if (const url::CustomScheme *cs = url::CustomScheme::FindScheme(scheme)) + install_file_scheme = cs->flags & (url::CustomScheme::LocalAccessAllowed | url::CustomScheme::Local); + } + + if (install_file_scheme && factories->find(url::kFileScheme) == factories->end()) { + auto file_factory = content::CreateFileURLLoaderFactory(profile->GetPath(), + profile->GetSharedCorsOriginAccessList()); + factories->emplace(url::kFileScheme, std::move(file_factory)); + } + +#if BUILDFLAG(ENABLE_EXTENSIONS) + auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id, render_frame_id); + if (factory) + factories->emplace(extensions::kExtensionScheme, std::move(factory)); + + if (!web_contents) + return; + + extensions::ExtensionWebContentsObserverQt *web_observer = + extensions::ExtensionWebContentsObserverQt::FromWebContents(web_contents); + if (!web_observer) + return; + + const extensions::Extension *extension = web_observer->GetExtensionFromFrame(frame_host, false); + if (!extension) + return; + + std::vector<std::string> allowed_webui_hosts; + // Support for chrome:// scheme if appropriate. + if ((extension->is_extension() || extension->is_platform_app()) && + extensions::Manifest::IsComponentLocation(extension->location())) { + // Components of chrome that are implemented as extensions or platform apps + // are allowed to use chrome://resources/ and chrome://theme/ URLs. + allowed_webui_hosts.emplace_back(content::kChromeUIResourcesHost); + } + if (!allowed_webui_hosts.empty()) { + factories->emplace(content::kChromeUIScheme, + content::CreateWebUIURLLoaderFactory(frame_host, + content::kChromeUIScheme, + std::move(allowed_webui_hosts))); + } +#endif +} + +base::flat_set<std::string> ContentBrowserClientQt::GetPluginMimeTypesWithExternalHandlers( + content::BrowserContext *browser_context) +{ + base::flat_set<std::string> mime_types; +#if BUILDFLAG(ENABLE_EXTENSIONS) + ProfileQt *profile = static_cast<ProfileQt *>(browser_context); + for (const std::string &extension_id : MimeTypesHandler::GetMIMETypeAllowlist()) { + const extensions::Extension *extension = + extensions::ExtensionRegistry::Get(browser_context) + ->enabled_extensions() + .GetByID(extension_id); + // The allowed extension may not be installed, so we have to nullptr + // check |extension|. + if (!extension || + (profile->IsOffTheRecord() && !extensions::util::IsIncognitoEnabled( + extension_id, browser_context))) { + continue; + } + if (MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension)) { + for (const auto &supported_mime_type : handler->mime_type_set()) + mime_types.insert(supported_mime_type); + } + } +#endif +#if BUILDFLAG(ENABLE_PDF) + mime_types.insert("application/x-google-chrome-pdf"); +#endif + return mime_types; +} + +bool ContentBrowserClientQt::WillCreateURLLoaderFactory( + content::BrowserContext *browser_context, + content::RenderFrameHost *frame, + int render_process_id, + URLLoaderFactoryType type, + const url::Origin &request_initiator, + absl::optional<int64_t> navigation_id, + ukm::SourceIdObj ukm_source_id, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, + mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient> *header_client, + bool *bypass_redirect_checks, + bool *disable_secure_dns, + network::mojom::URLLoaderFactoryOverridePtr *factory_override, + scoped_refptr<base::SequencedTaskRunner> navigation_response_task_runner) +{ + Q_UNUSED(render_process_id); + Q_UNUSED(type); + Q_UNUSED(request_initiator); + Q_UNUSED(navigation_id); + Q_UNUSED(ukm_source_id); + Q_UNUSED(header_client); + Q_UNUSED(bypass_redirect_checks); + Q_UNUSED(disable_secure_dns); + Q_UNUSED(factory_override); + auto adapter = static_cast<ProfileQt *>(browser_context)->profileAdapter(); + auto proxied_receiver = std::move(*factory_receiver); + 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; +} + +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) +{ + 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) + + return interceptors; +} + +bool ContentBrowserClientQt::WillInterceptWebSocket(content::RenderFrameHost *frame) +{ + 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); + 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->Insert(extension->id(), site_instance->GetProcess()->GetID()); +#endif +} + +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); + + return nullptr; +} + +content::ContentBrowserClient::AllowWebBluetoothResult +ContentBrowserClientQt::AllowWebBluetooth(content::BrowserContext *browser_context, + const url::Origin &requesting_origin, + const url::Origin &embedding_origin) +{ + DCHECK(browser_context); + 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 |