| Index: content/browser/net/network_quality_observer_impl.cc
|
| diff --git a/content/browser/net/network_quality_observer_impl.cc b/content/browser/net/network_quality_observer_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a92ea1a9a5a20d899cb7847286ee663067dc2885
|
| --- /dev/null
|
| +++ b/content/browser/net/network_quality_observer_impl.cc
|
| @@ -0,0 +1,184 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/net/network_quality_observer_impl.h"
|
| +
|
| +#include "base/memory/ptr_util.h"
|
| +#include "content/browser/renderer_host/render_process_host_impl.h"
|
| +#include "content/common/view_messages.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/notification_observer.h"
|
| +#include "content/public/browser/notification_registrar.h"
|
| +#include "content/public/browser/notification_service.h"
|
| +#include "content/public/browser/notification_types.h"
|
| +#include "content/public/browser/render_process_host.h"
|
| +
|
| +namespace {
|
| +
|
| +// Returns true if the |current_value| is meaningfully different from the
|
| +// |past_value|.
|
| +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;
|
| + }
|
| +
|
| + // Metric has changed meaningfully only if (i) the difference between the two
|
| + // values exceed the threshold; and, (ii) the ratio of the values also exceeds
|
| + // the threshold.
|
| + static const int kMinDifferenceInMetrics = 100;
|
| + static const float kMinRatio = 1.2f;
|
| +
|
| + if (std::abs(past_value - current_value) < kMinDifferenceInMetrics) {
|
| + // The absolute change in the value is not sufficient enough.
|
| + return false;
|
| + }
|
| +
|
| + if (past_value < (kMinRatio * current_value) &&
|
| + current_value < (kMinRatio * past_value)) {
|
| + // The relative change in the value is not sufficient enough.
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +namespace content {
|
| +
|
| +// UiThreadObserver observes the changes to the network quality on the UI
|
| +// thread, and notifies the renderers of the change in the network quality.
|
| +class NetworkQualityObserverImpl::UiThreadObserver
|
| + : public content::NotificationObserver {
|
| + public:
|
| + UiThreadObserver() {}
|
| +
|
| + ~UiThreadObserver() override {
|
| + registrar_.Remove(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
|
| + NotificationService::AllSources());
|
| + }
|
| +
|
| + void InitOnUIThread() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED,
|
| + NotificationService::AllSources());
|
| + }
|
| +
|
| + void OnRTTOrThroughputEstimatesComputed(
|
| + const net::nqe::internal::NetworkQuality& network_quality) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + last_notified_network_quality_ = network_quality;
|
| +
|
| + // Notify all the existing renderers of the change in the network quality.
|
| + for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
|
| + !it.IsAtEnd(); it.Advance()) {
|
| + it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged(
|
| + last_notified_network_quality_.http_rtt().InMilliseconds(),
|
| + last_notified_network_quality_.transport_rtt().InMilliseconds(),
|
| + last_notified_network_quality_.downstream_throughput_kbps());
|
| + }
|
| + }
|
| +
|
| + private:
|
| + // NotificationObserver implementation:
|
| + void Observe(int type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) override {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| + DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type);
|
| +
|
| + RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
|
| +
|
| + // Notify the newly created renderer of the current network quality.
|
| + rph->GetRendererInterface()->OnNetworkQualityChanged(
|
| + last_notified_network_quality_.http_rtt().InMilliseconds(),
|
| + last_notified_network_quality_.transport_rtt().InMilliseconds(),
|
| + last_notified_network_quality_.downstream_throughput_kbps());
|
| + }
|
| +
|
| + content::NotificationRegistrar registrar_;
|
| +
|
| + // The network quality that was last sent to the renderers.
|
| + net::nqe::internal::NetworkQuality last_notified_network_quality_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(UiThreadObserver);
|
| +};
|
| +
|
| +NetworkQualityObserverImpl::NetworkQualityObserverImpl(
|
| + net::NetworkQualityEstimator* network_quality_estimator)
|
| + : network_quality_estimator_(network_quality_estimator) {
|
| + network_quality_estimator_->AddRTTAndThroughputEstimatesObserver(this);
|
| +
|
| + ui_thread_observer_ = base::MakeUnique<UiThreadObserver>();
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::BindOnce(&UiThreadObserver::InitOnUIThread,
|
| + base::Unretained(ui_thread_observer_.get())));
|
| +}
|
| +
|
| +NetworkQualityObserverImpl::~NetworkQualityObserverImpl() {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + network_quality_estimator_->RemoveRTTAndThroughputEstimatesObserver(this);
|
| +
|
| + DCHECK(ui_thread_observer_);
|
| +
|
| + // If possible, delete |ui_thread_observer_| on UI thread.
|
| + UiThreadObserver* ui_thread_observer_ptr = ui_thread_observer_.release();
|
| + bool posted = BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE,
|
| + ui_thread_observer_ptr);
|
| +
|
| + if (!posted)
|
| + delete ui_thread_observer_ptr;
|
| +}
|
| +
|
| +void NetworkQualityObserverImpl::OnRTTOrThroughputEstimatesComputed(
|
| + base::TimeDelta http_rtt,
|
| + base::TimeDelta transport_rtt,
|
| + int32_t downstream_throughput_kbps) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| + // Check if any of the network quality metrics changed meaningfully.
|
| + 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);
|
| +
|
| + if (!http_rtt_changed && !transport_rtt_changed && !kbps_changed) {
|
| + // Return since none of the metrics changed meaningfully. This reduces
|
| + // the number of notifications to the different renderers every time
|
| + // the network quality is recomputed.
|
| + return;
|
| + }
|
| +
|
| + last_notified_network_quality_ = net::nqe::internal::NetworkQuality(
|
| + http_rtt, transport_rtt, downstream_throughput_kbps);
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + base::BindOnce(&UiThreadObserver::OnRTTOrThroughputEstimatesComputed,
|
| + base::Unretained(ui_thread_observer_.get()),
|
| + last_notified_network_quality_));
|
| +}
|
| +
|
| +std::unique_ptr<net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver>
|
| +CreateNetworkQualityObserver(
|
| + net::NetworkQualityEstimator* network_quality_estimator) {
|
| + return base::MakeUnique<NetworkQualityObserverImpl>(
|
| + network_quality_estimator);
|
| +}
|
| +
|
| +} // namespace content
|
|
|