|  | // Copyright 2017 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/network_service_client.h" | 
|  |  | 
|  | #include <utility> | 
|  |  | 
|  | #include "base/bind.h" | 
|  | #include "base/feature_list.h" | 
|  | #include "base/task/post_task.h" | 
|  | #include "base/threading/sequence_bound.h" | 
|  | #include "base/unguessable_token.h" | 
|  | #include "content/browser/browsing_data/clear_site_data_handler.h" | 
|  | #include "content/browser/renderer_host/frame_tree_node.h" | 
|  | #include "content/browser/ssl/ssl_manager.h" | 
|  | #include "content/browser/webrtc/webrtc_connections_observer.h" | 
|  | #include "content/public/browser/browser_context.h" | 
|  | #include "content/public/browser/browser_task_traits.h" | 
|  | #include "content/public/browser/browser_thread.h" | 
|  | #include "content/public/browser/child_process_security_policy.h" | 
|  | #include "content/public/browser/content_browser_client.h" | 
|  | #include "content/public/browser/global_request_id.h" | 
|  | #include "content/public/browser/network_service_instance.h" | 
|  | #include "content/public/common/content_client.h" | 
|  | #include "content/public/common/content_features.h" | 
|  | #include "content/public/common/network_service_util.h" | 
|  | #include "services/network/public/cpp/network_switches.h" | 
|  | #include "services/network/public/mojom/network_context.mojom.h" | 
|  | #include "third_party/abseil-cpp/absl/types/optional.h" | 
|  | #include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h" | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | #include "base/android/content_uri_utils.h" | 
|  | #endif | 
|  |  | 
|  | #if defined(OS_MAC) | 
|  | #include "base/task/current_thread.h" | 
|  | #endif | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | NetworkServiceClient::NetworkServiceClient() | 
|  | #if defined(OS_ANDROID) | 
|  | : app_status_listener_(base::android::ApplicationStatusListener::New( | 
|  | base::BindRepeating(&NetworkServiceClient::OnApplicationStateChange, | 
|  | base::Unretained(this)))) | 
|  | #endif | 
|  | { | 
|  |  | 
|  | #if defined(OS_MAC) | 
|  | if (base::CurrentUIThread::IsSet())  // Not set in some unit tests. | 
|  | net::CertDatabase::GetInstance()->StartListeningForKeychainEvents(); | 
|  | #endif | 
|  |  | 
|  | if (IsOutOfProcessNetworkService()) { | 
|  | net::CertDatabase::GetInstance()->AddObserver(this); | 
|  | memory_pressure_listener_ = std::make_unique<base::MemoryPressureListener>( | 
|  | FROM_HERE, base::BindRepeating(&NetworkServiceClient::OnMemoryPressure, | 
|  | base::Unretained(this))); | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | DCHECK(!net::NetworkChangeNotifier::CreateIfNeeded()); | 
|  | GetNetworkService()->GetNetworkChangeManager( | 
|  | network_change_manager_.BindNewPipeAndPassReceiver()); | 
|  | net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 
|  | net::NetworkChangeNotifier::AddMaxBandwidthObserver(this); | 
|  | net::NetworkChangeNotifier::AddIPAddressObserver(this); | 
|  | net::NetworkChangeNotifier::AddDNSObserver(this); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | webrtc_connections_observer_ = | 
|  | std::make_unique<content::WebRtcConnectionsObserver>(base::BindRepeating( | 
|  | &NetworkServiceClient::OnPeerToPeerConnectionsCountChange, | 
|  | base::Unretained(this))); | 
|  | } | 
|  |  | 
|  | NetworkServiceClient::~NetworkServiceClient() { | 
|  | if (IsOutOfProcessNetworkService()) { | 
|  | net::CertDatabase::GetInstance()->RemoveObserver(this); | 
|  | #if defined(OS_ANDROID) | 
|  | net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 
|  | net::NetworkChangeNotifier::RemoveMaxBandwidthObserver(this); | 
|  | net::NetworkChangeNotifier::RemoveIPAddressObserver(this); | 
|  | net::NetworkChangeNotifier::RemoveDNSObserver(this); | 
|  | #endif | 
|  | } | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnCertDBChanged() { | 
|  | GetNetworkService()->OnCertDBChanged(); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnMemoryPressure( | 
|  | base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { | 
|  | GetNetworkService()->OnMemoryPressure(memory_pressure_level); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnPeerToPeerConnectionsCountChange(uint32_t count) { | 
|  | GetNetworkService()->OnPeerToPeerConnectionsCountChange(count); | 
|  | } | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | void NetworkServiceClient::OnApplicationStateChange( | 
|  | base::android::ApplicationState state) { | 
|  | GetNetworkService()->OnApplicationStateChange(state); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnConnectionTypeChanged( | 
|  | net::NetworkChangeNotifier::ConnectionType type) { | 
|  | network_change_manager_->OnNetworkChanged( | 
|  | false /* dns_changed */, false /* ip_address_changed */, | 
|  | true /* connection_type_changed */, network::mojom::ConnectionType(type), | 
|  | false /* connection_subtype_changed */, | 
|  | network::mojom::ConnectionSubtype( | 
|  | net::NetworkChangeNotifier::GetConnectionSubtype())); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnMaxBandwidthChanged( | 
|  | double max_bandwidth_mbps, | 
|  | net::NetworkChangeNotifier::ConnectionType type) { | 
|  | // The connection subtype change will trigger a max bandwidth change in the | 
|  | // network service notifier. | 
|  | network_change_manager_->OnNetworkChanged( | 
|  | false /* dns_changed */, false /* ip_address_changed */, | 
|  | false /* connection_type_changed */, network::mojom::ConnectionType(type), | 
|  | true /* connection_subtype_changed */, | 
|  | network::mojom::ConnectionSubtype( | 
|  | net::NetworkChangeNotifier::GetConnectionSubtype())); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnIPAddressChanged() { | 
|  | network_change_manager_->OnNetworkChanged( | 
|  | false /* dns_changed */, true /* ip_address_changed */, | 
|  | false /* connection_type_changed */, | 
|  | network::mojom::ConnectionType( | 
|  | net::NetworkChangeNotifier::GetConnectionType()), | 
|  | false /* connection_subtype_changed */, | 
|  | network::mojom::ConnectionSubtype( | 
|  | net::NetworkChangeNotifier::GetConnectionSubtype())); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnDNSChanged() { | 
|  | network_change_manager_->OnNetworkChanged( | 
|  | true /* dns_changed */, false /* ip_address_changed */, | 
|  | false /* connection_type_changed */, | 
|  | network::mojom::ConnectionType( | 
|  | net::NetworkChangeNotifier::GetConnectionType()), | 
|  | false /* connection_subtype_changed */, | 
|  | network::mojom::ConnectionSubtype( | 
|  | net::NetworkChangeNotifier::GetConnectionSubtype())); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> | 
|  | NetworkServiceClient::BindURLLoaderNetworkServiceObserver() { | 
|  | mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver> remote; | 
|  | url_loader_network_service_observers_.Add( | 
|  | this, remote.InitWithNewPipeAndPassReceiver()); | 
|  | return remote; | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnSSLCertificateError( | 
|  | const GURL& url, | 
|  | int net_error, | 
|  | const net::SSLInfo& ssl_info, | 
|  | bool fatal, | 
|  | OnSSLCertificateErrorCallback response) { | 
|  | std::move(response).Run(net::ERR_INSECURE_RESPONSE); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnCertificateRequested( | 
|  | const absl::optional<base::UnguessableToken>& window_id, | 
|  | const scoped_refptr<net::SSLCertRequestInfo>& cert_info, | 
|  | mojo::PendingRemote<network::mojom::ClientCertificateResponder> | 
|  | cert_responder_remote) { | 
|  | mojo::Remote<network::mojom::ClientCertificateResponder> cert_responder( | 
|  | std::move(cert_responder_remote)); | 
|  |  | 
|  | if (base::CommandLine::ForCurrentProcess()->HasSwitch( | 
|  | network::switches::kIgnoreUrlFetcherCertRequests)) { | 
|  | cert_responder->ContinueWithoutCertificate(); | 
|  | return; | 
|  | } | 
|  | cert_responder->CancelRequest(); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnAuthRequired( | 
|  | const absl::optional<base::UnguessableToken>& window_id, | 
|  | uint32_t request_id, | 
|  | const GURL& url, | 
|  | bool first_auth_attempt, | 
|  | const net::AuthChallengeInfo& auth_info, | 
|  | const scoped_refptr<net::HttpResponseHeaders>& head_headers, | 
|  | mojo::PendingRemote<network::mojom::AuthChallengeResponder> | 
|  | auth_challenge_responder) { | 
|  | mojo::Remote<network::mojom::AuthChallengeResponder> | 
|  | auth_challenge_responder_remote(std::move(auth_challenge_responder)); | 
|  | auth_challenge_responder_remote->OnAuthCredentials(absl::nullopt); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnClearSiteData(const GURL& url, | 
|  | const std::string& header_value, | 
|  | int load_flags, | 
|  | OnClearSiteDataCallback callback) { | 
|  | std::move(callback).Run(); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnLoadingStateUpdate( | 
|  | network::mojom::LoadInfoPtr info, | 
|  | OnLoadingStateUpdateCallback callback) { | 
|  | std::move(callback).Run(); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::OnDataUseUpdate( | 
|  | int32_t network_traffic_annotation_id_hash, | 
|  | int64_t recv_bytes, | 
|  | int64_t sent_bytes) { | 
|  | GetContentClient()->browser()->OnNetworkServiceDataUseUpdate( | 
|  | network::mojom::kBrowserProcessId, MSG_ROUTING_NONE, | 
|  | network_traffic_annotation_id_hash, recv_bytes, sent_bytes); | 
|  | } | 
|  |  | 
|  | void NetworkServiceClient::Clone( | 
|  | mojo::PendingReceiver<network::mojom::URLLoaderNetworkServiceObserver> | 
|  | observer) { | 
|  | url_loader_network_service_observers_.Add(this, std::move(observer)); | 
|  | } | 
|  |  | 
|  | }  // namespace content |