|  | // Copyright 2014 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 <cmath>  // For std::modf. | 
|  | #include <map> | 
|  | #include <string> | 
|  |  | 
|  | #include "base/command_line.h" | 
|  | #include "base/run_loop.h" | 
|  | #include "base/strings/string_number_conversions.h" | 
|  | #include "base/test/metrics/histogram_tester.h" | 
|  | #include "build/build_config.h" | 
|  | #include "content/browser/net/network_quality_observer_impl.h" | 
|  | #include "content/public/browser/render_process_host.h" | 
|  | #include "content/public/common/content_switches.h" | 
|  | #include "content/public/test/browser_test.h" | 
|  | #include "content/public/test/browser_test_utils.h" | 
|  | #include "content/public/test/content_browser_test.h" | 
|  | #include "content/public/test/content_browser_test_utils.h" | 
|  | #include "content/shell/browser/shell.h" | 
|  | #include "net/base/network_change_notifier.h" | 
|  | #include "net/base/network_change_notifier_factory.h" | 
|  | #include "net/dns/mock_host_resolver.h" | 
|  | #include "net/log/test_net_log.h" | 
|  | #include "net/nqe/effective_connection_type.h" | 
|  | #include "services/network/test/test_network_quality_tracker.h" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Returns the total count of samples in |histogram|. | 
|  | int GetTotalSampleCount(base::HistogramTester* tester, | 
|  | const std::string& histogram) { | 
|  | int count = 0; | 
|  | std::vector<base::Bucket> buckets = tester->GetAllSamples(histogram); | 
|  | for (const auto& bucket : buckets) | 
|  | count += bucket.count; | 
|  | return count; | 
|  | } | 
|  |  | 
|  | void VerifyRtt(base::TimeDelta expected_rtt, int32_t got_rtt_milliseconds) { | 
|  | EXPECT_EQ(0, got_rtt_milliseconds % 50) | 
|  | << " got_rtt_milliseconds=" << got_rtt_milliseconds; | 
|  |  | 
|  | if (expected_rtt > base::TimeDelta::FromMilliseconds(3000)) | 
|  | expected_rtt = base::TimeDelta::FromMilliseconds(3000); | 
|  |  | 
|  | // The difference between the actual and the estimate value should be within | 
|  | // 10%. Add 50 (bucket size used in Blink) to account for the cases when the | 
|  | // sample may spill over to the next bucket due to the added noise of 10%. | 
|  | // For example, if sample is 300 msec, after adding noise, it may become 330, | 
|  | // and after rounding off, it would spill over to the next bucket of 350 msec. | 
|  | EXPECT_GE((expected_rtt.InMilliseconds() * 0.1) + 50, | 
|  | std::abs(expected_rtt.InMilliseconds() - got_rtt_milliseconds)) | 
|  | << " expected_rtt=" << expected_rtt | 
|  | << " got_rtt_milliseconds=" << got_rtt_milliseconds; | 
|  | } | 
|  |  | 
|  | void VerifyDownlinkKbps(double expected_kbps, double got_kbps) { | 
|  | // First verify that |got_kbps| is a multiple of 50. | 
|  | int quotient = static_cast<int>(got_kbps / 50); | 
|  | // |mod| is the remainder left after dividing |got_kbps| by 50 while | 
|  | // restricting the quotient to integer.  For example, if |got_kbps| is | 
|  | // 1050, then mod will be 0. If |got_kbps| is 1030, mod will be 30. | 
|  | double mod = got_kbps - 50 * quotient; | 
|  | EXPECT_LE(0.0, mod); | 
|  | EXPECT_GT(50.0, mod); | 
|  | // It is possible that |mod| is not exactly 0 because of floating point | 
|  | // computations. e.g., |got_kbps| may be 99.999999, in which case |mod| | 
|  | // will be 49.999999. | 
|  | EXPECT_TRUE(mod < (1e-5) || (50 - mod) < 1e-5) << " got_kbps=" << got_kbps; | 
|  |  | 
|  | if (expected_kbps > 10000) | 
|  | expected_kbps = 10000; | 
|  |  | 
|  | // The difference between the actual and the estimate value should be within | 
|  | // 10%. Add 50 (bucket size used in Blink) to account for the cases when the | 
|  | // sample may spill over to the next bucket due to the added noise of 10%. | 
|  | // For example, if sample is 300 kbps, after adding noise, it may become 330, | 
|  | // and after rounding off, it would spill over to the next bucket of 350 kbps. | 
|  | EXPECT_GE((expected_kbps * 0.1) + 50, std::abs(expected_kbps - got_kbps)) | 
|  | << " expected_kbps=" << expected_kbps << " got_kbps=" << got_kbps; | 
|  | } | 
|  |  | 
|  | class MockNetworkChangeNotifierWifi : public net::NetworkChangeNotifier { | 
|  | public: | 
|  | void GetCurrentMaxBandwidthAndConnectionType( | 
|  | double* max_bandwidth_mbps, | 
|  | ConnectionType* connection_type) const override { | 
|  | *connection_type = NetworkChangeNotifier::CONNECTION_WIFI; | 
|  | *max_bandwidth_mbps = | 
|  | net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( | 
|  | net::NetworkChangeNotifier::SUBTYPE_WIFI_N); | 
|  | } | 
|  | ConnectionType GetCurrentConnectionType() const override { | 
|  | return NetworkChangeNotifier::CONNECTION_WIFI; | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | class NetInfoBrowserTest : public content::ContentBrowserTest { | 
|  | public: | 
|  | NetInfoBrowserTest() | 
|  | : test_network_quality_tracker_( | 
|  | std::make_unique<network::TestNetworkQualityTracker>()) {} | 
|  |  | 
|  | network::NetworkQualityTracker* GetNetworkQualityTracker() const { | 
|  | return test_network_quality_tracker_.get(); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | void SetUpCommandLine(base::CommandLine* command_line) override { | 
|  | // TODO(jkarlin): Once NetInfo is enabled on all platforms remove this | 
|  | // switch. | 
|  | command_line->AppendSwitch(switches::kEnableNetworkInformationDownlinkMax); | 
|  |  | 
|  | // TODO(jkarlin): Remove this once downlinkMax is no longer | 
|  | // experimental. | 
|  | command_line->AppendSwitch( | 
|  | switches::kEnableExperimentalWebPlatformFeatures); | 
|  | } | 
|  |  | 
|  | void SetUp() override { | 
|  | net::NetworkChangeNotifier::SetTestNotificationsOnly(true); | 
|  |  | 
|  | content::ContentBrowserTest::SetUp(); | 
|  | } | 
|  |  | 
|  | void SetUpOnMainThread() override { | 
|  | host_resolver()->AddRule("*", "127.0.0.1"); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | static void SetConnectionType( | 
|  | net::NetworkChangeNotifier::ConnectionType type, | 
|  | net::NetworkChangeNotifier::ConnectionSubtype subtype) { | 
|  | net::NetworkChangeNotifier::NotifyObserversOfMaxBandwidthChangeForTests( | 
|  | net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( | 
|  | subtype), | 
|  | type); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | } | 
|  |  | 
|  | std::string RunScriptExtractString(const std::string& script) { | 
|  | std::string data; | 
|  | EXPECT_TRUE(ExecuteScriptAndExtractString(shell(), script, &data)); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | bool RunScriptExtractBool(const std::string& script) { | 
|  | bool data; | 
|  | EXPECT_TRUE(ExecuteScriptAndExtractBool(shell(), script, &data)); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | double RunScriptExtractDouble(const std::string& script) { | 
|  | double data = 0.0; | 
|  | EXPECT_TRUE(ExecuteScriptAndExtractDouble(shell(), script, &data)); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | int RunScriptExtractInt(const std::string& script) { | 
|  | int data = 0; | 
|  | EXPECT_TRUE(ExecuteScriptAndExtractInt(shell(), script, &data)); | 
|  | return data; | 
|  | } | 
|  |  | 
|  | private: | 
|  | std::unique_ptr<network::TestNetworkQualityTracker> | 
|  | test_network_quality_tracker_; | 
|  | }; | 
|  |  | 
|  | // Make sure the type is correct when the page is first opened. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, VerifyNetworkStateInitialized) { | 
|  | // Mock out the NCN. | 
|  | net::NetworkChangeNotifier::DisableForTest disable_for_test; | 
|  | MockNetworkChangeNotifierWifi mock_notifier; | 
|  |  | 
|  | EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"))); | 
|  | EXPECT_TRUE(RunScriptExtractBool("getOnLine()")); | 
|  | EXPECT_EQ("wifi", RunScriptExtractString("getType()")); | 
|  | EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( | 
|  | net::NetworkChangeNotifier::SUBTYPE_WIFI_N), | 
|  | RunScriptExtractDouble("getDownlinkMax()")); | 
|  | } | 
|  |  | 
|  | // Make sure that type changes in the browser make their way to | 
|  | // navigator.connection.type. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkChangePlumbsToNavigator) { | 
|  | EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"))); | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI, | 
|  | net::NetworkChangeNotifier::SUBTYPE_WIFI_N); | 
|  | EXPECT_EQ("wifi", RunScriptExtractString("getType()")); | 
|  | EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( | 
|  | net::NetworkChangeNotifier::SUBTYPE_WIFI_N), | 
|  | RunScriptExtractDouble("getDownlinkMax()")); | 
|  |  | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET, | 
|  | net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET); | 
|  | EXPECT_EQ("ethernet", RunScriptExtractString("getType()")); | 
|  | EXPECT_EQ(net::NetworkChangeNotifier::GetMaxBandwidthMbpsForConnectionSubtype( | 
|  | net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET), | 
|  | RunScriptExtractDouble("getDownlinkMax()")); | 
|  | } | 
|  |  | 
|  | // Make sure that type changes in the browser make their way to | 
|  | // navigator.isOnline. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, IsOnline) { | 
|  | EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"))); | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET, | 
|  | net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET); | 
|  | EXPECT_TRUE(RunScriptExtractBool("getOnLine()")); | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE, | 
|  | net::NetworkChangeNotifier::SUBTYPE_NONE); | 
|  | EXPECT_FALSE(RunScriptExtractBool("getOnLine()")); | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI, | 
|  | net::NetworkChangeNotifier::SUBTYPE_WIFI_N); | 
|  | EXPECT_TRUE(RunScriptExtractBool("getOnLine()")); | 
|  | } | 
|  |  | 
|  | // Creating a new render view shouldn't reinitialize Blink's | 
|  | // NetworkStateNotifier. See https://crbug.com/535081. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, TwoRenderViewsInOneProcess) { | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_ETHERNET, | 
|  | net::NetworkChangeNotifier::SUBTYPE_GIGABIT_ETHERNET); | 
|  | EXPECT_TRUE(NavigateToURL(shell(), content::GetTestUrl("", "net_info.html"))); | 
|  | EXPECT_TRUE(RunScriptExtractBool("getOnLine()")); | 
|  |  | 
|  | SetConnectionType(net::NetworkChangeNotifier::CONNECTION_NONE, | 
|  | net::NetworkChangeNotifier::SUBTYPE_NONE); | 
|  | EXPECT_FALSE(RunScriptExtractBool("getOnLine()")); | 
|  |  | 
|  | // Open the same page in a new window on the same process. | 
|  | EXPECT_TRUE(ExecuteScript(shell(), "window.open(\"net_info.html\")")); | 
|  |  | 
|  | // The network state should not have reinitialized to what it was when opening | 
|  | // the first window (online). | 
|  | EXPECT_FALSE(RunScriptExtractBool("getOnLine()")); | 
|  | } | 
|  |  | 
|  | // Verify that when the network quality notifications are not sent, the | 
|  | // Javascript API returns a valid estimate that is multiple of 50 msec and 50 | 
|  | // kbps. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, | 
|  | NetworkQualityEstimatorNotInitialized) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  |  | 
|  | // When NQE is not initialized, the javascript calls should return default | 
|  | // values. | 
|  | EXPECT_EQ(0, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(10000, RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | } | 
|  |  | 
|  | // Make sure the changes in the effective connection type are notified to the | 
|  | // render thread. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, | 
|  | EffectiveConnectionTypeChangeNotified) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000)); | 
|  | int32_t downstream_throughput_kbps = 300; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  |  | 
|  | FetchHistogramsFromChildProcesses(); | 
|  |  | 
|  | int samples = | 
|  | GetTotalSampleCount(&histogram_tester, "NQE.RenderThreadNotified"); | 
|  | EXPECT_LT(0, samples); | 
|  |  | 
|  | // Change effective connection type so that the renderer process is notified. | 
|  | // Changing the effective connection type from 2G to 3G is guaranteed to | 
|  | // generate the notification to the renderers, irrespective of the current | 
|  | // effective connection type. | 
|  | GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting( | 
|  | net::EFFECTIVE_CONNECTION_TYPE_2G); | 
|  | EXPECT_EQ("2g", RunScriptExtractString("getEffectiveType()")); | 
|  |  | 
|  | GetNetworkQualityTracker()->ReportEffectiveConnectionTypeForTesting( | 
|  | net::EFFECTIVE_CONNECTION_TYPE_3G); | 
|  | EXPECT_EQ("3g", RunScriptExtractString("getEffectiveType()")); | 
|  |  | 
|  | FetchHistogramsFromChildProcesses(); | 
|  | EXPECT_GT(GetTotalSampleCount(&histogram_tester, "NQE.RenderThreadNotified"), | 
|  | samples); | 
|  | } | 
|  |  | 
|  | // Make sure the changes in the network quality are notified to the render | 
|  | // thread, and the changed network quality is accessible via Javascript API. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotified) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1000)); | 
|  | int32_t downstream_throughput_kbps = 300; | 
|  |  | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  |  | 
|  | FetchHistogramsFromChildProcesses(); | 
|  | EXPECT_FALSE( | 
|  | histogram_tester.GetAllSamples("NQE.RenderThreadNotified").empty()); | 
|  |  | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | // Verify that the network quality change is accessible via Javascript API. | 
|  | http_rtt = base::TimeDelta::FromSeconds(10); | 
|  | downstream_throughput_kbps = 3000; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | } | 
|  |  | 
|  | // Make sure the changes in the network quality are rounded to the nearest | 
|  | // 50 milliseconds or 50 kbps. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeRounded) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | // Verify that the network quality is rounded properly. | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(103)); | 
|  | int32_t downstream_throughput_kbps = 8303; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | http_rtt = base::TimeDelta::FromMilliseconds(1103); | 
|  | downstream_throughput_kbps = 1307; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | http_rtt = base::TimeDelta::FromMilliseconds(2112); | 
|  | downstream_throughput_kbps = 2112; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | } | 
|  |  | 
|  | // Make sure the network quality are rounded down when it exceeds the upper | 
|  | // limit. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeUpperLimit) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(12003)); | 
|  | int32_t downstream_throughput_kbps = 30300; | 
|  |  | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | } | 
|  |  | 
|  | // Make sure the noise added to the network quality varies with the hostname. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityRandomized) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(2000)); | 
|  | int32_t downstream_throughput_kbps = 3000; | 
|  |  | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  |  | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | const int32_t rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000; | 
|  | const int32_t downlink_noise_kbps = | 
|  | RunScriptExtractDouble("getDownlink()") * 1000 - 3000; | 
|  |  | 
|  | // When the hostname is not changed, the noise should not change. | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | EXPECT_EQ(rtt_noise_milliseconds, RunScriptExtractInt("getRtt()") - 2000); | 
|  | EXPECT_EQ(downlink_noise_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000 - 3000); | 
|  |  | 
|  | // Verify that changing the hostname changes the noise. It is possible that | 
|  | // the hash of a different host also maps to the same bucket among 20 buckets. | 
|  | // Try 10 different hosts. This reduces the probability of failure of this | 
|  | // test to (1/20)^10 = 9,7 * 10^-14. | 
|  | for (size_t i = 0; i < 10; ++i) { | 
|  | // The noise added is a function of the hostname. Varying the hostname | 
|  | // should vary the noise. | 
|  | std::string fake_hostname = "example" + base::NumberToString(i) + ".com"; | 
|  | EXPECT_TRUE(NavigateToURL(shell(), embedded_test_server()->GetURL( | 
|  | fake_hostname, "/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | int32_t new_rtt_noise_milliseconds = RunScriptExtractInt("getRtt()") - 2000; | 
|  | int32_t new_downlink_noise_kbps = | 
|  | RunScriptExtractDouble("getDownlink()") * 1000 - 3000; | 
|  |  | 
|  | if (rtt_noise_milliseconds != new_rtt_noise_milliseconds && | 
|  | downlink_noise_kbps != new_downlink_noise_kbps) { | 
|  | return; | 
|  | } | 
|  | } | 
|  | NOTREACHED() << "Noise not added to the network quality estimates"; | 
|  | } | 
|  |  | 
|  | // Make sure the minor changes (<10%) in the network quality are not notified. | 
|  | IN_PROC_BROWSER_TEST_F(NetInfoBrowserTest, NetworkQualityChangeNotNotified) { | 
|  | base::HistogramTester histogram_tester; | 
|  | NetworkQualityObserverImpl impl(GetNetworkQualityTracker()); | 
|  |  | 
|  | // Verify that the network quality is rounded properly. | 
|  | base::TimeDelta http_rtt(base::TimeDelta::FromMilliseconds(1123)); | 
|  | int32_t downstream_throughput_kbps = 1303; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  |  | 
|  | EXPECT_TRUE(embedded_test_server()->Start()); | 
|  | EXPECT_TRUE( | 
|  | NavigateToURL(shell(), embedded_test_server()->GetURL("/net_info.html"))); | 
|  | VerifyRtt(http_rtt, RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(downstream_throughput_kbps, | 
|  | RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | // All the 3 metrics change by less than 10%. So, the observers are not | 
|  | // notified. | 
|  | http_rtt = base::TimeDelta::FromMilliseconds(1223); | 
|  | downstream_throughput_kbps = 1403; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | VerifyRtt(base::TimeDelta::FromMilliseconds(1100), | 
|  | RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(1300, RunScriptExtractDouble("getDownlink()") * 1000); | 
|  |  | 
|  | // HTTP RTT has changed by more than 10% from the last notified value of | 
|  | // |network_quality_1|. The observers should be notified. | 
|  | http_rtt = base::TimeDelta::FromMilliseconds(2223); | 
|  | downstream_throughput_kbps = 1403; | 
|  | GetNetworkQualityTracker()->ReportRTTsAndThroughputForTesting( | 
|  | http_rtt, downstream_throughput_kbps); | 
|  | base::RunLoop().RunUntilIdle(); | 
|  | VerifyRtt(base::TimeDelta::FromMilliseconds(2200), | 
|  | RunScriptExtractInt("getRtt()")); | 
|  | VerifyDownlinkKbps(1400, RunScriptExtractDouble("getDownlink()") * 1000); | 
|  | } | 
|  |  | 
|  | }  // namespace content |