| // 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/optional.h" |
| #include "base/task/post_task.h" |
| #include "base/threading/sequence_bound.h" |
| #include "base/unguessable_token.h" |
| #include "components/rappor/public/rappor_service.h" |
| #include "content/browser/browsing_data/clear_site_data_handler.h" |
| #include "content/browser/devtools/devtools_instrumentation.h" |
| #include "content/browser/frame_host/frame_tree_node.h" |
| #include "content/browser/loader/webrtc_connections_observer.h" |
| #include "content/browser/ssl/ssl_manager.h" |
| #include "content/browser/web_contents/web_contents_impl.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/load_info_util.h" |
| #include "services/network/public/mojom/network_context.mojom.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_MACOSX) |
| #include "base/message_loop/message_loop_current.h" |
| #endif |
| |
| namespace content { |
| namespace { |
| |
| WebContents* GetWebContents(int process_id, int routing_id) { |
| if (process_id != network::mojom::kBrowserProcessId) { |
| return WebContentsImpl::FromRenderFrameHostID(process_id, routing_id); |
| } |
| return WebContents::FromFrameTreeNodeId(routing_id); |
| } |
| |
| } // namespace |
| |
| NetworkServiceClient::NetworkServiceClient( |
| mojo::PendingReceiver<network::mojom::NetworkServiceClient> |
| network_service_client_receiver) |
| : receiver_(this, std::move(network_service_client_receiver)) |
| #if defined(OS_ANDROID) |
| , |
| app_status_listener_(base::android::ApplicationStatusListener::New( |
| base::BindRepeating(&NetworkServiceClient::OnApplicationStateChange, |
| base::Unretained(this)))) |
| #endif |
| { |
| |
| #if defined(OS_MACOSX) |
| if (base::MessageLoopCurrentForUI::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>(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::OnLoadingStateUpdate( |
| std::vector<network::mojom::LoadInfoPtr> infos, |
| OnLoadingStateUpdateCallback callback) { |
| std::map<WebContents*, network::mojom::LoadInfo> info_map; |
| |
| for (auto& info : infos) { |
| auto* web_contents = GetWebContents(info->process_id, info->routing_id); |
| if (!web_contents) |
| continue; |
| |
| auto existing = info_map.find(web_contents); |
| if (existing == info_map.end() || |
| network::LoadInfoIsMoreInteresting(*info, existing->second)) { |
| info_map[web_contents] = *info; |
| } |
| } |
| |
| for (const auto& load_info : info_map) { |
| net::LoadStateWithParam load_state; |
| load_state.state = static_cast<net::LoadState>(load_info.second.load_state); |
| load_state.param = load_info.second.state_param; |
| static_cast<WebContentsImpl*>(load_info.first) |
| ->LoadStateChanged(load_info.second.host, load_state, |
| load_info.second.upload_position, |
| load_info.second.upload_size); |
| } |
| |
| std::move(callback).Run(); |
| } |
| |
| 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 |
| |
| void NetworkServiceClient::OnDataUseUpdate( |
| int32_t network_traffic_annotation_id_hash, |
| int64_t recv_bytes, |
| int64_t sent_bytes) { |
| GetContentClient()->browser()->OnNetworkServiceDataUseUpdate( |
| network_traffic_annotation_id_hash, recv_bytes, sent_bytes); |
| } |
| |
| void NetworkServiceClient::OnRawRequest( |
| int32_t process_id, |
| int32_t routing_id, |
| const std::string& devtools_request_id, |
| const net::CookieStatusList& cookies_with_status, |
| std::vector<network::mojom::HttpRawHeaderPairPtr> headers) { |
| devtools_instrumentation::OnRequestWillBeSentExtraInfo( |
| process_id, routing_id, devtools_request_id, cookies_with_status, |
| headers); |
| } |
| |
| void NetworkServiceClient::OnRawResponse( |
| int32_t process_id, |
| int32_t routing_id, |
| const std::string& devtools_request_id, |
| const net::CookieAndLineStatusList& cookies_with_status, |
| std::vector<network::mojom::HttpRawHeaderPairPtr> headers, |
| const base::Optional<std::string>& raw_response_headers) { |
| devtools_instrumentation::OnResponseReceivedExtraInfo( |
| process_id, routing_id, devtools_request_id, cookies_with_status, headers, |
| raw_response_headers); |
| } |
| |
| void NetworkServiceClient::OnCorsPreflightRequest( |
| int32_t process_id, |
| int32_t render_frame_id, |
| const base::UnguessableToken& devtools_request_id, |
| const network::ResourceRequest& request, |
| const GURL& initiator_url) { |
| devtools_instrumentation::OnCorsPreflightRequest( |
| process_id, render_frame_id, devtools_request_id, request, initiator_url); |
| } |
| |
| void NetworkServiceClient::OnCorsPreflightResponse( |
| int32_t process_id, |
| int32_t render_frame_id, |
| const base::UnguessableToken& devtools_request_id, |
| const GURL& url, |
| network::mojom::URLResponseHeadPtr head) { |
| devtools_instrumentation::OnCorsPreflightResponse( |
| process_id, render_frame_id, devtools_request_id, url, std::move(head)); |
| } |
| |
| void NetworkServiceClient::OnCorsPreflightRequestCompleted( |
| int32_t process_id, |
| int32_t render_frame_id, |
| const base::UnguessableToken& devtools_request_id, |
| const network::URLLoaderCompletionStatus& status) { |
| devtools_instrumentation::OnCorsPreflightRequestCompleted( |
| process_id, render_frame_id, devtools_request_id, status); |
| } |
| |
| void NetworkServiceClient::LogCrossOriginFetchFromContentScript3( |
| const std::string& isolated_world_host) { |
| rappor::RapporService* rappor = |
| GetContentClient()->browser()->GetRapporService(); |
| if (rappor) { |
| rappor->RecordSampleString("Extensions.CrossOriginFetchFromContentScript3", |
| rappor::UMA_RAPPOR_TYPE, isolated_world_host); |
| } |
| |
| ContentBrowserClient* client = GetContentClient()->browser(); |
| if (client) { |
| client->LogUkmEventForCrossOriginFetchFromContentScript3( |
| isolated_world_host); |
| } |
| } |
| |
| } // namespace content |