| // Copyright 2022 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/preloading/prefetch/prefetch_network_context.h" |
| |
| #include "base/command_line.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "content/browser/preloading/prefetch/prefetch_network_context_client.h" |
| #include "content/browser/preloading/prefetch/prefetch_proxy_configurator.h" |
| #include "content/browser/preloading/prefetch/prefetch_service.h" |
| #include "content/browser/preloading/prefetch/prefetch_type.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/network_service_instance.h" |
| #include "content/public/browser/prefetch_service_delegate.h" |
| #include "content/public/browser/storage_partition.h" |
| #include "content/public/common/content_constants.h" |
| #include "content/public/common/content_switches.h" |
| #include "content/public/common/user_agent.h" |
| #include "mojo/public/cpp/bindings/pending_receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "mojo/public/cpp/bindings/self_owned_receiver.h" |
| #include "net/base/isolation_info.h" |
| #include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h" |
| #include "services/network/public/cpp/shared_url_loader_factory.h" |
| #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" |
| #include "services/network/public/mojom/cookie_manager.mojom.h" |
| #include "services/network/public/mojom/network_context.mojom.h" |
| #include "services/network/public/mojom/url_loader_factory.mojom.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace content { |
| |
| PrefetchNetworkContext::PrefetchNetworkContext( |
| PrefetchService* prefetch_service, |
| const PrefetchType& prefetch_type) |
| : prefetch_service_(prefetch_service), prefetch_type_(prefetch_type) {} |
| |
| PrefetchNetworkContext::~PrefetchNetworkContext() = default; |
| |
| network::mojom::NetworkContext* PrefetchNetworkContext::GetNetworkContext() |
| const { |
| DCHECK(network_context_); |
| return network_context_.get(); |
| } |
| |
| network::mojom::URLLoaderFactory* |
| PrefetchNetworkContext::GetURLLoaderFactory() { |
| if (!url_loader_factory_) { |
| if (prefetch_type_.IsIsolatedNetworkContextRequired()) { |
| CreateIsolatedURLLoaderFactory(); |
| DCHECK(network_context_); |
| } else { |
| // TODO(crbug.com/1278103): Use |
| // RenderFrameHost::CreateNetworkServiceDefaultFactory if possible. |
| url_loader_factory_ = prefetch_service_->GetBrowserContext() |
| ->GetDefaultStoragePartition() |
| ->GetURLLoaderFactoryForBrowserProcess(); |
| } |
| } |
| DCHECK(url_loader_factory_); |
| return url_loader_factory_.get(); |
| } |
| |
| network::mojom::CookieManager* PrefetchNetworkContext::GetCookieManager() { |
| DCHECK(prefetch_type_.IsIsolatedNetworkContextRequired()); |
| DCHECK(network_context_); |
| if (!cookie_manager_) |
| network_context_->GetCookieManager( |
| cookie_manager_.BindNewPipeAndPassReceiver()); |
| |
| return cookie_manager_.get(); |
| } |
| |
| void PrefetchNetworkContext::CloseIdleConnections() { |
| if (network_context_) |
| network_context_->CloseIdleConnections(base::DoNothing()); |
| } |
| |
| void PrefetchNetworkContext::CreateIsolatedURLLoaderFactory() { |
| DCHECK(prefetch_type_.IsIsolatedNetworkContextRequired()); |
| |
| network_context_.reset(); |
| url_loader_factory_.reset(); |
| |
| PrefetchServiceDelegate* delegate = |
| prefetch_service_->GetPrefetchServiceDelegate(); |
| |
| auto context_params = network::mojom::NetworkContextParams::New(); |
| context_params->user_agent = content::GetReducedUserAgent( |
| base::CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kUseMobileUserAgent), |
| delegate ? delegate->GetMajorVersionNumber() : ""); |
| context_params->cert_verifier_params = GetCertVerifierParams( |
| cert_verifier::mojom::CertVerifierCreationParams::New()); |
| context_params->cors_exempt_header_list = {kCorsExemptPurposeHeaderName}; |
| context_params->cookie_manager_params = |
| network::mojom::CookieManagerParams::New(); |
| |
| if (delegate) { |
| context_params->accept_language = delegate->GetAcceptLanguageHeader(); |
| } |
| |
| context_params->http_cache_enabled = true; |
| DCHECK(!context_params->http_cache_directory); |
| |
| if (prefetch_type_.IsProxyRequired() && |
| !prefetch_type_.IsProxyBypassedForTesting()) { |
| PrefetchProxyConfigurator* prefetch_proxy_configurator = |
| prefetch_service_->GetPrefetchProxyConfigurator(); |
| DCHECK(prefetch_proxy_configurator); |
| |
| context_params->initial_custom_proxy_config = |
| prefetch_proxy_configurator->CreateCustomProxyConfig(); |
| context_params->custom_proxy_connection_observer_remote = |
| prefetch_proxy_configurator->NewProxyConnectionObserverRemote(); |
| |
| // Register a client config receiver so that updates to the set of proxy |
| // hosts or proxy headers will be updated. |
| mojo::Remote<network::mojom::CustomProxyConfigClient> config_client; |
| context_params->custom_proxy_config_client_receiver = |
| config_client.BindNewPipeAndPassReceiver(); |
| prefetch_proxy_configurator->AddCustomProxyConfigClient( |
| std::move(config_client), base::DoNothing()); |
| } |
| |
| // Explicitly disallow network service features which could cause a privacy |
| // leak. |
| context_params->enable_certificate_reporting = false; |
| context_params->enable_expect_ct_reporting = false; |
| context_params->enable_domain_reliability = false; |
| |
| CreateNetworkContextInNetworkService( |
| network_context_.BindNewPipeAndPassReceiver(), std::move(context_params)); |
| |
| if (prefetch_type_.IsProxyRequired() && |
| !prefetch_type_.IsProxyBypassedForTesting()) { |
| // Configure a context client to ensure Web Reports and other privacy leak |
| // surfaces won't be enabled. |
| mojo::PendingRemote<network::mojom::NetworkContextClient> client_remote; |
| mojo::MakeSelfOwnedReceiver( |
| std::make_unique<PrefetchNetworkContextClient>(), |
| client_remote.InitWithNewPipeAndPassReceiver()); |
| network_context_->SetClient(std::move(client_remote)); |
| } |
| |
| mojo::PendingRemote<network::mojom::URLLoaderFactory> isolated_factory_remote; |
| |
| CreateNewURLLoaderFactory( |
| isolated_factory_remote.InitWithNewPipeAndPassReceiver(), absl::nullopt); |
| url_loader_factory_ = network::SharedURLLoaderFactory::Create( |
| std::make_unique<network::WrapperPendingSharedURLLoaderFactory>( |
| std::move(isolated_factory_remote))); |
| } |
| |
| void PrefetchNetworkContext::CreateNewURLLoaderFactory( |
| mojo::PendingReceiver<network::mojom::URLLoaderFactory> pending_receiver, |
| absl::optional<net::IsolationInfo> isolation_info) { |
| DCHECK(prefetch_type_.IsIsolatedNetworkContextRequired()); |
| DCHECK(network_context_); |
| |
| auto factory_params = network::mojom::URLLoaderFactoryParams::New(); |
| factory_params->process_id = network::mojom::kBrowserProcessId; |
| factory_params->is_trusted = true; |
| factory_params->is_corb_enabled = false; |
| if (isolation_info) { |
| factory_params->isolation_info = *isolation_info; |
| } |
| |
| network_context_->CreateURLLoaderFactory(std::move(pending_receiver), |
| std::move(factory_params)); |
| } |
| |
| } // namespace content |