1 // Copyright 2014 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 <cmath> // For std::modf.
6 #include <map>
7 #include <string>
8
9 #include "base/command_line.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/test/metrics/histogram_tester.h"
13 #include "build/build_config.h"
14 #include "content/browser/net/network_quality_observer_impl.h"
15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/common/content_switches.h"
17 #include "content/public/test/browser_test.h"
18 #include "content/public/test/browser_test_utils.h"
19 #include "content/public/test/content_browser_test.h"
20 #include "content/public/test/content_browser_test_utils.h"
21 #include "content/shell/browser/shell.h"
22 #include "net/base/network_change_notifier.h"
23 #include "net/base/network_change_notifier_factory.h"
24 #include "net/dns/mock_host_resolver.h"
25 #include "net/log/test_net_log.h"
26 #include "net/nqe/effective_connection_type.h"
27 #include "services/network/test/test_network_quality_tracker.h"
28
29 namespace {
30
31 // Returns the total count of samples in |histogram|.
GetTotalSampleCount(base::HistogramTester * tester,const std::string & histogram)32 int GetTotalSampleCount(base::HistogramTester* tester,
33 const std::string& histogram) {
34 int count = 0;
35 std::vector<base::Bucket> buckets = tester->GetAllSamples(histogram);
36 for (const auto& bucket : buckets)
37 count += bucket.count;
38 return count;
39 }
40
VerifyRtt(base::TimeDelta expected_rtt,int32_t got_rtt_milliseconds)41 void VerifyRtt(base::TimeDelta expected_rtt, int32_t got_rtt_milliseconds) {
42 EXPECT_EQ(0, got_rtt_milliseconds % 50)
43 << " got_rtt_milliseconds=" << got_rtt_milliseconds;
44
45 if (expected_rtt > base::TimeDelta::FromMilliseconds(3000))
46 expected_rtt = base::TimeDelta::FromMilliseconds(3000);
47
48 // The difference between the actual and the estimate value should be within
49 // 10%. Add 50 (bucket size used in Blink) to account for the cases when the
50 // sample may spill over to the next bucket due to the added noise of 10%.
51 // For example, if sample is 300 msec, after adding noise, it may become 330,
52 // and after rounding off, it would spill over to the next bucket of 350 msec.
53 EXPECT_GE((expected_rtt.InMilliseconds() * 0.1) + 50,
54 std::abs(expected_rtt.InMilliseconds() - got_rtt_milliseconds))
55 << " expected_rtt=" << expected_rtt
56 << " got_rtt_milliseconds=" << got_rtt_milliseconds;
57 }
58
VerifyDownlinkKbps(double expected_kbps,double got_kbps)59 void VerifyDownlinkKbps(double expected_kbps, double got_kbps) {
60 // First verify that |got_kbps| is a multiple of 50.
61 int quotient = static_cast<int>(got_kbps / 50);
62 // |mod| is the remainder left after dividing |got_kbps| by 50 while
63 // restricting the quotient to integer. For example, if |got_kbps| is
64 // 1050, then mod will be 0. If |got_kbps| is 1030, mod will be 30.
65 double mod = got_kbps - 50 * quotient;
66 EXPECT_LE(0.0, mod);
67 EXPECT_GT(50.0, mod);
68 // It is possible that |mod| is not exactly 0 because of floating point
69 // computations. e.g., |got_kbps| may be 99.999999, in which case |mod|
70 // will be 49.999999.
71 EXPECT_TRUE(mod < (1e-5) || (50 - mod) < 1e-5) << " got_kbps=" << got_kbps;
72
73 if (expected_kbps > 10000)
74 expected_kbps = 10000;
75
76 // The difference between the actual and the estimate value should be within
77 // 10%. Add 50 (bucket size used in Blink) to account for the cases when the
78 // sample may spill over to the next bucket due to the added noise of 10%.
79 // For example, if sample is 300 kbps, after adding noise, it may become 330,
80 // and after rounding off, it would spill over to the next bucket of 350 kbps.
81 EXPECT_GE((expected_kbps * 0.1) + 50, std::abs(expected_kbps - got_kbps))
82 << " expected_kbps=" << expected_kbps << " got_kbps=" << got_kbps;
83 }
84
85 class MockNetworkChangeNotifierWifi : public net::NetworkChangeNotifier {
86 public:
GetCurrentMaxBandwidthAndConnectionType(double * max_bandwidth_mbps,ConnectionType * connection_type) const87 void GetCurrentMaxBandwidthAndConnectionType(
88 double* max_bandwidth_mbps,
89 ConnectionType* connection_type) const override {
90 *connection_type = NetworkChangeNotifier::CONNECTION_WIFI;
91 *max_bandwidth_mbps =
92 net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
93 net::NetworkChangeNotifier::SUBTYPE_WIFI_N);
94 }
GetCurrentConnectionType() const95 ConnectionType GetCurrentConnectionType() const override {
96 return NetworkChangeNotifier::CONNECTION_WIFI;
97 }
98 };
99
100 } // namespace
101
102 namespace content {
103
104 class NetInfoBrowserTest : public content::ContentBrowserTest {
105 public:
NetInfoBrowserTest()106 NetInfoBrowserTest()
107 : test_network_quality_tracker_(
108 std::make_unique<network::TestNetworkQualityTracker>()) {}
109
GetNetworkQualityTracker() const110 network::NetworkQualityTracker* GetNetworkQualityTracker() const {
111 return test_network_quality_tracker_.get();
112 }
113
114 protected:
SetUpCommandLine(base::CommandLine * command_line)115 void SetUpCommandLine(base::CommandLine* command_line) override {
116 // TODO(jkarlin): Once NetInfo is enabled on all platforms remove this
117 // switch.
118 command_line->AppendSwitch(switches::kEnableNetworkInformationDownlinkMax);
119
120 // TODO(jkarlin): Remove this once downlinkMax is no longer
121 // experimental.
122 command_line->AppendSwitch(
123 switches::kEnableExperimentalWebPlatformFeatures);
124 }
125
SetUp()126 void SetUp() override {
127 net::NetworkChangeNotifier::SetTestNotificationsOnly(true);
128
129 content::ContentBrowserTest::SetUp();
130 }
131
SetUpOnMainThread()132 void SetUpOnMainThread() override {
133 host_resolver()->AddRule("*", "127.0.0.1");
134 base::RunLoop().RunUntilIdle();
135 }
136
SetConnectionType(net::NetworkChangeNotifier::ConnectionType type,net::NetworkChangeNotifier::ConnectionSubtype subtype)137 static void SetConnectionType(
138 net::NetworkChangeNotifier::ConnectionType type,
139 net::NetworkChangeNotifier::ConnectionSubtype subtype) {
140 net::NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeForTests(
141 net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
142 subtype),
143 type);
144 base::RunLoop().RunUntilIdle();
145 }
146
RunScriptExtractString(const std::string & script)147 std::string RunScriptExtractString(const std::string& script) {
148 std::string data;
149 EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &data));
150 return data;
151 }
152
RunScriptExtractBool(const std::string & script)153 bool RunScriptExtractBool(const std::string& script) {
154 bool data;
155 EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(), script, &data));
156 return data;
157 }
158
RunScriptExtractDouble(const std::string & script)159 double RunScriptExtractDouble(const std::string& script) {
160 double data = 0.0;
161 EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), script, &data));
162 return data;
163 }
164
RunScriptExtractInt(const std::string & script)165 int RunScriptExtractInt(const std::string& script) {
166 int data = 0;
167 EXPECT_TRUE(ExecuteScriptAndExtractInt(shell(), script, &data));
168 return data;
169 }
170
171 private:
172 std::unique_ptr<network::TestNetworkQualityTracker>
173 test_network_quality_tracker_;
174 };
175
176 // Make sure the type is correct when the page is first opened.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,VerifyNetworkStateInitialized)177 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, VerifyNetworkStateInitialized) {
178 // Mock out the NCN.
179 net::NetworkChangeNotifier::DisableForTest disable_for_test;
180 MockNetworkChangeNotifierWifi mock_notifier;
181
182 EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html")));
183 EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
184 EXPECT_EQ("wifi", RunScriptExtractString("getType()"));
185 EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
186 net::NetworkChangeNotifier::SUBTYPE_WIFI_N),
187 RunScriptExtractDouble("getDownlinkMax()"));
188 }
189
190 // Make sure that type changes in the browser make their way to
191 // navigator.connection.type.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkChangePlumbsToNavigator)192 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkChangePlumbsToNavigator) {
193 EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html")));
194 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI,
195 net::NetworkChangeNotifier::SUBTYPE_WIFI_N);
196 EXPECT_EQ("wifi", RunScriptExtractString("getType()"));
197 EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
198 net::NetworkChangeNotifier::SUBTYPE_WIFI_N),
199 RunScriptExtractDouble("getDownlinkMax()"));
200
201 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET,
202 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET);
203 EXPECT_EQ("ethernet", RunScriptExtractString("getType()"));
204 EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype(
205 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET),
206 RunScriptExtractDouble("getDownlinkMax()"));
207 }
208
209 // Make sure that type changes in the browser make their way to
210 // navigator.isOnline.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,IsOnline)211 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, IsOnline) {
212 EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html")));
213 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET,
214 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET);
215 EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
216 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE,
217 net::NetworkChangeNotifier::SUBTYPE_NONE);
218 EXPECT_FALSE(RunScriptExtractBool("getOnLine()"));
219 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI,
220 net::NetworkChangeNotifier::SUBTYPE_WIFI_N);
221 EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
222 }
223
224 // Creating a new render view shouldn't reinitialize Blink's
225 // NetworkStateNotifier. See https://crbug.com/535081.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,TwoRenderViewsInOneProcess)226 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, TwoRenderViewsInOneProcess) {
227 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET,
228 net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET);
229 EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html")));
230 EXPECT_TRUE(RunScriptExtractBool("getOnLine()"));
231
232 SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE,
233 net::NetworkChangeNotifier::SUBTYPE_NONE);
234 EXPECT_FALSE(RunScriptExtractBool("getOnLine()"));
235
236 // Open the same page in a new window on the same process.
237 EXPECT_TRUE(ExecuteScript(shell(), "window.open(\"net_info.html\")"));
238
239 // The network state should not have reinitialized to what it was when opening
240 // the first window (online).
241 EXPECT_FALSE(RunScriptExtractBool("getOnLine()"));
242 }
243
244 // Verify that when the network quality notifications are not sent, the
245 // Javascript API returns a valid estimate that is multiple of 50 msec and 50
246 // kbps.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityEstimatorNotInitialized)247 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
248 NetworkQualityEstimatorNotInitialized) {
249 base::HistogramTester histogram_tester;
250 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
251
252 EXPECT_TRUE(embedded_test_server()->Start());
253 EXPECT_TRUE(
254 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
255
256 // When NQE is not initialized, the javascript calls should return default
257 // values.
258 EXPECT_EQ(0, RunScriptExtractInt("getRtt()"));
259 VerifyDownlinkKbps(10000, RunScriptExtractDouble("getDownlink()") * 1000);
260 }
261
262 // Make sure the changes in the effective connection type are notified to the
263 // render thread.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,EffectiveConnectionTypeChangeNotified)264 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,
265 EffectiveConnectionTypeChangeNotified) {
266 base::HistogramTester histogram_tester;
267 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
268
269 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000));
270 int32_t downstream_throughput_kbps = 300;
271 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
272 http_rtt, downstream_throughput_kbps);
273
274 EXPECT_TRUE(embedded_test_server()->Start());
275 EXPECT_TRUE(
276 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
277
278 FetchHistogramsFromChildProcesses();
279
280 int samples =
281 GetTotalSampleCount(&histogram_tester, "NQE.RenderThreadNotified");
282 EXPECT_LT(0, samples);
283
284 // Change effective connection type so that the renderer process is notified.
285 // Changing the effective connection type from 2G to 3G is guaranteed to
286 // generate the notification to the renderers, irrespective of the current
287 // effective connection type.
288 GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
289 net::EFFECTIVE_CONNECTION_TYPE_2G);
290 EXPECT_EQ("2g", RunScriptExtractString("getEffectiveType()"));
291
292 GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting(
293 net::EFFECTIVE_CONNECTION_TYPE_3G);
294 EXPECT_EQ("3g", RunScriptExtractString("getEffectiveType()"));
295
296 FetchHistogramsFromChildProcesses();
297 EXPECT_GT(GetTotalSampleCount(&histogram_tester, "NQE.RenderThreadNotified"),
298 samples);
299 }
300
301 // Make sure the changes in the network quality are notified to the render
302 // thread, and the changed network quality is accessible via Javascript API.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityChangeNotified)303 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) {
304 base::HistogramTester histogram_tester;
305 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
306
307 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000));
308 int32_t downstream_throughput_kbps = 300;
309
310 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
311 http_rtt, downstream_throughput_kbps);
312
313 EXPECT_TRUE(embedded_test_server()->Start());
314 EXPECT_TRUE(
315 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
316
317 FetchHistogramsFromChildProcesses();
318 EXPECT_FALSE(
319 histogram_tester.GetAllSamples("NQE.RenderThreadNotified").empty());
320
321 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
322 VerifyDownlinkKbps(downstream_throughput_kbps,
323 RunScriptExtractDouble("getDownlink()") * 1000);
324
325 // Verify that the network quality change is accessible via Javascript API.
326 http_rtt = base::TimeDelta::FromSeconds(10);
327 downstream_throughput_kbps = 3000;
328 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
329 http_rtt, downstream_throughput_kbps);
330 base::RunLoop().RunUntilIdle();
331 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
332 VerifyDownlinkKbps(downstream_throughput_kbps,
333 RunScriptExtractDouble("getDownlink()") * 1000);
334 }
335
336 // Make sure the changes in the network quality are rounded to the nearest
337 // 50 milliseconds or 50 kbps.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityChangeRounded)338 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) {
339 base::HistogramTester histogram_tester;
340 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
341
342 // Verify that the network quality is rounded properly.
343 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(103));
344 int32_t downstream_throughput_kbps = 8303;
345 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
346 http_rtt, downstream_throughput_kbps);
347
348 EXPECT_TRUE(embedded_test_server()->Start());
349 EXPECT_TRUE(
350 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
351 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
352 VerifyDownlinkKbps(downstream_throughput_kbps,
353 RunScriptExtractDouble("getDownlink()") * 1000);
354
355 http_rtt = base::TimeDelta::FromMilliseconds(1103);
356 downstream_throughput_kbps = 1307;
357 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
358 http_rtt, downstream_throughput_kbps);
359 base::RunLoop().RunUntilIdle();
360 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
361 VerifyDownlinkKbps(downstream_throughput_kbps,
362 RunScriptExtractDouble("getDownlink()") * 1000);
363
364 http_rtt = base::TimeDelta::FromMilliseconds(2112);
365 downstream_throughput_kbps = 2112;
366 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
367 http_rtt, downstream_throughput_kbps);
368 base::RunLoop().RunUntilIdle();
369 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
370 VerifyDownlinkKbps(downstream_throughput_kbps,
371 RunScriptExtractDouble("getDownlink()") * 1000);
372 }
373
374 // Make sure the network quality are rounded down when it exceeds the upper
375 // limit.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityChangeUpperLimit)376 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeUpperLimit) {
377 base::HistogramTester histogram_tester;
378 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
379
380 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(12003));
381 int32_t downstream_throughput_kbps = 30300;
382
383 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
384 http_rtt, downstream_throughput_kbps);
385
386 EXPECT_TRUE(embedded_test_server()->Start());
387 EXPECT_TRUE(
388 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
389 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
390 VerifyDownlinkKbps(downstream_throughput_kbps,
391 RunScriptExtractDouble("getDownlink()") * 1000);
392 }
393
394 // Make sure the noise added to the network quality varies with the hostname.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityRandomized)395 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) {
396 base::HistogramTester histogram_tester;
397 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
398
399 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(2000));
400 int32_t downstream_throughput_kbps = 3000;
401
402 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
403 http_rtt, downstream_throughput_kbps);
404
405 EXPECT_TRUE(embedded_test_server()->Start());
406
407 EXPECT_TRUE(
408 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
409 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
410 VerifyDownlinkKbps(downstream_throughput_kbps,
411 RunScriptExtractDouble("getDownlink()") * 1000);
412
413 const int32_t rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
414 const int32_t downlink_noise_kbps =
415 RunScriptExtractDouble("getDownlink()") * 1000 - 3000;
416
417 // When the hostname is not changed, the noise should not change.
418 EXPECT_TRUE(
419 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
420 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
421 VerifyDownlinkKbps(downstream_throughput_kbps,
422 RunScriptExtractDouble("getDownlink()") * 1000);
423 EXPECT_EQ(rtt_noise_milliseconds, RunScriptExtractInt("getRtt()") - 2000);
424 EXPECT_EQ(downlink_noise_kbps,
425 RunScriptExtractDouble("getDownlink()") * 1000 - 3000);
426
427 // Verify that changing the hostname changes the noise. It is possible that
428 // the hash of a different host also maps to the same bucket among 20 buckets.
429 // Try 10 different hosts. This reduces the probability of failure of this
430 // test to (1/20)^10 = 9,7 * 10^-14.
431 for (size_t i = 0; i < 10; ++i) {
432 // The noise added is a function of the hostname. Varying the hostname
433 // should vary the noise.
434 std::string fake_hostname = "example" + base::NumberToString(i) + ".com";
435 EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL(
436 fake_hostname, "/net_info.html")));
437 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
438 VerifyDownlinkKbps(downstream_throughput_kbps,
439 RunScriptExtractDouble("getDownlink()") * 1000);
440
441 int32_t new_rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000;
442 int32_t new_downlink_noise_kbps =
443 RunScriptExtractDouble("getDownlink()") * 1000 - 3000;
444
445 if (rtt_noise_milliseconds != new_rtt_noise_milliseconds &&
446 downlink_noise_kbps != new_downlink_noise_kbps) {
447 return;
448 }
449 }
450 NOTREACHED() << "Noise not added to the network quality estimates";
451 }
452
453 // Make sure the minor changes (<10%) in the network quality are not notified.
IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest,NetworkQualityChangeNotNotified)454 IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) {
455 base::HistogramTester histogram_tester;
456 NetworkQualityObserverImpl impl(GetNetworkQualityTracker());
457
458 // Verify that the network quality is rounded properly.
459 base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1123));
460 int32_t downstream_throughput_kbps = 1303;
461 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
462 http_rtt, downstream_throughput_kbps);
463
464 EXPECT_TRUE(embedded_test_server()->Start());
465 EXPECT_TRUE(
466 NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html")));
467 VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()"));
468 VerifyDownlinkKbps(downstream_throughput_kbps,
469 RunScriptExtractDouble("getDownlink()") * 1000);
470
471 // All the 3 metrics change by less than 10%. So, the observers are not
472 // notified.
473 http_rtt = base::TimeDelta::FromMilliseconds(1223);
474 downstream_throughput_kbps = 1403;
475 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
476 http_rtt, downstream_throughput_kbps);
477 base::RunLoop().RunUntilIdle();
478 VerifyRtt(base::TimeDelta::FromMilliseconds(1100),
479 RunScriptExtractInt("getRtt()"));
480 VerifyDownlinkKbps(1300, RunScriptExtractDouble("getDownlink()") * 1000);
481
482 // HTTP RTT has changed by more than 10% from the last notified value of
483 // |network_quality_1|. The observers should be notified.
484 http_rtt = base::TimeDelta::FromMilliseconds(2223);
485 downstream_throughput_kbps = 1403;
486 GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting(
487 http_rtt, downstream_throughput_kbps);
488 base::RunLoop().RunUntilIdle();
489 VerifyRtt(base::TimeDelta::FromMilliseconds(2200),
490 RunScriptExtractInt("getRtt()"));
491 VerifyDownlinkKbps(1400, RunScriptExtractDouble("getDownlink()") * 1000);
492 }
493
494 } // namespace content
495