#include "content/browser/network/network_quality_observer_impl.h"
#include "base/metrics/histogram_macros.h"
#include "content/common/renderer.mojom.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/network_quality_observer_factory.h"
#include "content/public/browser/render_process_host.h"
namespace {
bool MetricChangedMeaningfully(int32_t past_value, int32_t current_value) {
if ((past_value == net::nqe::internal::INVALID_RTT_THROUGHPUT) !=
(current_value == net::nqe::internal::INVALID_RTT_THROUGHPUT)) {
return true;
}
if (past_value == net::nqe::internal::INVALID_RTT_THROUGHPUT &&
current_value == net::nqe::internal::INVALID_RTT_THROUGHPUT) {
return false;
}
DCHECK_LE(0, past_value);
DCHECK_LE(0, current_value);
static const int kMinDifferenceInMetrics = 100;
static const float kMinRatio = 1.2f;
if (std::abs(past_value - current_value) < kMinDifferenceInMetrics) {
return false;
}
if (past_value < (kMinRatio * current_value) &&
current_value < (kMinRatio * past_value)) {
return false;
}
return true;
}
}
namespace content {
NetworkQualityObserverImpl::NetworkQualityObserverImpl(
network::NetworkQualityTracker* network_quality_tracker)
: network_quality_tracker_(network_quality_tracker),
last_notified_type_(net::EFFECTIVE_CONNECTION_TYPE_UNKNOWN) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
network_quality_tracker_->AddRTTAndThroughputEstimatesObserver(this);
network_quality_tracker_->AddEffectiveConnectionTypeObserver(this);
}
NetworkQualityObserverImpl::~NetworkQualityObserverImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
network_quality_tracker_->RemoveRTTAndThroughputEstimatesObserver(this);
network_quality_tracker_->RemoveEffectiveConnectionTypeObserver(this);
}
void NetworkQualityObserverImpl::OnEffectiveConnectionTypeChanged(
net::EffectiveConnectionType type) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (last_notified_type_ == type)
return;
last_notified_type_ = type;
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
last_notified_type_, last_notified_network_quality_.http_rtt(),
last_notified_network_quality_.transport_rtt(),
last_notified_network_quality_.downstream_throughput_kbps());
}
}
}
void NetworkQualityObserverImpl::OnRenderProcessHostCreated(
content::RenderProcessHost* rph) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
rph->GetRendererInterface()->OnNetworkQualityChanged(
last_notified_type_, last_notified_network_quality_.http_rtt(),
last_notified_network_quality_.transport_rtt(),
last_notified_network_quality_.downstream_throughput_kbps());
}
void NetworkQualityObserverImpl::OnRTTOrThroughputEstimatesComputed(
base::TimeDelta http_rtt,
base::TimeDelta transport_rtt,
int32_t downstream_throughput_kbps) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
bool http_rtt_changed = MetricChangedMeaningfully(
last_notified_network_quality_.http_rtt().InMilliseconds(),
http_rtt.InMilliseconds());
bool transport_rtt_changed = MetricChangedMeaningfully(
last_notified_network_quality_.transport_rtt().InMilliseconds(),
transport_rtt.InMilliseconds());
bool kbps_changed = MetricChangedMeaningfully(
last_notified_network_quality_.downstream_throughput_kbps(),
downstream_throughput_kbps);
bool network_quality_meaningfully_changed =
http_rtt_changed || transport_rtt_changed || kbps_changed;
LOCAL_HISTOGRAM_BOOLEAN(
"NQE.ContentObserver.NetworkQualityMeaningfullyChanged",
network_quality_meaningfully_changed);
if (!network_quality_meaningfully_changed) {
return;
}
last_notified_network_quality_ = net::nqe::internal::NetworkQuality(
http_rtt, transport_rtt, downstream_throughput_kbps);
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue()->IsInitializedAndNotDead()) {
it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
last_notified_type_, last_notified_network_quality_.http_rtt(),
last_notified_network_quality_.transport_rtt(),
last_notified_network_quality_.downstream_throughput_kbps());
}
}
}
std::unique_ptr<
network::NetworkQualityTracker::RTTAndThroughputEstimatesObserver>
CreateNetworkQualityObserver(
network::NetworkQualityTracker* network_quality_tracker) {
return std::make_unique<NetworkQualityObserverImpl>(network_quality_tracker);
}
}