| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/nqe/network_quality_estimator.h" | 5 #include "net/nqe/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 86 // parameter for Wi-Fi would be "WiFi.DefaultMedianKbps". | 86 // parameter for Wi-Fi would be "WiFi.DefaultMedianKbps". |
| 87 const char kDefaultKbpsObservationSuffix[] = ".DefaultMedianKbps"; | 87 const char kDefaultKbpsObservationSuffix[] = ".DefaultMedianKbps"; |
| 88 | 88 |
| 89 // Suffix of the name of the variation parameter that contains the threshold | 89 // Suffix of the name of the variation parameter that contains the threshold |
| 90 // HTTP RTTs (in milliseconds) for different effective connection types. | 90 // HTTP RTTs (in milliseconds) for different effective connection types. |
| 91 // Complete name of the variation parameter would be | 91 // Complete name of the variation parameter would be |
| 92 // |EffectiveConnectionType|.|kThresholdURLRTTMsecSuffix|. | 92 // |EffectiveConnectionType|.|kThresholdURLRTTMsecSuffix|. |
| 93 const char kThresholdURLRTTMsecSuffix[] = ".ThresholdMedianHttpRTTMsec"; | 93 const char kThresholdURLRTTMsecSuffix[] = ".ThresholdMedianHttpRTTMsec"; |
| 94 | 94 |
| 95 // Suffix of the name of the variation parameter that contains the threshold | 95 // Suffix of the name of the variation parameter that contains the threshold |
| 96 // transport RTTs (in milliseconds) for different effective connection types. |
| 97 // Complete name of the variation parameter would be |
| 98 // |EffectiveConnectionType|.|kThresholdTransportRTTMsecSuffix|. |
| 99 const char kThresholdTransportRTTMsecSuffix[] = |
| 100 ".ThresholdMedianTransportRTTMsec"; |
| 101 |
| 102 // Suffix of the name of the variation parameter that contains the threshold |
| 96 // downlink throughput (in kbps) for different effective connection types. | 103 // downlink throughput (in kbps) for different effective connection types. |
| 97 // Complete name of the variation parameter would be | 104 // Complete name of the variation parameter would be |
| 98 // |EffectiveConnectionType|.|kThresholdKbpsSuffix|. | 105 // |EffectiveConnectionType|.|kThresholdKbpsSuffix|. |
| 99 const char kThresholdKbpsSuffix[] = ".ThresholdMedianKbps"; | 106 const char kThresholdKbpsSuffix[] = ".ThresholdMedianKbps"; |
| 100 | 107 |
| 101 // Computes and returns the weight multiplier per second. | 108 // Computes and returns the weight multiplier per second. |
| 102 // |variation_params| is the map containing all field trial parameters | 109 // |variation_params| is the map containing all field trial parameters |
| 103 // related to NetworkQualityEstimator field trial. | 110 // related to NetworkQualityEstimator field trial. |
| 104 double GetWeightMultiplierPerSecond( | 111 double GetWeightMultiplierPerSecond( |
| 105 const std::map<std::string, std::string>& variation_params) { | 112 const std::map<std::string, std::string>& variation_params) { |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 220 false, | 227 false, |
| 221 false) {} | 228 false) {} |
| 222 | 229 |
| 223 NetworkQualityEstimator::NetworkQualityEstimator( | 230 NetworkQualityEstimator::NetworkQualityEstimator( |
| 224 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 231 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 225 const std::map<std::string, std::string>& variation_params, | 232 const std::map<std::string, std::string>& variation_params, |
| 226 bool use_local_host_requests_for_tests, | 233 bool use_local_host_requests_for_tests, |
| 227 bool use_smaller_responses_for_tests) | 234 bool use_smaller_responses_for_tests) |
| 228 : algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput", | 235 : algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput", |
| 229 EffectiveConnectionTypeAlgorithm:: | 236 EffectiveConnectionTypeAlgorithm:: |
| 230 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT}}), | 237 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT}, |
| 238 {"TransportRTTOrDownstreamThroughput", |
| 239 EffectiveConnectionTypeAlgorithm:: |
| 240 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT}}), |
| 231 use_localhost_requests_(use_local_host_requests_for_tests), | 241 use_localhost_requests_(use_local_host_requests_for_tests), |
| 232 use_small_responses_(use_smaller_responses_for_tests), | 242 use_small_responses_(use_smaller_responses_for_tests), |
| 233 weight_multiplier_per_second_( | 243 weight_multiplier_per_second_( |
| 234 GetWeightMultiplierPerSecond(variation_params)), | 244 GetWeightMultiplierPerSecond(variation_params)), |
| 235 effective_connection_type_algorithm_( | 245 effective_connection_type_algorithm_( |
| 236 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( | 246 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( |
| 237 variation_params)) == algorithm_name_to_enum_.end() | 247 variation_params)) == algorithm_name_to_enum_.end() |
| 238 ? kDefaultEffectiveConnectionTypeAlgorithm | 248 ? kDefaultEffectiveConnectionTypeAlgorithm |
| 239 : algorithm_name_to_enum_ | 249 : algorithm_name_to_enum_ |
| 240 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) | 250 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 continue; | 376 continue; |
| 367 | 377 |
| 368 std::string connection_type_name = std::string( | 378 std::string connection_type_name = std::string( |
| 369 GetNameForEffectiveConnectionType(effective_connection_type)); | 379 GetNameForEffectiveConnectionType(effective_connection_type)); |
| 370 | 380 |
| 371 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; | 381 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 372 if (GetValueForVariationParam( | 382 if (GetValueForVariationParam( |
| 373 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, | 383 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, |
| 374 &variations_value) && | 384 &variations_value) && |
| 375 variations_value >= kMinimumRTTVariationParameterMsec) { | 385 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 376 base::TimeDelta rtt(base::TimeDelta::FromMilliseconds(variations_value)); | 386 connection_thresholds_[i].set_http_rtt( |
| 377 connection_thresholds_[i] = nqe::internal::NetworkQuality( | 387 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
| 378 rtt, connection_thresholds_[i].transport_rtt(), | |
| 379 connection_thresholds_[i].downstream_throughput_kbps()); | |
| 380 | 388 |
| 381 // Verify that the RTT values are in decreasing order as the network | 389 // Verify that the RTT values are in decreasing order as the network |
| 382 // quality improves. | 390 // quality improves. |
| 383 DCHECK(i == 0 || | 391 DCHECK(i == 0 || |
| 384 connection_thresholds_[i - 1].http_rtt() == | 392 connection_thresholds_[i - 1].http_rtt() == |
| 385 nqe::internal::InvalidRTT() || | 393 nqe::internal::InvalidRTT() || |
| 386 rtt <= connection_thresholds_[i - 1].http_rtt()); | 394 connection_thresholds_[i].http_rtt() <= |
| 395 connection_thresholds_[i - 1].http_rtt()); |
| 396 } |
| 397 |
| 398 variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 399 if (GetValueForVariationParam( |
| 400 variation_params, |
| 401 connection_type_name + kThresholdTransportRTTMsecSuffix, |
| 402 &variations_value) && |
| 403 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 404 connection_thresholds_[i].set_transport_rtt( |
| 405 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
| 406 |
| 407 // Verify that the transport RTT values are in decreasing order as the |
| 408 // network quality improves. |
| 409 DCHECK(i == 0 || |
| 410 connection_thresholds_[i - 1].transport_rtt() == |
| 411 nqe::internal::InvalidRTT() || |
| 412 connection_thresholds_[i].transport_rtt() <= |
| 413 connection_thresholds_[i - 1].transport_rtt()); |
| 387 } | 414 } |
| 388 | 415 |
| 389 variations_value = kMinimumThroughputVariationParameterKbps - 1; | 416 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
| 390 if (GetValueForVariationParam(variation_params, | 417 if (GetValueForVariationParam(variation_params, |
| 391 connection_type_name + kThresholdKbpsSuffix, | 418 connection_type_name + kThresholdKbpsSuffix, |
| 392 &variations_value) && | 419 &variations_value) && |
| 393 variations_value >= kMinimumThroughputVariationParameterKbps) { | 420 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 394 int32_t throughput_kbps = variations_value; | 421 connection_thresholds_[i].set_downstream_throughput_kbps( |
| 395 connection_thresholds_[i] = nqe::internal::NetworkQuality( | 422 variations_value); |
| 396 connection_thresholds_[i].http_rtt(), | |
| 397 connection_thresholds_[i].transport_rtt(), throughput_kbps); | |
| 398 | 423 |
| 399 // Verify that the throughput values are in increasing order as the | 424 // Verify that the throughput values are in increasing order as the |
| 400 // network quality improves. | 425 // network quality improves. |
| 401 DCHECK(i == 0 || | 426 DCHECK(i == 0 || |
| 402 connection_thresholds_[i - 1].downstream_throughput_kbps() == | 427 connection_thresholds_[i - 1].downstream_throughput_kbps() == |
| 403 kMinimumThroughputVariationParameterKbps || | 428 kMinimumThroughputVariationParameterKbps || |
| 404 throughput_kbps >= | 429 connection_thresholds_[i].downstream_throughput_kbps() >= |
| 405 connection_thresholds_[i - 1].downstream_throughput_kbps()); | 430 connection_thresholds_[i - 1].downstream_throughput_kbps()); |
| 406 } | 431 } |
| 407 } | 432 } |
| 408 } | 433 } |
| 409 | 434 |
| 410 void NetworkQualityEstimator::AddDefaultEstimates() { | 435 void NetworkQualityEstimator::AddDefaultEstimates() { |
| 411 DCHECK(thread_checker_.CalledOnValidThread()); | 436 DCHECK(thread_checker_.CalledOnValidThread()); |
| 412 | 437 |
| 413 if (default_observations_[current_network_id_.type].http_rtt() != | 438 if (default_observations_[current_network_id_.type].http_rtt() != |
| 414 nqe::internal::InvalidRTT()) { | 439 nqe::internal::InvalidRTT()) { |
| (...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 882 return GetRecentEffectiveConnectionType(base::TimeTicks()); | 907 return GetRecentEffectiveConnectionType(base::TimeTicks()); |
| 883 } | 908 } |
| 884 | 909 |
| 885 NetworkQualityEstimator::EffectiveConnectionType | 910 NetworkQualityEstimator::EffectiveConnectionType |
| 886 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 911 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
| 887 const base::TimeTicks& start_time) const { | 912 const base::TimeTicks& start_time) const { |
| 888 DCHECK(thread_checker_.CalledOnValidThread()); | 913 DCHECK(thread_checker_.CalledOnValidThread()); |
| 889 | 914 |
| 890 if (effective_connection_type_algorithm_ == | 915 if (effective_connection_type_algorithm_ == |
| 891 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { | 916 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { |
| 892 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 917 return GetRecentEffectiveConnectionTypeUsingMetrics( |
| 893 start_time); | 918 start_time, NetworkQualityEstimator::MetricUsage:: |
| 919 MUST_BE_USED /* http_rtt_metric */, |
| 920 NetworkQualityEstimator::MetricUsage:: |
| 921 DO_NOT_USE /* transport_rtt_metric */, |
| 922 NetworkQualityEstimator::MetricUsage:: |
| 923 MUST_BE_USED /* downstream_throughput_kbps_metric */); |
| 924 } |
| 925 if (effective_connection_type_algorithm_ == |
| 926 EffectiveConnectionTypeAlgorithm:: |
| 927 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT) { |
| 928 return GetRecentEffectiveConnectionTypeUsingMetrics( |
| 929 start_time, |
| 930 NetworkQualityEstimator::MetricUsage::DO_NOT_USE /* http_rtt_metric */, |
| 931 NetworkQualityEstimator::MetricUsage:: |
| 932 USE_IF_AVAILABLE /* transport_rtt_metric */, |
| 933 NetworkQualityEstimator::MetricUsage:: |
| 934 USE_IF_AVAILABLE /* downstream_throughput_kbps_metric */); |
| 894 } | 935 } |
| 895 // Add additional algorithms here. | 936 // Add additional algorithms here. |
| 896 NOTREACHED(); | 937 NOTREACHED(); |
| 897 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 938 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 898 } | 939 } |
| 899 | 940 |
| 900 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: | 941 NetworkQualityEstimator::EffectiveConnectionType |
| 901 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 942 NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics( |
| 902 const base::TimeTicks& start_time) const { | 943 const base::TimeTicks& start_time, |
| 944 NetworkQualityEstimator::MetricUsage http_rtt_metric, |
| 945 NetworkQualityEstimator::MetricUsage transport_rtt_metric, |
| 946 NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric) |
| 947 const { |
| 903 DCHECK(thread_checker_.CalledOnValidThread()); | 948 DCHECK(thread_checker_.CalledOnValidThread()); |
| 904 | 949 |
| 905 // If the device is currently offline, then return | 950 // If the device is currently offline, then return |
| 906 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. | 951 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. |
| 907 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) | 952 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) |
| 908 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; | 953 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; |
| 909 | 954 |
| 910 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); | 955 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); |
| 911 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) | 956 if (http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 957 !GetRecentHttpRTTMedian(start_time, &http_rtt)) { |
| 912 http_rtt = nqe::internal::InvalidRTT(); | 958 http_rtt = nqe::internal::InvalidRTT(); |
| 959 } |
| 960 |
| 961 base::TimeDelta transport_rtt = nqe::internal::InvalidRTT(); |
| 962 if (transport_rtt_metric != |
| 963 NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 964 !GetRecentTransportRTTMedian(start_time, &transport_rtt)) { |
| 965 transport_rtt = nqe::internal::InvalidRTT(); |
| 966 } |
| 913 | 967 |
| 914 int32_t kbps = nqe::internal::kInvalidThroughput; | 968 int32_t kbps = nqe::internal::kInvalidThroughput; |
| 915 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) | 969 if (downstream_throughput_kbps_metric != |
| 970 NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 971 !GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) { |
| 916 kbps = nqe::internal::kInvalidThroughput; | 972 kbps = nqe::internal::kInvalidThroughput; |
| 973 } |
| 917 | 974 |
| 918 if (http_rtt == nqe::internal::InvalidRTT() || | 975 if (http_rtt == nqe::internal::InvalidRTT() && |
| 919 kbps == nqe::internal::kInvalidThroughput) { | 976 http_rtt_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
| 920 // Quality of the current network is unknown. | |
| 921 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 977 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 922 } | 978 } |
| 923 | 979 |
| 980 if (transport_rtt == nqe::internal::InvalidRTT() && |
| 981 transport_rtt_metric == |
| 982 NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
| 983 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 984 } |
| 985 |
| 986 if (kbps == nqe::internal::kInvalidThroughput && |
| 987 downstream_throughput_kbps_metric == |
| 988 NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
| 989 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 990 } |
| 991 |
| 992 if (http_rtt == nqe::internal::InvalidRTT() && |
| 993 transport_rtt == nqe::internal::InvalidRTT() && |
| 994 kbps == nqe::internal::kInvalidThroughput) { |
| 995 // None of the metrics are available. |
| 996 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 997 } |
| 998 |
| 924 // Search from the slowest connection type to the fastest to find the | 999 // Search from the slowest connection type to the fastest to find the |
| 925 // EffectiveConnectionType that best matches the current connection's | 1000 // EffectiveConnectionType that best matches the current connection's |
| 926 // performance. The match is done by comparing RTT and throughput. | 1001 // performance. The match is done by comparing RTT and throughput. |
| 927 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 1002 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 928 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 1003 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
| 929 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 1004 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 930 continue; | 1005 continue; |
| 931 bool estimated_http_rtt_is_higher_than_threshold = | 1006 |
| 1007 const bool estimated_http_rtt_is_higher_than_threshold = |
| 932 http_rtt != nqe::internal::InvalidRTT() && | 1008 http_rtt != nqe::internal::InvalidRTT() && |
| 933 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && | 1009 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && |
| 934 http_rtt >= connection_thresholds_[i].http_rtt(); | 1010 http_rtt >= connection_thresholds_[i].http_rtt(); |
| 935 bool estimated_throughput_is_lower_than_threshold = | 1011 |
| 1012 const bool estimated_transport_rtt_is_higher_than_threshold = |
| 1013 transport_rtt != nqe::internal::InvalidRTT() && |
| 1014 connection_thresholds_[i].transport_rtt() != |
| 1015 nqe::internal::InvalidRTT() && |
| 1016 transport_rtt >= connection_thresholds_[i].transport_rtt(); |
| 1017 |
| 1018 const bool estimated_throughput_is_lower_than_threshold = |
| 936 kbps != nqe::internal::kInvalidThroughput && | 1019 kbps != nqe::internal::kInvalidThroughput && |
| 937 connection_thresholds_[i].downstream_throughput_kbps() != | 1020 connection_thresholds_[i].downstream_throughput_kbps() != |
| 938 nqe::internal::kInvalidThroughput && | 1021 nqe::internal::kInvalidThroughput && |
| 939 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); | 1022 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); |
| 940 | 1023 |
| 941 // Return |type| as the effective connection type if the current network's | |
| 942 // RTT is worse than the threshold RTT for |type|, or if the current | |
| 943 // network's throughput is lower than the threshold throughput for |type|. | |
| 944 if (estimated_http_rtt_is_higher_than_threshold || | 1024 if (estimated_http_rtt_is_higher_than_threshold || |
| 1025 estimated_transport_rtt_is_higher_than_threshold || |
| 945 estimated_throughput_is_lower_than_threshold) { | 1026 estimated_throughput_is_lower_than_threshold) { |
| 946 return type; | 1027 return type; |
| 947 } | 1028 } |
| 948 } | 1029 } |
| 949 // Return the fastest connection type. | 1030 // Return the fastest connection type. |
| 950 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | 1031 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - |
| 951 1); | 1032 1); |
| 952 } | 1033 } |
| 953 | 1034 |
| 954 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( | 1035 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1360 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1441 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1361 DCHECK(thread_checker_.CalledOnValidThread()); | 1442 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1362 | 1443 |
| 1363 // TODO(tbansal): Add hysteresis in the notification. | 1444 // TODO(tbansal): Add hysteresis in the notification. |
| 1364 FOR_EACH_OBSERVER( | 1445 FOR_EACH_OBSERVER( |
| 1365 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1446 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1366 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1447 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1367 } | 1448 } |
| 1368 | 1449 |
| 1369 } // namespace net | 1450 } // namespace net |
| OLD | NEW |