network_quality_estimator.cc 59 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. // Copyright 2015 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "net/nqe/network_quality_estimator.h"
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <limits>
  8. #include <memory>
  9. #include <utility>
  10. #include "base/bind.h"
  11. #include "base/callback_helpers.h"
  12. #include "base/check_op.h"
  13. #include "base/location.h"
  14. #include "base/metrics/field_trial_params.h"
  15. #include "base/metrics/histogram.h"
  16. #include "base/metrics/histogram_base.h"
  17. #include "base/metrics/histogram_functions.h"
  18. #include "base/metrics/histogram_macros.h"
  19. #include "base/metrics/histogram_macros_local.h"
  20. #include "base/notreached.h"
  21. #include "base/observer_list.h"
  22. #include "base/strings/string_number_conversions.h"
  23. #include "base/strings/string_piece.h"
  24. #include "base/task/lazy_thread_pool_task_runner.h"
  25. #include "base/task/single_thread_task_runner.h"
  26. #include "base/threading/thread_task_runner_handle.h"
  27. #include "base/time/default_tick_clock.h"
  28. #include "base/trace_event/trace_event.h"
  29. #include "build/build_config.h"
  30. #include "build/chromeos_buildflags.h"
  31. #include "net/base/features.h"
  32. #include "net/base/host_port_pair.h"
  33. #include "net/base/load_flags.h"
  34. #include "net/base/load_timing_info.h"
  35. #include "net/base/network_interfaces.h"
  36. #include "net/base/trace_constants.h"
  37. #include "net/http/http_response_headers.h"
  38. #include "net/http/http_response_info.h"
  39. #include "net/http/http_status_code.h"
  40. #include "net/nqe/network_quality_estimator_util.h"
  41. #include "net/nqe/throughput_analyzer.h"
  42. #include "net/nqe/weighted_observation.h"
  43. #include "net/url_request/url_request.h"
  44. #include "net/url_request/url_request_context.h"
  45. #include "url/gurl.h"
  46. namespace net {
  47. namespace {
  48. #if BUILDFLAG(IS_CHROMEOS_ASH)
  49. // SequencedTaskRunner to get the network id. A SequencedTaskRunner is used
  50. // rather than parallel tasks to avoid having many threads getting the network
  51. // id concurrently.
  52. base::LazyThreadPoolSequencedTaskRunner g_get_network_id_task_runner =
  53. LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
  54. base::TaskTraits(base::MayBlock(),
  55. base::TaskPriority::BEST_EFFORT,
  56. base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN));
  57. #endif
  58. NetworkQualityObservationSource ProtocolSourceToObservationSource(
  59. SocketPerformanceWatcherFactory::Protocol protocol) {
  60. switch (protocol) {
  61. case SocketPerformanceWatcherFactory::PROTOCOL_TCP:
  62. return NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
  63. case SocketPerformanceWatcherFactory::PROTOCOL_QUIC:
  64. return NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC;
  65. }
  66. NOTREACHED();
  67. return NETWORK_QUALITY_OBSERVATION_SOURCE_TCP;
  68. }
  69. // Returns true if the scheme of the |request| is either HTTP or HTTPS.
  70. bool RequestSchemeIsHTTPOrHTTPS(const URLRequest& request) {
  71. return request.url().is_valid() && request.url().SchemeIsHTTPOrHTTPS();
  72. }
  73. nqe::internal::NetworkID DoGetCurrentNetworkID(
  74. NetworkQualityEstimatorParams* params) {
  75. nqe::internal::NetworkID network_id(
  76. NetworkChangeNotifier::GetConnectionType(), std::string(), INT32_MIN);
  77. return network_id;
  78. }
  79. } // namespace
  80. NetworkQualityEstimator::NetworkQualityEstimator(
  81. std::unique_ptr<NetworkQualityEstimatorParams> params,
  82. NetLog* net_log)
  83. : params_(std::move(params)),
  84. tick_clock_(base::DefaultTickClock::GetInstance()),
  85. last_connection_change_(tick_clock_->NowTicks()),
  86. current_network_id_(nqe::internal::NetworkID(
  87. NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
  88. std::string(),
  89. INT32_MIN)),
  90. http_downstream_throughput_kbps_observations_(
  91. params_.get(),
  92. tick_clock_,
  93. params_->weight_multiplier_per_second(),
  94. 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
  95. rtt_ms_observations_{
  96. ObservationBuffer(
  97. params_.get(),
  98. tick_clock_,
  99. params_->weight_multiplier_per_second(),
  100. 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
  101. ObservationBuffer(
  102. params_.get(),
  103. tick_clock_,
  104. params_->weight_multiplier_per_second(),
  105. 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
  106. ObservationBuffer(
  107. params_.get(),
  108. tick_clock_,
  109. params_->weight_multiplier_per_second(),
  110. 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)},
  111. net_log_(NetLogWithSource::Make(
  112. net_log,
  113. net::NetLogSourceType::NETWORK_QUALITY_ESTIMATOR)),
  114. event_creator_(net_log_) {
  115. DCHECK_EQ(nqe::internal::OBSERVATION_CATEGORY_COUNT,
  116. std::size(rtt_ms_observations_));
  117. network_quality_store_ =
  118. std::make_unique<nqe::internal::NetworkQualityStore>();
  119. NetworkChangeNotifier::AddConnectionTypeObserver(this);
  120. throughput_analyzer_ = std::make_unique<nqe::internal::ThroughputAnalyzer>(
  121. this, params_.get(), base::ThreadTaskRunnerHandle::Get(),
  122. base::BindRepeating(
  123. &NetworkQualityEstimator::OnNewThroughputObservationAvailable,
  124. weak_ptr_factory_.GetWeakPtr()),
  125. tick_clock_, net_log_);
  126. watcher_factory_ = std::make_unique<nqe::internal::SocketWatcherFactory>(
  127. base::ThreadTaskRunnerHandle::Get(),
  128. params_->min_socket_watcher_notification_interval(),
  129. // OnUpdatedTransportRTTAvailable() may be called via PostTask() by
  130. // socket watchers that live on a different thread than the current thread
  131. // (i.e., base::ThreadTaskRunnerHandle::Get()).
  132. // Use WeakPtr() to avoid crashes where the socket watcher is destroyed
  133. // after |this| is destroyed.
  134. base::BindRepeating(
  135. &NetworkQualityEstimator::OnUpdatedTransportRTTAvailable,
  136. weak_ptr_factory_.GetWeakPtr()),
  137. // ShouldSocketWatcherNotifyRTT() below is called by only the socket
  138. // watchers that live on the same thread as the current thread
  139. // (i.e., base::ThreadTaskRunnerHandle::Get()). Also, network quality
  140. // estimator is destroyed after network contexts and URLRequestContexts.
  141. // It's safe to use base::Unretained() below since the socket watcher
  142. // (owned by sockets) would be destroyed before |this|.
  143. base::BindRepeating(
  144. &NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT,
  145. base::Unretained(this)),
  146. tick_clock_);
  147. GatherEstimatesForNextConnectionType();
  148. }
  149. void NetworkQualityEstimator::AddDefaultEstimates() {
  150. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  151. if (!params_->add_default_platform_observations())
  152. return;
  153. if (params_->DefaultObservation(current_network_id_.type).http_rtt() !=
  154. nqe::internal::InvalidRTT()) {
  155. Observation rtt_observation(
  156. params_->DefaultObservation(current_network_id_.type)
  157. .http_rtt()
  158. .InMilliseconds(),
  159. tick_clock_->NowTicks(), INT32_MIN,
  160. NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM);
  161. AddAndNotifyObserversOfRTT(rtt_observation);
  162. }
  163. if (params_->DefaultObservation(current_network_id_.type).transport_rtt() !=
  164. nqe::internal::InvalidRTT()) {
  165. Observation rtt_observation(
  166. params_->DefaultObservation(current_network_id_.type)
  167. .transport_rtt()
  168. .InMilliseconds(),
  169. tick_clock_->NowTicks(), INT32_MIN,
  170. NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM);
  171. AddAndNotifyObserversOfRTT(rtt_observation);
  172. }
  173. if (params_->DefaultObservation(current_network_id_.type)
  174. .downstream_throughput_kbps() !=
  175. nqe::internal::INVALID_RTT_THROUGHPUT) {
  176. Observation throughput_observation(
  177. params_->DefaultObservation(current_network_id_.type)
  178. .downstream_throughput_kbps(),
  179. tick_clock_->NowTicks(), INT32_MIN,
  180. NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM);
  181. AddAndNotifyObserversOfThroughput(throughput_observation);
  182. }
  183. }
  184. NetworkQualityEstimator::~NetworkQualityEstimator() {
  185. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  186. NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
  187. }
  188. void NetworkQualityEstimator::NotifyStartTransaction(
  189. const URLRequest& request) {
  190. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  191. if (!RequestSchemeIsHTTPOrHTTPS(request))
  192. return;
  193. // Update |estimated_quality_at_last_main_frame_| if this is a main frame
  194. // request.
  195. // TODO(tbansal): Refactor this to a separate method.
  196. if (request.load_flags() & LOAD_MAIN_FRAME_DEPRECATED) {
  197. base::TimeTicks now = tick_clock_->NowTicks();
  198. last_main_frame_request_ = now;
  199. ComputeEffectiveConnectionType();
  200. effective_connection_type_at_last_main_frame_ = effective_connection_type_;
  201. estimated_quality_at_last_main_frame_ = network_quality_;
  202. } else {
  203. MaybeComputeEffectiveConnectionType();
  204. }
  205. throughput_analyzer_->NotifyStartTransaction(request);
  206. }
  207. bool NetworkQualityEstimator::IsHangingRequest(
  208. base::TimeDelta observed_http_rtt) const {
  209. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  210. // If there are sufficient number of end to end RTT samples available, use
  211. // the end to end RTT estimate to determine if the request is hanging.
  212. // If |observed_http_rtt| is within a fixed multiplier of |end_to_end_rtt_|,
  213. // then |observed_http_rtt| is determined to be not a hanging-request RTT.
  214. if (params_->use_end_to_end_rtt() && end_to_end_rtt_.has_value() &&
  215. end_to_end_rtt_observation_count_at_last_ect_computation_ >=
  216. params_->http_rtt_transport_rtt_min_count() &&
  217. params_->hanging_request_http_rtt_upper_bound_transport_rtt_multiplier() >
  218. 0 &&
  219. observed_http_rtt <
  220. params_->hanging_request_http_rtt_upper_bound_transport_rtt_multiplier() *
  221. end_to_end_rtt_.value()) {
  222. return false;
  223. }
  224. DCHECK_LT(
  225. 0,
  226. params_->hanging_request_http_rtt_upper_bound_transport_rtt_multiplier());
  227. if (transport_rtt_observation_count_last_ect_computation_ >=
  228. params_->http_rtt_transport_rtt_min_count() &&
  229. (observed_http_rtt <
  230. params_->hanging_request_http_rtt_upper_bound_transport_rtt_multiplier() *
  231. GetTransportRTT().value_or(base::Seconds(10)))) {
  232. // If there are sufficient number of transport RTT samples available, use
  233. // the transport RTT estimate to determine if the request is hanging.
  234. return false;
  235. }
  236. DCHECK_LT(
  237. 0, params_->hanging_request_http_rtt_upper_bound_http_rtt_multiplier());
  238. if (observed_http_rtt <
  239. params_->hanging_request_http_rtt_upper_bound_http_rtt_multiplier() *
  240. GetHttpRTT().value_or(base::Seconds(10))) {
  241. // Use the HTTP RTT estimate to determine if the request is hanging.
  242. return false;
  243. }
  244. if (observed_http_rtt <=
  245. params_->hanging_request_upper_bound_min_http_rtt()) {
  246. return false;
  247. }
  248. return true;
  249. }
  250. void NetworkQualityEstimator::NotifyHeadersReceived(
  251. const URLRequest& request,
  252. int64_t prefilter_total_bytes_read) {
  253. TRACE_EVENT0(NetTracingCategory(),
  254. "NetworkQualityEstimator::NotifyHeadersReceived");
  255. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  256. if (!RequestSchemeIsHTTPOrHTTPS(request) ||
  257. !RequestProvidesRTTObservation(request)) {
  258. return;
  259. }
  260. if (request.load_flags() & LOAD_MAIN_FRAME_DEPRECATED) {
  261. ComputeEffectiveConnectionType();
  262. RecordMetricsOnMainFrameRequest();
  263. }
  264. LoadTimingInfo load_timing_info;
  265. request.GetLoadTimingInfo(&load_timing_info);
  266. // If the load timing info is unavailable, it probably means that the request
  267. // did not go over the network.
  268. if (load_timing_info.send_start.is_null() ||
  269. load_timing_info.receive_headers_end.is_null()) {
  270. return;
  271. }
  272. DCHECK(!request.response_info().was_cached);
  273. // Duration between when the resource was requested and when the response
  274. // headers were received.
  275. const base::TimeDelta observed_http_rtt =
  276. load_timing_info.receive_headers_end - load_timing_info.send_start;
  277. if (observed_http_rtt <= base::TimeDelta())
  278. return;
  279. DCHECK_GE(observed_http_rtt, base::TimeDelta());
  280. if (IsHangingRequest(observed_http_rtt))
  281. return;
  282. Observation http_rtt_observation(observed_http_rtt.InMilliseconds(),
  283. tick_clock_->NowTicks(),
  284. current_network_id_.signal_strength,
  285. NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
  286. AddAndNotifyObserversOfRTT(http_rtt_observation);
  287. throughput_analyzer_->NotifyBytesRead(request);
  288. throughput_analyzer_->NotifyExpectedResponseContentSize(
  289. request, request.GetExpectedContentSize());
  290. }
  291. void NetworkQualityEstimator::NotifyBytesRead(
  292. const URLRequest& request,
  293. int64_t prefilter_total_bytes_read) {
  294. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  295. throughput_analyzer_->NotifyBytesRead(request);
  296. }
  297. void NetworkQualityEstimator::NotifyRequestCompleted(
  298. const URLRequest& request) {
  299. TRACE_EVENT0(NetTracingCategory(),
  300. "NetworkQualityEstimator::NotifyRequestCompleted");
  301. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  302. if (!RequestSchemeIsHTTPOrHTTPS(request))
  303. return;
  304. throughput_analyzer_->NotifyRequestCompleted(request);
  305. }
  306. void NetworkQualityEstimator::NotifyURLRequestDestroyed(
  307. const URLRequest& request) {
  308. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  309. if (!RequestSchemeIsHTTPOrHTTPS(request))
  310. return;
  311. throughput_analyzer_->NotifyRequestCompleted(request);
  312. }
  313. void NetworkQualityEstimator::AddRTTObserver(RTTObserver* rtt_observer) {
  314. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  315. rtt_observer_list_.AddObserver(rtt_observer);
  316. }
  317. void NetworkQualityEstimator::RemoveRTTObserver(RTTObserver* rtt_observer) {
  318. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  319. rtt_observer_list_.RemoveObserver(rtt_observer);
  320. }
  321. void NetworkQualityEstimator::AddThroughputObserver(
  322. ThroughputObserver* throughput_observer) {
  323. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  324. throughput_observer_list_.AddObserver(throughput_observer);
  325. }
  326. void NetworkQualityEstimator::RemoveThroughputObserver(
  327. ThroughputObserver* throughput_observer) {
  328. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  329. throughput_observer_list_.RemoveObserver(throughput_observer);
  330. }
  331. SocketPerformanceWatcherFactory*
  332. NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() {
  333. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  334. return watcher_factory_.get();
  335. }
  336. void NetworkQualityEstimator::SetUseLocalHostRequestsForTesting(
  337. bool use_localhost_requests) {
  338. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  339. use_localhost_requests_ = use_localhost_requests;
  340. watcher_factory_->SetUseLocalHostRequestsForTesting(use_localhost_requests_);
  341. throughput_analyzer_->SetUseLocalHostRequestsForTesting(
  342. use_localhost_requests_);
  343. }
  344. void NetworkQualityEstimator::SetUseSmallResponsesForTesting(
  345. bool use_small_responses) {
  346. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  347. params_->SetUseSmallResponsesForTesting(use_small_responses);
  348. }
  349. void NetworkQualityEstimator::DisableOfflineCheckForTesting(
  350. bool disable_offline_check) {
  351. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  352. disable_offline_check_ = disable_offline_check;
  353. }
  354. void NetworkQualityEstimator::ReportEffectiveConnectionTypeForTesting(
  355. EffectiveConnectionType effective_connection_type) {
  356. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  357. event_creator_.MaybeAddNetworkQualityChangedEventToNetLog(
  358. effective_connection_type_,
  359. params_->TypicalNetworkQuality(effective_connection_type));
  360. for (auto& observer : effective_connection_type_observer_list_)
  361. observer.OnEffectiveConnectionTypeChanged(effective_connection_type);
  362. network_quality_store_->Add(current_network_id_,
  363. nqe::internal::CachedNetworkQuality(
  364. tick_clock_->NowTicks(), network_quality_,
  365. effective_connection_type));
  366. }
  367. void NetworkQualityEstimator::ReportRTTsAndThroughputForTesting(
  368. base::TimeDelta http_rtt,
  369. base::TimeDelta transport_rtt,
  370. int32_t downstream_throughput_kbps) {
  371. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  372. for (auto& observer : rtt_and_throughput_estimates_observer_list_)
  373. observer.OnRTTOrThroughputEstimatesComputed(http_rtt, transport_rtt,
  374. downstream_throughput_kbps);
  375. }
  376. bool NetworkQualityEstimator::RequestProvidesRTTObservation(
  377. const URLRequest& request) const {
  378. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  379. bool private_network_request =
  380. nqe::internal::IsRequestForPrivateHost(request, net_log_);
  381. return (use_localhost_requests_ || !private_network_request) &&
  382. // Verify that response headers are received, so it can be ensured that
  383. // response is not cached.
  384. !request.response_info().response_time.is_null() &&
  385. !request.was_cached() &&
  386. request.creation_time() >= last_connection_change_ &&
  387. request.method() == "GET";
  388. }
  389. void NetworkQualityEstimator::OnConnectionTypeChanged(
  390. NetworkChangeNotifier::ConnectionType type) {
  391. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  392. // It's possible that |type| has the same value as |current_network_id_.type|.
  393. // This can happen if the device switches from one WiFi SSID to another.
  394. DCHECK_EQ(nqe::internal::OBSERVATION_CATEGORY_COUNT,
  395. std::size(rtt_ms_observations_));
  396. // Write the estimates of the previous network to the cache.
  397. network_quality_store_->Add(
  398. current_network_id_, nqe::internal::CachedNetworkQuality(
  399. last_effective_connection_type_computation_,
  400. network_quality_, effective_connection_type_));
  401. // Clear the local state.
  402. last_connection_change_ = tick_clock_->NowTicks();
  403. http_downstream_throughput_kbps_observations_.Clear();
  404. for (auto& rtt_ms_observation : rtt_ms_observations_)
  405. rtt_ms_observation.Clear();
  406. current_network_id_.signal_strength = INT32_MIN;
  407. network_quality_ = nqe::internal::NetworkQuality();
  408. end_to_end_rtt_ = absl::nullopt;
  409. effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
  410. effective_connection_type_at_last_main_frame_ =
  411. EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
  412. rtt_observations_size_at_last_ect_computation_ = 0;
  413. throughput_observations_size_at_last_ect_computation_ = 0;
  414. new_rtt_observations_since_last_ect_computation_ = 0;
  415. new_throughput_observations_since_last_ect_computation_ = 0;
  416. transport_rtt_observation_count_last_ect_computation_ = 0;
  417. end_to_end_rtt_observation_count_at_last_ect_computation_ = 0;
  418. last_socket_watcher_rtt_notification_ = base::TimeTicks();
  419. estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality();
  420. cached_estimate_applied_ = false;
  421. GatherEstimatesForNextConnectionType();
  422. throughput_analyzer_->OnConnectionTypeChanged();
  423. }
  424. void NetworkQualityEstimator::GatherEstimatesForNextConnectionType() {
  425. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  426. #if BUILDFLAG(IS_CHROMEOS_ASH)
  427. if (get_network_id_asynchronously_) {
  428. // Doing PostTaskAndReplyWithResult by handle because it requires the result
  429. // type have a default constructor and nqe::internal::NetworkID does not
  430. // have that.
  431. g_get_network_id_task_runner.Get()->PostTask(
  432. FROM_HERE,
  433. base::BindOnce(
  434. [](scoped_refptr<base::TaskRunner> reply_task_runner,
  435. base::OnceCallback<void(const nqe::internal::NetworkID&)>
  436. reply_callback) {
  437. reply_task_runner->PostTask(
  438. FROM_HERE, base::BindOnce(std::move(reply_callback),
  439. DoGetCurrentNetworkID(nullptr)));
  440. },
  441. base::ThreadTaskRunnerHandle::Get(),
  442. base::BindOnce(&NetworkQualityEstimator::
  443. ContinueGatherEstimatesForNextConnectionType,
  444. weak_ptr_factory_.GetWeakPtr())));
  445. return;
  446. }
  447. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  448. ContinueGatherEstimatesForNextConnectionType(GetCurrentNetworkID());
  449. }
  450. void NetworkQualityEstimator::ContinueGatherEstimatesForNextConnectionType(
  451. const nqe::internal::NetworkID& network_id) {
  452. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  453. // Update the local state as part of preparation for the new connection.
  454. current_network_id_ = network_id;
  455. RecordNetworkIDAvailability();
  456. // Read any cached estimates for the new network. If cached estimates are
  457. // unavailable, add the default estimates.
  458. if (!ReadCachedNetworkQualityEstimate())
  459. AddDefaultEstimates();
  460. ComputeEffectiveConnectionType();
  461. }
  462. void NetworkQualityEstimator::RecordNetworkIDAvailability() const {
  463. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  464. if (current_network_id_.type ==
  465. NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI ||
  466. NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) {
  467. UMA_HISTOGRAM_BOOLEAN("NQE.NetworkIdAvailable",
  468. !current_network_id_.id.empty());
  469. }
  470. }
  471. void NetworkQualityEstimator::RecordMetricsOnMainFrameRequest() const {
  472. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  473. if (estimated_quality_at_last_main_frame_.http_rtt() !=
  474. nqe::internal::InvalidRTT()) {
  475. // Add the 50th percentile value.
  476. LOCAL_HISTOGRAM_TIMES("NQE.MainFrame.RTT.Percentile50",
  477. estimated_quality_at_last_main_frame_.http_rtt());
  478. }
  479. if (estimated_quality_at_last_main_frame_.transport_rtt() !=
  480. nqe::internal::InvalidRTT()) {
  481. // Add the 50th percentile value.
  482. LOCAL_HISTOGRAM_TIMES(
  483. "NQE.MainFrame.TransportRTT.Percentile50",
  484. estimated_quality_at_last_main_frame_.transport_rtt());
  485. }
  486. if (estimated_quality_at_last_main_frame_.downstream_throughput_kbps() !=
  487. nqe::internal::INVALID_RTT_THROUGHPUT) {
  488. // Add the 50th percentile value.
  489. LOCAL_HISTOGRAM_COUNTS_1000000(
  490. "NQE.MainFrame.Kbps.Percentile50",
  491. estimated_quality_at_last_main_frame_.downstream_throughput_kbps());
  492. }
  493. LOCAL_HISTOGRAM_ENUMERATION("NQE.MainFrame.EffectiveConnectionType",
  494. effective_connection_type_at_last_main_frame_,
  495. EFFECTIVE_CONNECTION_TYPE_LAST);
  496. }
  497. void NetworkQualityEstimator::ComputeEffectiveConnectionType() {
  498. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  499. const base::TimeTicks now = tick_clock_->NowTicks();
  500. const EffectiveConnectionType past_type = effective_connection_type_;
  501. last_effective_connection_type_computation_ = now;
  502. base::TimeDelta http_rtt = nqe::internal::InvalidRTT();
  503. base::TimeDelta transport_rtt = nqe::internal::InvalidRTT();
  504. base::TimeDelta end_to_end_rtt = nqe::internal::InvalidRTT();
  505. int32_t downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
  506. effective_connection_type_ = GetRecentEffectiveConnectionTypeUsingMetrics(
  507. &http_rtt, &transport_rtt, &end_to_end_rtt, &downstream_throughput_kbps,
  508. &transport_rtt_observation_count_last_ect_computation_,
  509. &end_to_end_rtt_observation_count_at_last_ect_computation_);
  510. network_quality_ = nqe::internal::NetworkQuality(http_rtt, transport_rtt,
  511. downstream_throughput_kbps);
  512. ClampKbpsBasedOnEct();
  513. UMA_HISTOGRAM_ENUMERATION("NQE.EffectiveConnectionType.OnECTComputation",
  514. effective_connection_type_,
  515. EFFECTIVE_CONNECTION_TYPE_LAST);
  516. if (network_quality_.http_rtt() != nqe::internal::InvalidRTT()) {
  517. UMA_HISTOGRAM_TIMES("NQE.RTT.OnECTComputation",
  518. network_quality_.http_rtt());
  519. }
  520. if (network_quality_.transport_rtt() != nqe::internal::InvalidRTT()) {
  521. UMA_HISTOGRAM_TIMES("NQE.TransportRTT.OnECTComputation",
  522. network_quality_.transport_rtt());
  523. }
  524. if (end_to_end_rtt != nqe::internal::InvalidRTT()) {
  525. UMA_HISTOGRAM_TIMES("NQE.EndToEndRTT.OnECTComputation", end_to_end_rtt);
  526. }
  527. end_to_end_rtt_ = absl::nullopt;
  528. if (end_to_end_rtt != nqe::internal::InvalidRTT())
  529. end_to_end_rtt_ = end_to_end_rtt;
  530. if (network_quality_.downstream_throughput_kbps() !=
  531. nqe::internal::INVALID_RTT_THROUGHPUT) {
  532. UMA_HISTOGRAM_COUNTS_1M("NQE.Kbps.OnECTComputation",
  533. network_quality_.downstream_throughput_kbps());
  534. }
  535. NotifyObserversOfRTTOrThroughputComputed();
  536. if (past_type != effective_connection_type_)
  537. NotifyObserversOfEffectiveConnectionTypeChanged();
  538. event_creator_.MaybeAddNetworkQualityChangedEventToNetLog(
  539. effective_connection_type_, network_quality_);
  540. rtt_observations_size_at_last_ect_computation_ =
  541. rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP].Size() +
  542. rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
  543. .Size();
  544. throughput_observations_size_at_last_ect_computation_ =
  545. http_downstream_throughput_kbps_observations_.Size();
  546. new_rtt_observations_since_last_ect_computation_ = 0;
  547. new_throughput_observations_since_last_ect_computation_ = 0;
  548. }
  549. absl::optional<net::EffectiveConnectionType>
  550. NetworkQualityEstimator::GetOverrideECT() const {
  551. return absl::nullopt;
  552. }
  553. void NetworkQualityEstimator::ClampKbpsBasedOnEct() {
  554. // No need to clamp when ECT is unknown or if the connection speed is fast.
  555. if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
  556. effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_OFFLINE ||
  557. effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_4G) {
  558. return;
  559. }
  560. if (params_->upper_bound_typical_kbps_multiplier() <= 0.0)
  561. return;
  562. DCHECK_LT(0, params_->TypicalNetworkQuality(effective_connection_type_)
  563. .downstream_throughput_kbps());
  564. // For a given ECT, upper bound on Kbps can't be less than the typical Kbps
  565. // for that ECT.
  566. DCHECK_LE(1.0, params_->upper_bound_typical_kbps_multiplier());
  567. DCHECK(effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_SLOW_2G ||
  568. effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_2G ||
  569. effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_3G);
  570. // Put an upper bound on Kbps.
  571. network_quality_.set_downstream_throughput_kbps(
  572. std::min(network_quality_.downstream_throughput_kbps(),
  573. static_cast<int>(
  574. params_->TypicalNetworkQuality(effective_connection_type_)
  575. .downstream_throughput_kbps() *
  576. params_->upper_bound_typical_kbps_multiplier())));
  577. }
  578. void NetworkQualityEstimator::AdjustHttpRttBasedOnRTTCounts(
  579. base::TimeDelta* http_rtt) const {
  580. if (!params_->adjust_rtt_based_on_rtt_counts())
  581. return;
  582. // This is needed only when RTT from TCP sockets or
  583. // QUIC/H2 connections is unavailable.
  584. if (transport_rtt_observation_count_last_ect_computation_ >=
  585. params_->http_rtt_transport_rtt_min_count() ||
  586. end_to_end_rtt_observation_count_at_last_ect_computation_ >=
  587. params_->http_rtt_transport_rtt_min_count()) {
  588. UMA_HISTOGRAM_TIMES("NQE.HttpRttReduction.BasedOnRTTCounts",
  589. base::TimeDelta());
  590. return;
  591. }
  592. // We prefer to use the cached value if it's available and the network change
  593. // happened recently.
  594. base::TimeDelta time_since_connection_change =
  595. tick_clock_->NowTicks() - last_connection_change_;
  596. if (cached_estimate_applied_ &&
  597. time_since_connection_change <= base::Minutes(1)) {
  598. UMA_HISTOGRAM_TIMES("NQE.HttpRttReduction.BasedOnRTTCounts",
  599. base::TimeDelta());
  600. return;
  601. }
  602. // If there are not enough transport RTT samples, end-to-end RTT samples and
  603. // the cached estimates are unavailble/too stale, then the computed value of
  604. // HTTP RTT can't be trusted due to hanging GETs. In that case, return the
  605. // typical HTTP RTT for a fast connection.
  606. if (current_network_id_.type == net::NetworkChangeNotifier::CONNECTION_NONE) {
  607. UMA_HISTOGRAM_TIMES("NQE.HttpRttReduction.BasedOnRTTCounts",
  608. base::TimeDelta());
  609. return;
  610. }
  611. base::TimeDelta upper_bound_http_rtt =
  612. params_->TypicalNetworkQuality(net::EFFECTIVE_CONNECTION_TYPE_4G)
  613. .http_rtt();
  614. if (upper_bound_http_rtt > *http_rtt) {
  615. UMA_HISTOGRAM_TIMES("NQE.HttpRttReduction.BasedOnRTTCounts",
  616. base::TimeDelta());
  617. return;
  618. }
  619. DCHECK_LE(upper_bound_http_rtt, *http_rtt);
  620. UMA_HISTOGRAM_TIMES("NQE.HttpRttReduction.BasedOnRTTCounts",
  621. *http_rtt - upper_bound_http_rtt);
  622. *http_rtt = upper_bound_http_rtt;
  623. }
  624. EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType()
  625. const {
  626. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  627. absl::optional<net::EffectiveConnectionType> override_ect = GetOverrideECT();
  628. if (override_ect) {
  629. return override_ect.value();
  630. }
  631. return effective_connection_type_;
  632. }
  633. void NetworkQualityEstimator::UpdateHttpRttUsingAllRttValues(
  634. base::TimeDelta* http_rtt,
  635. const base::TimeDelta transport_rtt,
  636. const base::TimeDelta end_to_end_rtt) const {
  637. DCHECK(http_rtt);
  638. // Use transport RTT to clamp the lower bound on HTTP RTT.
  639. // To improve accuracy, the transport RTT estimate is used only when the
  640. // transport RTT estimate was computed using at least
  641. // |params_->http_rtt_transport_rtt_min_count()| observations.
  642. if (*http_rtt != nqe::internal::InvalidRTT() &&
  643. transport_rtt != nqe::internal::InvalidRTT() &&
  644. transport_rtt_observation_count_last_ect_computation_ >=
  645. params_->http_rtt_transport_rtt_min_count() &&
  646. params_->lower_bound_http_rtt_transport_rtt_multiplier() > 0) {
  647. *http_rtt =
  648. std::max(*http_rtt,
  649. transport_rtt *
  650. params_->lower_bound_http_rtt_transport_rtt_multiplier());
  651. }
  652. // Put lower bound on |http_rtt| using |end_to_end_rtt|.
  653. if (*http_rtt != nqe::internal::InvalidRTT() &&
  654. params_->use_end_to_end_rtt() &&
  655. end_to_end_rtt != nqe::internal::InvalidRTT() &&
  656. end_to_end_rtt_observation_count_at_last_ect_computation_ >=
  657. params_->http_rtt_transport_rtt_min_count() &&
  658. params_->lower_bound_http_rtt_transport_rtt_multiplier() > 0) {
  659. *http_rtt =
  660. std::max(*http_rtt,
  661. end_to_end_rtt *
  662. params_->lower_bound_http_rtt_transport_rtt_multiplier());
  663. }
  664. // Put upper bound on |http_rtt| using |end_to_end_rtt|.
  665. if (*http_rtt != nqe::internal::InvalidRTT() &&
  666. params_->use_end_to_end_rtt() &&
  667. end_to_end_rtt != nqe::internal::InvalidRTT() &&
  668. end_to_end_rtt_observation_count_at_last_ect_computation_ >=
  669. params_->http_rtt_transport_rtt_min_count() &&
  670. params_->upper_bound_http_rtt_endtoend_rtt_multiplier() > 0) {
  671. *http_rtt = std::min(
  672. *http_rtt, end_to_end_rtt *
  673. params_->upper_bound_http_rtt_endtoend_rtt_multiplier());
  674. }
  675. // Put upper bound on |http_rtt| if there is not enough HTTP RTT samples
  676. // available.
  677. AdjustHttpRttBasedOnRTTCounts(http_rtt);
  678. }
  679. EffectiveConnectionType
  680. NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
  681. base::TimeDelta* http_rtt,
  682. base::TimeDelta* transport_rtt,
  683. base::TimeDelta* end_to_end_rtt,
  684. int32_t* downstream_throughput_kbps,
  685. size_t* transport_rtt_observation_count,
  686. size_t* end_to_end_rtt_observation_count) const {
  687. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  688. *http_rtt = nqe::internal::InvalidRTT();
  689. *transport_rtt = nqe::internal::InvalidRTT();
  690. *end_to_end_rtt = nqe::internal::InvalidRTT();
  691. *downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
  692. auto forced_ect =
  693. params_->GetForcedEffectiveConnectionType(current_network_id_.type);
  694. if (forced_ect) {
  695. *http_rtt = params_->TypicalNetworkQuality(forced_ect.value()).http_rtt();
  696. *transport_rtt =
  697. params_->TypicalNetworkQuality(forced_ect.value()).transport_rtt();
  698. *downstream_throughput_kbps =
  699. params_->TypicalNetworkQuality(forced_ect.value())
  700. .downstream_throughput_kbps();
  701. return forced_ect.value();
  702. }
  703. // If the device is currently offline, then return
  704. // EFFECTIVE_CONNECTION_TYPE_OFFLINE.
  705. if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_NONE &&
  706. !disable_offline_check_) {
  707. return EFFECTIVE_CONNECTION_TYPE_OFFLINE;
  708. }
  709. if (force_report_wifi_as_slow_2g_for_testing_ &&
  710. current_network_id_.type == NetworkChangeNotifier::CONNECTION_WIFI) {
  711. return EFFECTIVE_CONNECTION_TYPE_SLOW_2G;
  712. }
  713. if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_HTTP, base::TimeTicks(),
  714. http_rtt, nullptr)) {
  715. *http_rtt = nqe::internal::InvalidRTT();
  716. }
  717. if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_TRANSPORT,
  718. base::TimeTicks(), transport_rtt,
  719. transport_rtt_observation_count)) {
  720. *transport_rtt = nqe::internal::InvalidRTT();
  721. }
  722. if (!GetRecentRTT(nqe::internal::OBSERVATION_CATEGORY_END_TO_END,
  723. base::TimeTicks(), end_to_end_rtt,
  724. end_to_end_rtt_observation_count)) {
  725. *end_to_end_rtt = nqe::internal::InvalidRTT();
  726. }
  727. UpdateHttpRttUsingAllRttValues(http_rtt, *transport_rtt, *end_to_end_rtt);
  728. if (!GetRecentDownlinkThroughputKbps(base::TimeTicks(),
  729. downstream_throughput_kbps)) {
  730. *downstream_throughput_kbps = nqe::internal::INVALID_RTT_THROUGHPUT;
  731. }
  732. if (*http_rtt == nqe::internal::InvalidRTT()) {
  733. return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
  734. }
  735. if (*http_rtt == nqe::internal::InvalidRTT() &&
  736. *transport_rtt == nqe::internal::InvalidRTT() &&
  737. *downstream_throughput_kbps == nqe::internal::INVALID_RTT_THROUGHPUT) {
  738. // None of the metrics are available.
  739. return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
  740. }
  741. // Search from the slowest connection type to the fastest to find the
  742. // EffectiveConnectionType that best matches the current connection's
  743. // performance. The match is done by comparing RTT and throughput.
  744. for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) {
  745. EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i);
  746. if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN)
  747. continue;
  748. const bool estimated_http_rtt_is_higher_than_threshold =
  749. *http_rtt != nqe::internal::InvalidRTT() &&
  750. params_->ConnectionThreshold(type).http_rtt() !=
  751. nqe::internal::InvalidRTT() &&
  752. *http_rtt >= params_->ConnectionThreshold(type).http_rtt();
  753. if (estimated_http_rtt_is_higher_than_threshold)
  754. return type;
  755. }
  756. // Return the fastest connection type.
  757. return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST -
  758. 1);
  759. }
  760. void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver(
  761. EffectiveConnectionTypeObserver* observer) {
  762. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  763. DCHECK(observer);
  764. effective_connection_type_observer_list_.AddObserver(observer);
  765. // Notify the |observer| on the next message pump since |observer| may not
  766. // be completely set up for receiving the callbacks.
  767. base::ThreadTaskRunnerHandle::Get()->PostTask(
  768. FROM_HERE,
  769. base::BindOnce(&NetworkQualityEstimator::
  770. NotifyEffectiveConnectionTypeObserverIfPresent,
  771. weak_ptr_factory_.GetWeakPtr(), observer));
  772. }
  773. void NetworkQualityEstimator::RemoveEffectiveConnectionTypeObserver(
  774. EffectiveConnectionTypeObserver* observer) {
  775. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  776. effective_connection_type_observer_list_.RemoveObserver(observer);
  777. }
  778. void NetworkQualityEstimator::AddPeerToPeerConnectionsCountObserver(
  779. PeerToPeerConnectionsCountObserver* observer) {
  780. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  781. DCHECK(observer);
  782. peer_to_peer_type_observer_list_.AddObserver(observer);
  783. // Notify the |observer| on the next message pump since |observer| may not
  784. // be completely set up for receiving the callbacks.
  785. base::ThreadTaskRunnerHandle::Get()->PostTask(
  786. FROM_HERE,
  787. base::BindOnce(&NetworkQualityEstimator::
  788. NotifyPeerToPeerConnectionsCountObserverIfPresent,
  789. weak_ptr_factory_.GetWeakPtr(), observer));
  790. }
  791. void NetworkQualityEstimator::RemovePeerToPeerConnectionsCountObserver(
  792. PeerToPeerConnectionsCountObserver* observer) {
  793. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  794. peer_to_peer_type_observer_list_.RemoveObserver(observer);
  795. }
  796. void NetworkQualityEstimator::AddRTTAndThroughputEstimatesObserver(
  797. RTTAndThroughputEstimatesObserver* observer) {
  798. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  799. DCHECK(observer);
  800. rtt_and_throughput_estimates_observer_list_.AddObserver(observer);
  801. // Notify the |observer| on the next message pump since |observer| may not
  802. // be completely set up for receiving the callbacks.
  803. base::ThreadTaskRunnerHandle::Get()->PostTask(
  804. FROM_HERE,
  805. base::BindOnce(&NetworkQualityEstimator::
  806. NotifyRTTAndThroughputEstimatesObserverIfPresent,
  807. weak_ptr_factory_.GetWeakPtr(), observer));
  808. }
  809. void NetworkQualityEstimator::RemoveRTTAndThroughputEstimatesObserver(
  810. RTTAndThroughputEstimatesObserver* observer) {
  811. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  812. rtt_and_throughput_estimates_observer_list_.RemoveObserver(observer);
  813. }
  814. bool NetworkQualityEstimator::GetRecentRTT(
  815. nqe::internal::ObservationCategory observation_category,
  816. const base::TimeTicks& start_time,
  817. base::TimeDelta* rtt,
  818. size_t* observations_count) const {
  819. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  820. *rtt = GetRTTEstimateInternal(start_time, observation_category, 50,
  821. observations_count);
  822. return (*rtt != nqe::internal::InvalidRTT());
  823. }
  824. bool NetworkQualityEstimator::GetRecentDownlinkThroughputKbps(
  825. const base::TimeTicks& start_time,
  826. int32_t* kbps) const {
  827. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  828. *kbps = GetDownlinkThroughputKbpsEstimateInternal(start_time, 50);
  829. return (*kbps != nqe::internal::INVALID_RTT_THROUGHPUT);
  830. }
  831. base::TimeDelta NetworkQualityEstimator::GetRTTEstimateInternal(
  832. base::TimeTicks start_time,
  833. nqe::internal::ObservationCategory observation_category,
  834. int percentile,
  835. size_t* observations_count) const {
  836. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  837. DCHECK_EQ(nqe::internal::OBSERVATION_CATEGORY_COUNT,
  838. std::size(rtt_ms_observations_));
  839. // RTT observations are sorted by duration from shortest to longest, thus
  840. // a higher percentile RTT will have a longer RTT than a lower percentile.
  841. switch (observation_category) {
  842. case nqe::internal::OBSERVATION_CATEGORY_HTTP:
  843. case nqe::internal::OBSERVATION_CATEGORY_TRANSPORT:
  844. case nqe::internal::OBSERVATION_CATEGORY_END_TO_END:
  845. return base::Milliseconds(
  846. rtt_ms_observations_[observation_category]
  847. .GetPercentile(start_time, current_network_id_.signal_strength,
  848. percentile, observations_count)
  849. .value_or(nqe::internal::INVALID_RTT_THROUGHPUT));
  850. case nqe::internal::OBSERVATION_CATEGORY_COUNT:
  851. NOTREACHED();
  852. return base::TimeDelta();
  853. }
  854. }
  855. int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal(
  856. const base::TimeTicks& start_time,
  857. int percentile) const {
  858. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  859. // Throughput observations are sorted by kbps from slowest to fastest,
  860. // thus a higher percentile throughput will be faster than a lower one.
  861. return http_downstream_throughput_kbps_observations_
  862. .GetPercentile(start_time, current_network_id_.signal_strength,
  863. 100 - percentile, nullptr)
  864. .value_or(nqe::internal::INVALID_RTT_THROUGHPUT);
  865. }
  866. nqe::internal::NetworkID NetworkQualityEstimator::GetCurrentNetworkID() const {
  867. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  868. // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class
  869. // that overrides this method on the Android platform.
  870. return DoGetCurrentNetworkID(params_.get());
  871. }
  872. bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
  873. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  874. if (!params_->persistent_cache_reading_enabled())
  875. return false;
  876. nqe::internal::CachedNetworkQuality cached_network_quality;
  877. const bool cached_estimate_available = network_quality_store_->GetById(
  878. current_network_id_, &cached_network_quality);
  879. UMA_HISTOGRAM_BOOLEAN("NQE.CachedNetworkQualityAvailable",
  880. cached_estimate_available);
  881. if (!cached_estimate_available)
  882. return false;
  883. EffectiveConnectionType effective_connection_type =
  884. cached_network_quality.effective_connection_type();
  885. if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
  886. effective_connection_type == EFFECTIVE_CONNECTION_TYPE_OFFLINE ||
  887. effective_connection_type == EFFECTIVE_CONNECTION_TYPE_LAST) {
  888. return false;
  889. }
  890. nqe::internal::NetworkQuality network_quality =
  891. cached_network_quality.network_quality();
  892. bool update_network_quality_store = false;
  893. // Populate |network_quality| with synthetic RTT and throughput observations
  894. // if they are missing.
  895. if (network_quality.http_rtt().InMilliseconds() ==
  896. nqe::internal::INVALID_RTT_THROUGHPUT) {
  897. network_quality.set_http_rtt(
  898. params_->TypicalNetworkQuality(effective_connection_type).http_rtt());
  899. update_network_quality_store = true;
  900. }
  901. if (network_quality.transport_rtt().InMilliseconds() ==
  902. nqe::internal::INVALID_RTT_THROUGHPUT) {
  903. network_quality.set_transport_rtt(
  904. params_->TypicalNetworkQuality(effective_connection_type)
  905. .transport_rtt());
  906. update_network_quality_store = true;
  907. }
  908. if (network_quality.downstream_throughput_kbps() ==
  909. nqe::internal::INVALID_RTT_THROUGHPUT) {
  910. network_quality.set_downstream_throughput_kbps(
  911. params_->TypicalNetworkQuality(effective_connection_type)
  912. .downstream_throughput_kbps());
  913. update_network_quality_store = true;
  914. }
  915. if (update_network_quality_store) {
  916. network_quality_store_->Add(current_network_id_,
  917. nqe::internal::CachedNetworkQuality(
  918. tick_clock_->NowTicks(), network_quality,
  919. effective_connection_type));
  920. }
  921. Observation http_rtt_observation(
  922. network_quality.http_rtt().InMilliseconds(), tick_clock_->NowTicks(),
  923. INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
  924. AddAndNotifyObserversOfRTT(http_rtt_observation);
  925. Observation transport_rtt_observation(
  926. network_quality.transport_rtt().InMilliseconds(), tick_clock_->NowTicks(),
  927. INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE);
  928. AddAndNotifyObserversOfRTT(transport_rtt_observation);
  929. Observation througphput_observation(
  930. network_quality.downstream_throughput_kbps(), tick_clock_->NowTicks(),
  931. INT32_MIN, NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE);
  932. AddAndNotifyObserversOfThroughput(througphput_observation);
  933. ComputeEffectiveConnectionType();
  934. return true;
  935. }
  936. void NetworkQualityEstimator::SetTickClockForTesting(
  937. const base::TickClock* tick_clock) {
  938. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  939. tick_clock_ = tick_clock;
  940. for (auto& rtt_ms_observation : rtt_ms_observations_)
  941. rtt_ms_observation.SetTickClockForTesting(tick_clock_); // IN-TEST
  942. http_downstream_throughput_kbps_observations_.SetTickClockForTesting(
  943. tick_clock_);
  944. throughput_analyzer_->SetTickClockForTesting(tick_clock_);
  945. watcher_factory_->SetTickClockForTesting(tick_clock_);
  946. }
  947. void NetworkQualityEstimator::OnUpdatedTransportRTTAvailable(
  948. SocketPerformanceWatcherFactory::Protocol protocol,
  949. const base::TimeDelta& rtt,
  950. const absl::optional<nqe::internal::IPHash>& host) {
  951. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  952. DCHECK_LT(nqe::internal::INVALID_RTT_THROUGHPUT, rtt.InMilliseconds());
  953. Observation observation(rtt.InMilliseconds(), tick_clock_->NowTicks(),
  954. current_network_id_.signal_strength,
  955. ProtocolSourceToObservationSource(protocol), host);
  956. AddAndNotifyObserversOfRTT(observation);
  957. }
  958. void NetworkQualityEstimator::AddAndNotifyObserversOfRTT(
  959. const Observation& observation) {
  960. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  961. DCHECK_NE(nqe::internal::InvalidRTT(),
  962. base::Milliseconds(observation.value()));
  963. DCHECK_GT(NETWORK_QUALITY_OBSERVATION_SOURCE_MAX, observation.source());
  964. if (!ShouldAddObservation(observation))
  965. return;
  966. MaybeUpdateCachedEstimateApplied(
  967. observation,
  968. &rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP]);
  969. MaybeUpdateCachedEstimateApplied(
  970. observation,
  971. &rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]);
  972. ++new_rtt_observations_since_last_ect_computation_;
  973. std::vector<nqe::internal::ObservationCategory> observation_categories =
  974. observation.GetObservationCategories();
  975. for (nqe::internal::ObservationCategory observation_category :
  976. observation_categories) {
  977. rtt_ms_observations_[observation_category].AddObservation(observation);
  978. }
  979. if (observation.source() == NETWORK_QUALITY_OBSERVATION_SOURCE_TCP ||
  980. observation.source() == NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC) {
  981. last_socket_watcher_rtt_notification_ = tick_clock_->NowTicks();
  982. }
  983. UMA_HISTOGRAM_ENUMERATION("NQE.RTT.ObservationSource", observation.source(),
  984. NETWORK_QUALITY_OBSERVATION_SOURCE_MAX);
  985. // Maybe recompute the effective connection type since a new RTT observation
  986. // is available.
  987. if (observation.source() !=
  988. NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE &&
  989. observation.source() !=
  990. NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE) {
  991. MaybeComputeEffectiveConnectionType();
  992. }
  993. for (auto& observer : rtt_observer_list_) {
  994. observer.OnRTTObservation(observation.value(), observation.timestamp(),
  995. observation.source());
  996. }
  997. }
  998. void NetworkQualityEstimator::AddAndNotifyObserversOfThroughput(
  999. const Observation& observation) {
  1000. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1001. DCHECK_NE(nqe::internal::INVALID_RTT_THROUGHPUT, observation.value());
  1002. DCHECK_GT(NETWORK_QUALITY_OBSERVATION_SOURCE_MAX, observation.source());
  1003. DCHECK_EQ(1u, observation.GetObservationCategories().size());
  1004. DCHECK_EQ(nqe::internal::OBSERVATION_CATEGORY_HTTP,
  1005. observation.GetObservationCategories().front());
  1006. if (!ShouldAddObservation(observation))
  1007. return;
  1008. MaybeUpdateCachedEstimateApplied(
  1009. observation, &http_downstream_throughput_kbps_observations_);
  1010. ++new_throughput_observations_since_last_ect_computation_;
  1011. http_downstream_throughput_kbps_observations_.AddObservation(observation);
  1012. LOCAL_HISTOGRAM_ENUMERATION("NQE.Kbps.ObservationSource",
  1013. observation.source(),
  1014. NETWORK_QUALITY_OBSERVATION_SOURCE_MAX);
  1015. // Maybe recompute the effective connection type since a new throughput
  1016. // observation is available.
  1017. if (observation.source() !=
  1018. NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE &&
  1019. observation.source() !=
  1020. NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE) {
  1021. MaybeComputeEffectiveConnectionType();
  1022. }
  1023. for (auto& observer : throughput_observer_list_) {
  1024. observer.OnThroughputObservation(
  1025. observation.value(), observation.timestamp(), observation.source());
  1026. }
  1027. }
  1028. void NetworkQualityEstimator::OnNewThroughputObservationAvailable(
  1029. int32_t downstream_kbps) {
  1030. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1031. if (downstream_kbps <= 0)
  1032. return;
  1033. DCHECK_NE(nqe::internal::INVALID_RTT_THROUGHPUT, downstream_kbps);
  1034. Observation throughput_observation(downstream_kbps, tick_clock_->NowTicks(),
  1035. current_network_id_.signal_strength,
  1036. NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP);
  1037. AddAndNotifyObserversOfThroughput(throughput_observation);
  1038. }
  1039. bool NetworkQualityEstimator::ShouldComputeEffectiveConnectionType() const {
  1040. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1041. DCHECK_EQ(nqe::internal::OBSERVATION_CATEGORY_COUNT,
  1042. std::size(rtt_ms_observations_));
  1043. const base::TimeTicks now = tick_clock_->NowTicks();
  1044. // Recompute effective connection type only if
  1045. // |effective_connection_type_recomputation_interval_| has passed since it was
  1046. // last computed or a connection change event was observed since the last
  1047. // computation. Strict inequalities are used to ensure that effective
  1048. // connection type is recomputed on connection change events even if the clock
  1049. // has not updated.
  1050. if (now - last_effective_connection_type_computation_ >=
  1051. effective_connection_type_recomputation_interval_) {
  1052. return true;
  1053. }
  1054. if (last_connection_change_ >= last_effective_connection_type_computation_) {
  1055. return true;
  1056. }
  1057. // Recompute the effective connection type if the previously computed
  1058. // effective connection type was unknown.
  1059. if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
  1060. return true;
  1061. }
  1062. // Recompute the effective connection type if the number of samples
  1063. // available now are 50% more than the number of samples that were
  1064. // available when the effective connection type was last computed.
  1065. if (rtt_observations_size_at_last_ect_computation_ * 1.5 <
  1066. (rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_HTTP].Size() +
  1067. rtt_ms_observations_[nqe::internal::OBSERVATION_CATEGORY_TRANSPORT]
  1068. .Size())) {
  1069. return true;
  1070. }
  1071. if (throughput_observations_size_at_last_ect_computation_ * 1.5 <
  1072. http_downstream_throughput_kbps_observations_.Size()) {
  1073. return true;
  1074. }
  1075. if ((new_rtt_observations_since_last_ect_computation_ +
  1076. new_throughput_observations_since_last_ect_computation_) >=
  1077. params_->count_new_observations_received_compute_ect()) {
  1078. return true;
  1079. }
  1080. return false;
  1081. }
  1082. void NetworkQualityEstimator::MaybeComputeEffectiveConnectionType() {
  1083. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1084. if (!ShouldComputeEffectiveConnectionType())
  1085. return;
  1086. ComputeEffectiveConnectionType();
  1087. }
  1088. void NetworkQualityEstimator::
  1089. NotifyObserversOfEffectiveConnectionTypeChanged() {
  1090. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1091. DCHECK_NE(EFFECTIVE_CONNECTION_TYPE_LAST, effective_connection_type_);
  1092. absl::optional<net::EffectiveConnectionType> override_ect = GetOverrideECT();
  1093. // TODO(tbansal): Add hysteresis in the notification.
  1094. for (auto& observer : effective_connection_type_observer_list_)
  1095. observer.OnEffectiveConnectionTypeChanged(
  1096. override_ect ? override_ect.value() : effective_connection_type_);
  1097. // Add the estimates of the current network to the cache store.
  1098. network_quality_store_->Add(current_network_id_,
  1099. nqe::internal::CachedNetworkQuality(
  1100. tick_clock_->NowTicks(), network_quality_,
  1101. effective_connection_type_));
  1102. }
  1103. void NetworkQualityEstimator::NotifyObserversOfRTTOrThroughputComputed() const {
  1104. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1105. // TODO(tbansal): Add hysteresis in the notification.
  1106. for (auto& observer : rtt_and_throughput_estimates_observer_list_) {
  1107. observer.OnRTTOrThroughputEstimatesComputed(
  1108. network_quality_.http_rtt(), network_quality_.transport_rtt(),
  1109. network_quality_.downstream_throughput_kbps());
  1110. }
  1111. }
  1112. void NetworkQualityEstimator::NotifyEffectiveConnectionTypeObserverIfPresent(
  1113. EffectiveConnectionTypeObserver* observer) const {
  1114. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1115. if (!effective_connection_type_observer_list_.HasObserver(observer))
  1116. return;
  1117. absl::optional<net::EffectiveConnectionType> override_ect = GetOverrideECT();
  1118. if (override_ect) {
  1119. observer->OnEffectiveConnectionTypeChanged(override_ect.value());
  1120. return;
  1121. }
  1122. if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN)
  1123. return;
  1124. observer->OnEffectiveConnectionTypeChanged(effective_connection_type_);
  1125. }
  1126. void NetworkQualityEstimator::NotifyPeerToPeerConnectionsCountObserverIfPresent(
  1127. PeerToPeerConnectionsCountObserver* observer) const {
  1128. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1129. if (!peer_to_peer_type_observer_list_.HasObserver(observer))
  1130. return;
  1131. observer->OnPeerToPeerConnectionsCountChange(p2p_connections_count_);
  1132. }
  1133. void NetworkQualityEstimator::NotifyRTTAndThroughputEstimatesObserverIfPresent(
  1134. RTTAndThroughputEstimatesObserver* observer) const {
  1135. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1136. if (!rtt_and_throughput_estimates_observer_list_.HasObserver(observer))
  1137. return;
  1138. observer->OnRTTOrThroughputEstimatesComputed(
  1139. network_quality_.http_rtt(), network_quality_.transport_rtt(),
  1140. network_quality_.downstream_throughput_kbps());
  1141. }
  1142. void NetworkQualityEstimator::AddNetworkQualitiesCacheObserver(
  1143. nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
  1144. observer) {
  1145. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1146. network_quality_store_->AddNetworkQualitiesCacheObserver(observer);
  1147. }
  1148. void NetworkQualityEstimator::RemoveNetworkQualitiesCacheObserver(
  1149. nqe::internal::NetworkQualityStore::NetworkQualitiesCacheObserver*
  1150. observer) {
  1151. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1152. network_quality_store_->RemoveNetworkQualitiesCacheObserver(observer);
  1153. }
  1154. void NetworkQualityEstimator::OnPrefsRead(
  1155. const std::map<nqe::internal::NetworkID,
  1156. nqe::internal::CachedNetworkQuality> read_prefs) {
  1157. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1158. UMA_HISTOGRAM_COUNTS_1M("NQE.Prefs.ReadSize", read_prefs.size());
  1159. for (auto& it : read_prefs) {
  1160. EffectiveConnectionType effective_connection_type =
  1161. it.second.effective_connection_type();
  1162. if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
  1163. effective_connection_type == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
  1164. continue;
  1165. }
  1166. // RTT and throughput values are not set in the prefs.
  1167. DCHECK_EQ(nqe::internal::InvalidRTT(),
  1168. it.second.network_quality().http_rtt());
  1169. DCHECK_EQ(nqe::internal::InvalidRTT(),
  1170. it.second.network_quality().transport_rtt());
  1171. DCHECK_EQ(nqe::internal::INVALID_RTT_THROUGHPUT,
  1172. it.second.network_quality().downstream_throughput_kbps());
  1173. nqe::internal::CachedNetworkQuality cached_network_quality(
  1174. tick_clock_->NowTicks(),
  1175. params_->TypicalNetworkQuality(effective_connection_type),
  1176. effective_connection_type);
  1177. network_quality_store_->Add(it.first, cached_network_quality);
  1178. }
  1179. ReadCachedNetworkQualityEstimate();
  1180. }
  1181. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1182. void NetworkQualityEstimator::EnableGetNetworkIdAsynchronously() {
  1183. get_network_id_asynchronously_ = true;
  1184. }
  1185. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  1186. absl::optional<base::TimeDelta> NetworkQualityEstimator::GetHttpRTT() const {
  1187. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1188. if (network_quality_.http_rtt() == nqe::internal::InvalidRTT())
  1189. return absl::optional<base::TimeDelta>();
  1190. return network_quality_.http_rtt();
  1191. }
  1192. absl::optional<base::TimeDelta> NetworkQualityEstimator::GetTransportRTT()
  1193. const {
  1194. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1195. if (network_quality_.transport_rtt() == nqe::internal::InvalidRTT())
  1196. return absl::optional<base::TimeDelta>();
  1197. return network_quality_.transport_rtt();
  1198. }
  1199. absl::optional<int32_t> NetworkQualityEstimator::GetDownstreamThroughputKbps()
  1200. const {
  1201. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1202. if (network_quality_.downstream_throughput_kbps() ==
  1203. nqe::internal::INVALID_RTT_THROUGHPUT) {
  1204. return absl::optional<int32_t>();
  1205. }
  1206. return network_quality_.downstream_throughput_kbps();
  1207. }
  1208. void NetworkQualityEstimator::MaybeUpdateCachedEstimateApplied(
  1209. const Observation& observation,
  1210. ObservationBuffer* buffer) {
  1211. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1212. if (observation.source() !=
  1213. NETWORK_QUALITY_OBSERVATION_SOURCE_HTTP_CACHED_ESTIMATE &&
  1214. observation.source() !=
  1215. NETWORK_QUALITY_OBSERVATION_SOURCE_TRANSPORT_CACHED_ESTIMATE) {
  1216. return;
  1217. }
  1218. cached_estimate_applied_ = true;
  1219. bool deleted_observation_sources[NETWORK_QUALITY_OBSERVATION_SOURCE_MAX] = {
  1220. false};
  1221. deleted_observation_sources
  1222. [NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM] = true;
  1223. deleted_observation_sources
  1224. [NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM] =
  1225. true;
  1226. buffer->RemoveObservationsWithSource(deleted_observation_sources);
  1227. }
  1228. bool NetworkQualityEstimator::ShouldAddObservation(
  1229. const Observation& observation) const {
  1230. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1231. if (cached_estimate_applied_ &&
  1232. (observation.source() ==
  1233. NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_HTTP_FROM_PLATFORM ||
  1234. observation.source() ==
  1235. NETWORK_QUALITY_OBSERVATION_SOURCE_DEFAULT_TRANSPORT_FROM_PLATFORM)) {
  1236. return false;
  1237. }
  1238. return true;
  1239. }
  1240. bool NetworkQualityEstimator::ShouldSocketWatcherNotifyRTT(
  1241. base::TimeTicks now) {
  1242. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1243. return (now - last_socket_watcher_rtt_notification_ >=
  1244. params_->socket_watchers_min_notification_interval());
  1245. }
  1246. void NetworkQualityEstimator::SimulateNetworkQualityChangeForTesting(
  1247. net::EffectiveConnectionType type) {
  1248. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1249. params_->SetForcedEffectiveConnectionTypeForTesting(type);
  1250. ComputeEffectiveConnectionType();
  1251. }
  1252. void NetworkQualityEstimator::ForceReportWifiAsSlow2GForTesting() {
  1253. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1254. force_report_wifi_as_slow_2g_for_testing_ = true;
  1255. }
  1256. void NetworkQualityEstimator::RecordSpdyPingLatency(
  1257. const HostPortPair& host_port_pair,
  1258. base::TimeDelta rtt) {
  1259. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1260. DCHECK_LT(nqe::internal::INVALID_RTT_THROUGHPUT, rtt.InMilliseconds());
  1261. Observation observation(rtt.InMilliseconds(), tick_clock_->NowTicks(),
  1262. current_network_id_.signal_strength,
  1263. NETWORK_QUALITY_OBSERVATION_SOURCE_H2_PINGS);
  1264. AddAndNotifyObserversOfRTT(observation);
  1265. }
  1266. void NetworkQualityEstimator::OnPeerToPeerConnectionsCountChange(
  1267. uint32_t count) {
  1268. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1269. if (p2p_connections_count_ == count)
  1270. return;
  1271. if (p2p_connections_count_ == 0 && count > 0) {
  1272. DCHECK(!p2p_connections_count_active_timestamp_);
  1273. p2p_connections_count_active_timestamp_ = tick_clock_->NowTicks();
  1274. }
  1275. if (p2p_connections_count_ > 0 && count == 0) {
  1276. DCHECK(p2p_connections_count_active_timestamp_);
  1277. base::TimeDelta duration = tick_clock_->NowTicks() -
  1278. p2p_connections_count_active_timestamp_.value();
  1279. LOCAL_HISTOGRAM_CUSTOM_TIMES("NQE.PeerToPeerConnectionsDuration", duration,
  1280. base::Milliseconds(1), base::Hours(1), 50);
  1281. p2p_connections_count_active_timestamp_ = absl::nullopt;
  1282. }
  1283. p2p_connections_count_ = count;
  1284. for (auto& observer : peer_to_peer_type_observer_list_) {
  1285. observer.OnPeerToPeerConnectionsCountChange(p2p_connections_count_);
  1286. }
  1287. }
  1288. uint32_t NetworkQualityEstimator::GetPeerToPeerConnectionsCountChange() const {
  1289. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  1290. return p2p_connections_count_;
  1291. }
  1292. } // namespace net