OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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 | |
5 #include "content/browser/net/network_quality_observer_impl.h" | |
6 | |
7 #include "base/memory/ptr_util.h" | |
8 #include "content/browser/renderer_host/render_process_host_impl.h" | |
9 #include "content/common/view_messages.h" | |
10 #include "content/public/browser/browser_thread.h" | |
11 #include "content/public/browser/notification_observer.h" | |
12 #include "content/public/browser/notification_registrar.h" | |
13 #include "content/public/browser/notification_service.h" | |
14 #include "content/public/browser/notification_types.h" | |
15 #include "content/public/browser/render_process_host.h" | |
16 | |
17 namespace { | |
18 | |
19 // Returns true if the |current_value| is meaningfully different from the | |
20 // |past_value|. | |
21 bool MetricChangedMeaningfully(int32_t past_value, int32_t current_value) { | |
22 if ((past_value == net::nqe::internal::INVALID_RTT_THROUGHPUT) != | |
23 (current_value == net::nqe::internal::INVALID_RTT_THROUGHPUT)) { | |
24 return true; | |
25 } | |
26 | |
27 if (past_value == net::nqe::internal::INVALID_RTT_THROUGHPUT && | |
28 current_value == net::nqe::internal::INVALID_RTT_THROUGHPUT) { | |
29 return false; | |
30 } | |
31 | |
32 // Metric has changed meaningfully only if (i) the difference between the two | |
33 // values exceed the threshold; and, (ii) the ratio of the values also exceeds | |
34 // the threshold. | |
35 static const int kMinDifferenceInMetrics = 100; | |
36 static const float kMinRatio = 1.2f; | |
37 | |
38 if (std::abs(past_value - current_value) < kMinDifferenceInMetrics) { | |
39 // The absolute change in the value is not sufficient enough. | |
40 return false; | |
41 } | |
42 | |
43 if (past_value < (kMinRatio * current_value) && | |
44 current_value < (kMinRatio * past_value)) { | |
45 // The relative change in the value is not sufficient enough. | |
46 return false; | |
47 } | |
48 | |
49 return true; | |
50 } | |
51 | |
52 } // namespace | |
53 | |
54 namespace content { | |
55 | |
56 // UiThreadObserver observes the changes to the network quality on the UI | |
57 // thread, and notifies the renderers of the change in the network quality. | |
58 class NetworkQualityObserverImpl::UiThreadObserver | |
59 : public content::NotificationObserver { | |
60 public: | |
61 UiThreadObserver() {} | |
62 | |
63 ~UiThreadObserver() override {} | |
64 | |
65 void InitOnUIThread() { | |
66 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
67 registrar_.Add(this, NOTIFICATION_RENDERER_PROCESS_CREATED, | |
nasko
2017/05/09 20:27:47
Shouldn't there be a Remove couterpart of this cal
tbansal1
2017/05/09 21:37:18
Done.
| |
68 NotificationService::AllSources()); | |
69 } | |
70 | |
71 void OnRTTOrThroughputEstimatesComputed( | |
72 const net::nqe::internal::NetworkQuality& network_quality) { | |
73 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
74 | |
75 last_notified_network_quality_ = network_quality; | |
76 | |
77 // Notify all the existing renderers of the change in the network quality. | |
78 for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); | |
79 !it.IsAtEnd(); it.Advance()) { | |
80 it.GetCurrentValue()->GetRendererInterface()->OnNetworkQualityChanged( | |
81 last_notified_network_quality_.http_rtt().InMilliseconds(), | |
82 last_notified_network_quality_.transport_rtt().InMilliseconds(), | |
83 last_notified_network_quality_.downstream_throughput_kbps()); | |
84 } | |
85 } | |
86 | |
87 private: | |
88 // NotificationObserver implementation: | |
89 void Observe(int type, | |
90 const NotificationSource& source, | |
91 const NotificationDetails& details) override { | |
92 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
93 DCHECK_EQ(NOTIFICATION_RENDERER_PROCESS_CREATED, type); | |
94 | |
95 RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr(); | |
96 | |
97 // Notify the newly created renderer of the current network quality. | |
98 rph->GetRendererInterface()->OnNetworkQualityChanged( | |
99 last_notified_network_quality_.http_rtt().InMilliseconds(), | |
100 last_notified_network_quality_.transport_rtt().InMilliseconds(), | |
101 last_notified_network_quality_.downstream_throughput_kbps()); | |
102 } | |
103 | |
104 content::NotificationRegistrar registrar_; | |
105 | |
106 // The network quality that was last notified to the renderers. | |
nasko
2017/05/09 20:27:47
nit: s/notified/sent/
tbansal1
2017/05/09 21:37:18
Done.
| |
107 net::nqe::internal::NetworkQuality last_notified_network_quality_; | |
108 | |
109 DISALLOW_COPY_AND_ASSIGN(UiThreadObserver); | |
110 }; | |
111 | |
112 NetworkQualityObserverImpl::NetworkQualityObserverImpl( | |
113 net::NetworkQualityEstimator* network_quality_estimator) | |
114 : network_quality_estimator_(network_quality_estimator) { | |
115 network_quality_estimator_->AddRTTAndThroughputEstimatesObserver(this); | |
116 | |
117 ui_thread_observer_ = base::MakeUnique<UiThreadObserver>(); | |
118 BrowserThread::PostTask( | |
119 BrowserThread::UI, FROM_HERE, | |
120 base::BindOnce(&UiThreadObserver::InitOnUIThread, | |
121 base::Unretained(ui_thread_observer_.get()))); | |
122 } | |
123 | |
124 NetworkQualityObserverImpl::~NetworkQualityObserverImpl() { | |
125 DCHECK(thread_checker_.CalledOnValidThread()); | |
126 network_quality_estimator_->RemoveRTTAndThroughputEstimatesObserver(this); | |
127 | |
128 if (!ui_thread_observer_) | |
129 return; | |
130 | |
131 // |ui_thread_observer_| must be deleted on UI thread. | |
132 BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, | |
133 ui_thread_observer_.release()); | |
nasko
2017/05/09 20:27:47
You probably want to check the return value of Del
tbansal1
2017/05/09 21:37:18
Done.
| |
134 } | |
135 | |
136 void NetworkQualityObserverImpl::OnRTTOrThroughputEstimatesComputed( | |
137 base::TimeDelta http_rtt, | |
138 base::TimeDelta transport_rtt, | |
139 int32_t downstream_throughput_kbps) { | |
140 DCHECK(thread_checker_.CalledOnValidThread()); | |
141 | |
142 // Check if any of the network quality metrics changed meaningfully. | |
143 bool http_rtt_changed = MetricChangedMeaningfully( | |
144 last_notified_network_quality_.http_rtt().InMilliseconds(), | |
145 http_rtt.InMilliseconds()); | |
146 | |
147 bool transport_rtt_changed = MetricChangedMeaningfully( | |
148 last_notified_network_quality_.transport_rtt().InMilliseconds(), | |
149 transport_rtt.InMilliseconds()); | |
150 bool kbps_changed = MetricChangedMeaningfully( | |
151 last_notified_network_quality_.downstream_throughput_kbps(), | |
152 downstream_throughput_kbps); | |
153 | |
154 if (!http_rtt_changed && !transport_rtt_changed && !kbps_changed) { | |
155 // Return since none of the metrics changed meaningfully. This reduces | |
156 // the number of notifications to the different renderers every time | |
157 // the network quality is recomputed. | |
158 return; | |
159 } | |
160 | |
161 last_notified_network_quality_ = net::nqe::internal::NetworkQuality( | |
162 http_rtt, transport_rtt, downstream_throughput_kbps); | |
163 | |
164 BrowserThread::PostTask( | |
165 BrowserThread::UI, FROM_HERE, | |
166 base::BindOnce(&UiThreadObserver::OnRTTOrThroughputEstimatesComputed, | |
167 base::Unretained(ui_thread_observer_.get()), | |
168 last_notified_network_quality_)); | |
169 } | |
170 | |
171 std::unique_ptr<net::NetworkQualityEstimator::RTTAndThroughputEstimatesObserver> | |
172 CreateNetworkQualityObserver( | |
173 net::NetworkQualityEstimator* network_quality_estimator) { | |
174 return base::MakeUnique<NetworkQualityObserverImpl>( | |
175 network_quality_estimator); | |
176 } | |
177 | |
178 } // namespace content | |
OLD | NEW |