#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "net/nqe/network_quality_estimator.h"
#include <algorithm>
#include <cmath>
#include <limits>
#include <memory>
#include <utility>
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/histogram_macros_local.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/lazy_thread_pool_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "net/base/features.h"
#include "net/base/host_port_pair.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/base/network_interfaces.h"
#include "net/base/trace_constants.h"
#include "net/base/tracing.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_status_code.h"
#include "net/nqe/network_quality_estimator_util.h"
#include "net/nqe/throughput_analyzer.h"
#include "net/nqe/weighted_observation.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "url/gurl.h"
namespace net {
namespace {
#if BUILDFLAG(IS_CHROMEOS_ASH)
base::LazyThreadPoolSequencedTaskRunner g_get_network_id_task_runner =
LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
base::TaskTraits(base::MayBlock(),
base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
#endif
NetworkQualityObservationSource ProtocolSourceToObservationSource(
SocketPerformanceWatcherFactory::Protocol protocol) { … }
bool RequestSchemeIsHTTPOrHTTPS(const URLRequest& request) { … }
nqe::internal::NetworkID DoGetCurrentNetworkID(
NetworkQualityEstimatorParams* params) { … }
const char* CategoryToString(nqe::internal::ObservationCategory category) { … }
base::TimeTicks GetStartTimeFromThreshold(int threshold) { … }
base::TimeTicks GetHTTPStartTime() { … }
base::TimeTicks GetTransportStartTime() { … }
base::TimeTicks GetEndToEndStartTime() { … }
void RecordFallbackSuccess(std::string_view category, bool fallback_success) { … }
}
NetworkQualityEstimator::NetworkQualityEstimator(
std::unique_ptr<NetworkQualityEstimatorParams> params,
NetLog* net_log)
: … { … }
void NetworkQualityEstimator::AddDefaultEstimates() { … }
NetworkQualityEstimator::~NetworkQualityEstimator() { … }
void NetworkQualityEstimator::NotifyStartTransaction(
const URLRequest& request) { … }
bool NetworkQualityEstimator::IsHangingRequest(
base::TimeDelta observed_http_rtt) const { … }
void NetworkQualityEstimator::NotifyHeadersReceived(
const URLRequest& request,
int64_t prefilter_total_bytes_read) { … }
void NetworkQualityEstimator::NotifyBytesRead(
const URLRequest& request,
int64_t prefilter_total_bytes_read) { … }
void NetworkQualityEstimator::NotifyRequestCompleted(
const URLRequest& request) { … }
void NetworkQualityEstimator::NotifyURLRequestDestroyed(
const URLRequest& request) { … }
void NetworkQualityEstimator::AddRTTObserver(RTTObserver* rtt_observer) { … }
void NetworkQualityEstimator::RemoveRTTObserver(RTTObserver* rtt_observer) { … }
void NetworkQualityEstimator::AddThroughputObserver(
ThroughputObserver* throughput_observer) { … }
void NetworkQualityEstimator::RemoveThroughputObserver(
ThroughputObserver* throughput_observer) { … }
SocketPerformanceWatcherFactory*
NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() { … }
void NetworkQualityEstimator::SetUseLocalHostRequestsForTesting(
bool use_localhost_requests) { … }
void NetworkQualityEstimator::SetUseSmallResponsesForTesting(
bool use_small_responses) { … }
void NetworkQualityEstimator::DisableOfflineCheckForTesting(
bool disable_offline_check) { … }
void NetworkQualityEstimator::ReportEffectiveConnectionTypeForTesting(
EffectiveConnectionType effective_connection_type) { … }
void NetworkQualityEstimator::ReportRTTsAndThroughputForTesting(
base::TimeDelta http_rtt,
base::TimeDelta transport_rtt,
int32_t downstream_throughput_kbps) { … }
bool NetworkQualityEstimator::RequestProvidesRTTObservation(
const URLRequest& request) const { … }
void NetworkQualityEstimator::OnConnectionTypeChanged(
NetworkChangeNotifier::ConnectionType type) { … }
void NetworkQualityEstimator::GatherEstimatesForNextConnectionType() { … }
void NetworkQualityEstimator::ContinueGatherEstimatesForNextConnectionType(
const nqe::internal::NetworkID& network_id) { … }
void NetworkQualityEstimator::ComputeEffectiveConnectionType() { … }
std::optional<net::EffectiveConnectionType>
NetworkQualityEstimator::GetOverrideECT() const { … }
void NetworkQualityEstimator::ClampKbpsBasedOnEct() { … }
void NetworkQualityEstimator::AdjustHttpRttBasedOnRTTCounts(
base::TimeDelta* http_rtt) const { … }
EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType()
const { … }
void NetworkQualityEstimator::UpdateHttpRttUsingAllRttValues(
base::TimeDelta* http_rtt,
const base::TimeDelta transport_rtt,
const base::TimeDelta end_to_end_rtt) const { … }
EffectiveConnectionType
NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
base::TimeDelta* http_rtt,
base::TimeDelta* transport_rtt,
base::TimeDelta* end_to_end_rtt,
int32_t* downstream_throughput_kbps,
size_t* transport_rtt_observation_count,
size_t* end_to_end_rtt_observation_count) const { … }
void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver(
EffectiveConnectionTypeObserver* observer) { … }
void NetworkQualityEstimator::RemoveEffectiveConnectionTypeObserver(
EffectiveConnectionTypeObserver* observer) { … }
void NetworkQualityEstimator::AddPeerToPeerConnectionsCountObserver(
PeerToPeerConnectionsCountObserver* observer) { … }
void NetworkQualityEstimator::RemovePeerToPeerConnectionsCountObserver(
PeerToPeerConnectionsCountObserver* observer) { … }
void NetworkQualityEstimator::AddRTTAndThroughputEstimatesObserver(
RTTAndThroughputEstimatesObserver* observer) { … }
void NetworkQualityEstimator::RemoveRTTAndThroughputEstimatesObserver(
RTTAndThroughputEstimatesObserver* observer) { … }
bool NetworkQualityEstimator::GetRecentRTT(
nqe::internal::ObservationCategory observation_category,
const base::TimeTicks& start_time,
base::TimeDelta* rtt,
size_t* observations_count) const { … }
bool NetworkQualityEstimator::GetRecentDownlinkThroughputKbps(
const base::TimeTicks& start_time,
int32_t* kbps) const { … }
base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
base::TimeTicks start_time,
nqe::internal::ObservationCategory observation_category,
int percentile,
size_t* observations_count) const { … }
int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal(
const base::TimeTicks& start_time,
int percentile) const { … }
nqe::internal::NetworkID NetworkQualityEstimator::GetCurrentNetworkID() const { … }
bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() { … }
void NetworkQualityEstimator::SetTickClockForTesting(
const base::TickClock* tick_clock) { … }
void NetworkQualityEstimator::OnUpdatedTransportRTTAvailable(
SocketPerformanceWatcherFactory::Protocol protocol,
const base::TimeDelta& rtt,
const std::optional<nqe::internal::IPHash>& host) { … }
void NetworkQualityEstimator::AddAndNotifyObserversOfRTT(
const Observation& observation) { … }
void NetworkQualityEstimator::AddAndNotifyObserversOfThroughput(
const Observation& observation) { … }
void NetworkQualityEstimator::OnNewThroughputObservationAvailable(
int32_t downstream_kbps) { … }
bool NetworkQualityEstimator::ShouldComputeEffectiveConnectionType() const { … }
void NetworkQualityEstimator::MaybeComputeEffectiveConnectionType() { … }
void NetworkQualityEstimator::
NotifyObserversOfEffectiveConnectionTypeChanged() { … }
void NetworkQualityEstimator::NotifyObserversOfRTTOrThroughputComputed() const { … }
void NetworkQualityEstimator::NotifyEffectiveConnectionTypeObserverIfPresent(
MayBeDangling<EffectiveConnectionTypeObserver> observer) const { … }
void NetworkQualityEstimator::NotifyPeerToPeerConnectionsCountObserverIfPresent(
MayBeDangling<PeerToPeerConnectionsCountObserver> observer) const { … }
void NetworkQualityEstimator::NotifyRTTAndThroughputEstimatesObserverIfPresent(
RTTAndThroughputEstimatesObserver* observer) const { … }
void NetworkQualityEstimator::AddNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer) { … }
void NetworkQualityEstimator::RemoveNetworkQualitiesCacheObserver(
nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
observer) { … }
void NetworkQualityEstimator::OnPrefsRead(
const std::map<nqe::internal::NetworkID,
nqe::internal::CachedNetworkQuality> read_prefs) { … }
#if BUILDFLAG(IS_CHROMEOS_ASH)
void NetworkQualityEstimator::EnableGetNetworkIdAsynchronously() {
get_network_id_asynchronously_ = true;
}
#endif
std::optional<base::TimeDelta> NetworkQualityEstimator::GetHttpRTT() const { … }
std::optional<base::TimeDelta> NetworkQualityEstimator::GetTransportRTT()
const { … }
std::optional<int32_t> NetworkQualityEstimator::GetDownstreamThroughputKbps()
const { … }
void NetworkQualityEstimator::MaybeUpdateCachedEstimateApplied(
const Observation& observation,
ObservationBuffer* buffer) { … }
bool NetworkQualityEstimator::ShouldAddObservation(
const Observation& observation) const { … }
bool NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT(
base::TimeTicks now) { … }
void NetworkQualityEstimator::SimulateNetworkQualityChangeForTesting(
net::EffectiveConnectionType type) { … }
void NetworkQualityEstimator::ForceReportWifiAsSlow2GForTesting() { … }
void NetworkQualityEstimator::RecordSpdyPingLatency(
const HostPortPair& host_port_pair,
base::TimeDelta rtt) { … }
void NetworkQualityEstimator::OnPeerToPeerConnectionsCountChange(
uint32_t count) { … }
uint32_t NetworkQualityEstimator::GetPeerToPeerConnectionsCountChange() const { … }
}