diff options
Diffstat (limited to 'src/core/content_browser_client_qt.cpp')
-rw-r--r-- | src/core/content_browser_client_qt.cpp | 415 |
1 files changed, 369 insertions, 46 deletions
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 29b6e09ed..baa08fa7e 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -41,14 +41,18 @@ #include "base/memory/ptr_util.h" #include "base/optional.h" +#include "base/path_service.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" +#include "chrome/browser/custom_handlers/protocol_handler_registry.h" #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h" #if QT_CONFIG(webengine_spellchecker) #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" #endif +#include "components/navigation_interception/intercept_navigation_throttle.h" +#include "components/navigation_interception/navigation_params.h" #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" @@ -58,6 +62,7 @@ #include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/client_certificate_delegate.h" #include "content/public/browser/media_observer.h" +#include "content/public/browser/network_service_instance.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" @@ -66,14 +71,18 @@ #include "content/public/browser/storage_partition.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_user_data.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/url_loader_throttle.h" #include "content/public/common/user_agent.h" #include "media/media_buildflags.h" #include "extensions/buildflags/buildflags.h" +#include "extensions/browser/extension_protocols.h" +#include "extensions/browser/guest_view/web_view/web_view_guest.h" #include "mojo/public/cpp/bindings/binding.h" #include "mojo/public/cpp/bindings/binding_set.h" #include "mojo/public/cpp/bindings/remote.h" @@ -84,6 +93,8 @@ #include "qtwebengine/browser/qtwebengine_renderer_manifest.h" #include "net/ssl/client_cert_identity.h" #include "net/ssl/client_cert_store.h" +#include "services/network/network_service.h" +#include "services/network/public/cpp/features.h" #include "services/service_manager/public/cpp/connector.h" #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/sandbox/switches.h" @@ -109,8 +120,12 @@ #include "devtools_manager_delegate_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/qrc_url_scheme_handler.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" @@ -121,6 +136,7 @@ #include "renderer_host/user_resource_controller_host.h" #include "service/service_qt.h" #include "type_conversion.h" +#include "web_contents_adapter_client.h" #include "web_contents_delegate_qt.h" #include "web_engine_context.h" #include "web_engine_library_info.h" @@ -143,13 +159,16 @@ #endif #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "extensions/extensions_browser_client_qt.h" +#include "content/public/browser/file_url_loader.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/common/constants.h" + #include "common/extensions/extensions_client_qt.h" -#include "renderer_host/resource_dispatcher_host_delegate_qt.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 #if BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) @@ -159,6 +178,7 @@ #include <QGuiApplication> #include <QLocale> +#include <QStandardPaths> #if QT_CONFIG(opengl) # include <QOpenGLContext> # include <QOpenGLExtraFunctions> @@ -276,22 +296,26 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* { 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)); + + host->AddFilter(new network_hints::NetworkHintsMessageFilter(id)); + + // 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())); + host->AddFilter(new PrintingMessageFilterQt(id)); #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::IOThreadExtensionMessageFilter(id, profile)); + host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(id, profile)); #endif //ENABLE_EXTENSIONS bool is_incognito_process = profile->IsOffTheRecord(); @@ -313,11 +337,7 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost* 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()); } @@ -459,12 +479,20 @@ void ContentBrowserClientQt::AppendExtraCommandLineSwitches(base::CommandLine* c 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); +} + +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); } #if defined(Q_OS_LINUX) @@ -659,19 +687,6 @@ std::unique_ptr<device::LocationProvider> ContentBrowserClientQt::OverrideSystem } #endif -void ContentBrowserClientQt::AddNetworkHintsMessageFilter(int render_process_id, net::URLRequestContext *context) -{ - 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); -} - bool ContentBrowserClientQt::ShouldEnableStrictSiteIsolation() { // mirroring AwContentBrowserClient, CastContentBrowserClient and @@ -687,13 +702,17 @@ bool ContentBrowserClientQt::WillCreateRestrictedCookieManager(network::mojom::R int routing_id, network::mojom::RestrictedCookieManagerRequest *request) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::IO}, - base::BindOnce(&ProfileIODataQt::CreateRestrictedCookieManager, - ProfileIODataQt::FromBrowserContext(browser_context)->getWeakPtrOnUIThread(), - std::move(*request), - role, origin, is_service_worker, process_id, routing_id)); - return true; + network::mojom::RestrictedCookieManagerRequest orig_request = std::move(*request); + network::mojom::RestrictedCookieManagerPtrInfo target_rcm_info; + *request = mojo::MakeRequest(&target_rcm_info); + + ProxyingRestrictedCookieManagerQt::CreateAndBind( + ProfileIODataQt::FromBrowserContext(browser_context), + std::move(target_rcm_info), + is_service_worker, process_id, routing_id, + std::move(orig_request)); + + return false; // only made a proxy, still need the actual impl to be made. } bool ContentBrowserClientQt::AllowAppCacheOnIO(const GURL &manifest_url, @@ -751,6 +770,14 @@ static void LaunchURL(const GURL& url, content::WebContents* webContents = web_contents_getter.Run(); if (!webContents) return; + + ProtocolHandlerRegistry* protocolHandlerRegistry = + ProtocolHandlerRegistryFactory::GetForBrowserContext( + webContents->GetBrowserContext()); + if (protocolHandlerRegistry && + protocolHandlerRegistry->IsHandledProtocol(url.scheme())) + return; + WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(webContents->GetDelegate()); contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } @@ -766,7 +793,7 @@ bool ContentBrowserClientQt::HandleExternalProtocol( bool has_user_gesture, network::mojom::URLLoaderFactoryPtr *out_factory) { - Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); +// Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_UNUSED(child_id); Q_UNUSED(navigation_data); Q_UNUSED(out_factory); @@ -822,30 +849,126 @@ private: std::vector<std::unique_ptr<content::URLLoaderThrottle>> ContentBrowserClientQt::CreateURLLoaderThrottlesOnIO( - const network::ResourceRequest & /*request*/, content::ResourceContext *resource_context, + const network::ResourceRequest &request, content::ResourceContext *resource_context, const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, - content::NavigationUIData * /*navigation_ui_data*/, int /*frame_tree_node_id*/) + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) { std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; ProfileIODataQt *ioData = ProfileIODataQt::FromResourceContext(resource_context); result.push_back(std::make_unique<ProtocolHandlerThrottle< scoped_refptr<ProtocolHandlerRegistry::IOThreadDelegate>>>( - ioData->protocolHandlerRegistryIOThreadDelegate())); + ioData->protocolHandlerRegistryIOThreadDelegate())); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + resource_context, request.resource_type, frame_tree_node_id)); +#endif return result; } std::vector<std::unique_ptr<content::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) + const base::RepeatingCallback<content::WebContents *()> & /*wc_getter*/, + content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id) { std::vector<std::unique_ptr<content::URLLoaderThrottle>> result; result.push_back(std::make_unique<ProtocolHandlerThrottle<ProtocolHandlerRegistry *>>( - ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); + ProtocolHandlerRegistryFactory::GetForBrowserContext(browser_context))); +#if BUILDFLAG(ENABLE_EXTENSIONS) + result.push_back(std::make_unique<PluginResponseInterceptorURLLoaderThrottle>( + browser_context, request.resource_type, 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::WebContents *source, + const navigation_interception::NavigationParams ¶ms) +{ + // 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. + ProfileQt *profile = static_cast<ProfileQt *>(source->GetBrowserContext()); + if (params.is_external_protocol() && !profile->profileAdapter()->urlSchemeHandler(toQByteArray(params.url().scheme()))) + return false; + int navigationRequestAction = WebContentsAdapterClient::AcceptRequest; + WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(source->GetDelegate()); + WebContentsAdapterClient *client = delegate->adapterClient(); + client->navigationRequested(pageTransitionToNavigationType(params.transition_type()), + toQt(params.url()), + navigationRequestAction, + params.is_main_frame()); + return navigationRequestAction == static_cast<int>(WebContentsAdapterClient::IgnoreRequest); +} + +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)); + return throttles; +} + +bool ContentBrowserClientQt::IsHandledURL(const GURL &url) +{ + static const char *const kProtocolList[] = { + url::kFileScheme, + content::kChromeDevToolsScheme, +#if BUILDFLAG(ENABLE_EXTENSIONS) + extensions::kExtensionScheme, +#endif + content::kChromeUIScheme, + url::kDataScheme, + url::kAboutScheme, +#if !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kFtpScheme, +#endif // !BUILDFLAG(DISABLE_FTP_SUPPORT) + url::kBlobScheme, + url::kFileSystemScheme, + url::kQrcScheme, + }; + + // We don't check url.IsCustom() here because we don't + // know if the registered protocol is installed in the + // profile that will be used to load the URL. + + const std::string scheme = url.scheme(); + + for (const char *protocol : kProtocolList) { + if (scheme == protocol) + return true; + } + return net::URLRequest::IsHandledProtocol(scheme); +} + std::unique_ptr<content::LoginDelegate> ContentBrowserClientQt::CreateLoginDelegate( const net::AuthChallengeInfo &authInfo, content::WebContents *web_contents, @@ -875,6 +998,16 @@ bool ContentBrowserClientQt::ShouldUseProcessPerSite(content::BrowserContext* br return ContentBrowserClient::ShouldUseProcessPerSite(browser_context, effective_url); } +bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserOrResourceContext browser_or_resource_context, + const GURL &effective_site_url) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (effective_site_url.SchemeIs(extensions::kExtensionScheme)) + return true; +#endif + return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_or_resource_context, effective_site_url); +} + 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) @@ -887,4 +1020,194 @@ std::string ContentBrowserClientQt::GetProduct() 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 (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + + if (!SystemNetworkContextManager::GetInstance()) + SystemNetworkContextManager::CreateInstance(); + + // Need to set up global NetworkService state before anything else uses it. + SystemNetworkContextManager::GetInstance()->OnNetworkServiceCreated(network_service); +} + +network::mojom::NetworkContextPtr ContentBrowserClientQt::CreateNetworkContext(content::BrowserContext *context, + bool in_memory, + const base::FilePath &relative_partition_path) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return nullptr; + + network::mojom::NetworkContextPtr network_context; + // ### do we need to pass in_memory and relative_partition_path to ProfileIODataQt::CreateNetworkContextParams() ? + network::mojom::NetworkContextParamsPtr context_params = ProfileIODataQt::FromBrowserContext(context)->CreateNetworkContextParams(); + content::GetNetworkService()->CreateNetworkContext(mojo::MakeRequest(&network_context), std::move(context_params)); + + network::mojom::CookieManagerPtrInfo cookie_manager_info; + network_context->GetCookieManager(mojo::MakeRequest(&cookie_manager_info)); + ProfileIODataQt::FromBrowserContext(context)->cookieDelegate()->setMojoCookieManager(std::move(cookie_manager_info)); + + return network_context; +} + +std::vector<base::FilePath> ContentBrowserClientQt::GetNetworkContextsParentDirectory() +{ + return { + toFilePath(QStandardPaths::writableLocation(QStandardPaths::DataLocation)), + toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) }; +} + +void ContentBrowserClientQt::RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id, + NonNetworkURLLoaderFactoryMap *factories) +{ + DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); + 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, + !!extensions::WebViewGuest::FromWebContents(web_contents))); +#endif +} + +#if BUILDFLAG(ENABLE_EXTENSIONS) +namespace { +// The FileURLLoaderFactory provided to the extension background pages. +// Checks with the ChildProcessSecurityPolicy to validate the file access. +class FileURLLoaderFactory : public network::mojom::URLLoaderFactory +{ +public: + explicit FileURLLoaderFactory(int child_id) : child_id_(child_id) {} + +private: + // network::mojom::URLLoaderFactory: + void CreateLoaderAndStart(network::mojom::URLLoaderRequest loader, + int32_t routing_id, + int32_t request_id, + uint32_t options, + const network::ResourceRequest& request, + network::mojom::URLLoaderClientPtr client, + const net::MutableNetworkTrafficAnnotationTag &traffic_annotation) override + { + if (!content::ChildProcessSecurityPolicy::GetInstance()->CanRequestURL(child_id_, request.url)) { + client->OnComplete(network::URLLoaderCompletionStatus(net::ERR_ACCESS_DENIED)); + return; + } + content::CreateFileURLLoader(request, std::move(loader), std::move(client), + /* observer */ nullptr, + /* allow_directory_listing */ false); + } + + void Clone(network::mojom::URLLoaderFactoryRequest loader) override + { + bindings_.AddBinding(this, std::move(loader)); + } + + int child_id_; + mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; + DISALLOW_COPY_AND_ASSIGN(FileURLLoaderFactory); +}; +} // namespace +#endif + +void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, + NonNetworkURLLoaderFactoryMap *factories) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return; + 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)); + +#if BUILDFLAG(ENABLE_EXTENSIONS) + auto factory = extensions::CreateExtensionURLLoaderFactory(render_process_id, render_frame_id); + if (factory) + factories->emplace(extensions::kExtensionScheme, std::move(factory)); + + content::RenderFrameHost *frame_host = content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents *web_contents = content::WebContents::FromRenderFrameHost(frame_host); + 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::CreateWebUIURLLoader(frame_host, + content::kChromeUIScheme, + std::move(allowed_webui_hosts))); + } + // Support for file:// scheme when approved by ChildProcessSecurityPolicy. + // FIXME: Not needed after switching to using transferable url loaders and guest views. + factories->emplace(url::kFileScheme, std::make_unique<FileURLLoaderFactory>(render_process_id)); +#endif +} + +bool ContentBrowserClientQt::WillCreateURLLoaderFactory( + content::BrowserContext *browser_context, + content::RenderFrameHost *frame, + int render_process_id, + bool is_navigation, + bool is_download, + const url::Origin &request_initiator, + mojo::PendingReceiver<network::mojom::URLLoaderFactory> *factory_receiver, + network::mojom::TrustedURLLoaderHeaderClientPtrInfo *header_client, + bool *bypass_redirect_checks) +{ + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) + return false; + + auto proxied_receiver = std::move(*factory_receiver); + network::mojom::URLLoaderFactoryPtrInfo target_factory_info; + *factory_receiver = mojo::MakeRequest(&target_factory_info); + int process_id = is_navigation ? 0 : render_process_id; + + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::IO}, + base::BindOnce(&ProxyingURLLoaderFactoryQt::CreateProxy, process_id, + browser_context->GetResourceContext(), + std::move(proxied_receiver), + std::move(target_factory_info))); + return true; +} + } // namespace QtWebEngineCore |