| // 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 "services/network/proxy_config_service_mojo.h" |
| |
| #include "base/macros.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "net/proxy_resolution/proxy_config.h" |
| #include "net/proxy_resolution/proxy_config_service.h" |
| #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" |
| #include "services/network/public/mojom/proxy_config.mojom.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace network { |
| |
| namespace { |
| |
| // Test class for observing proxy config changes. |
| class TestProxyConfigServiceObserver |
| : public net::ProxyConfigService::Observer { |
| public: |
| explicit TestProxyConfigServiceObserver(net::ProxyConfigService* service) |
| : service_(service) {} |
| ~TestProxyConfigServiceObserver() override {} |
| |
| void OnProxyConfigChanged( |
| const net::ProxyConfigWithAnnotation& config, |
| net::ProxyConfigService::ConfigAvailability availability) override { |
| // The ProxyConfigServiceMojo only sends on availability state. |
| EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, availability); |
| |
| observed_config_ = config; |
| |
| // The passed in config should match the one that GetLatestProxyConfig |
| // returns. |
| net::ProxyConfigWithAnnotation retrieved_config; |
| EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, |
| service_->GetLatestProxyConfig(&retrieved_config)); |
| EXPECT_TRUE(observed_config_.value().Equals(retrieved_config.value())); |
| ++config_changes_; |
| } |
| |
| // Returns number of observed config changes since it was last called. |
| int GetAndResetConfigChanges() { |
| int result = config_changes_; |
| config_changes_ = 0; |
| return result; |
| } |
| |
| // Returns last observed config. |
| const net::ProxyConfigWithAnnotation& observed_config() const { |
| return observed_config_; |
| } |
| |
| private: |
| net::ProxyConfigWithAnnotation observed_config_; |
| |
| net::ProxyConfigService* const service_; |
| int config_changes_ = 0; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestProxyConfigServiceObserver); |
| }; |
| |
| // Test fixture for notifying ProxyConfigServiceMojo of changes through the |
| // client interface, and watching the subsequent values it emits to registered |
| // net::ProxyConfigService::Observers. |
| class ProxyConfigServiceMojoTest : public testing::Test { |
| public: |
| ProxyConfigServiceMojoTest() |
| : scoped_task_environment_( |
| base::test::ScopedTaskEnvironment::MainThreadType::IO), |
| proxy_config_service_(mojo::MakeRequest(&config_client_), |
| base::Optional<net::ProxyConfigWithAnnotation>(), |
| nullptr), |
| observer_(&proxy_config_service_) { |
| proxy_config_service_.AddObserver(&observer_); |
| } |
| |
| ~ProxyConfigServiceMojoTest() override { |
| proxy_config_service_.RemoveObserver(&observer_); |
| } |
| |
| protected: |
| // After notifying a new configuration through |config_client_|, waits for the |
| // observers to have been notified. |
| void WaitForConfig() { scoped_task_environment_.RunUntilIdle(); } |
| |
| base::test::ScopedTaskEnvironment scoped_task_environment_; |
| mojom::ProxyConfigClientPtr config_client_; |
| ProxyConfigServiceMojo proxy_config_service_; |
| TestProxyConfigServiceObserver observer_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ProxyConfigServiceMojoTest); |
| }; |
| |
| // Most tests of this class are in network_context_unittests. |
| |
| // Makes sure that a ProxyConfigService::Observer is correctly notified of |
| // changes when the ProxyConfig changes, and is not informed of them in the case |
| // of "changes" that result in the same ProxyConfig as before. |
| TEST_F(ProxyConfigServiceMojoTest, ObserveProxyChanges) { |
| net::ProxyConfigWithAnnotation proxy_config; |
| // The service should start without a config. |
| EXPECT_EQ(net::ProxyConfigService::CONFIG_PENDING, |
| proxy_config_service_.GetLatestProxyConfig(&proxy_config)); |
| |
| net::ProxyConfig proxy_configs[3]; |
| proxy_configs[0].proxy_rules().ParseFromString("http=foopy:80"); |
| proxy_configs[1].proxy_rules().ParseFromString("http=foopy:80;ftp=foopy2"); |
| proxy_configs[2] = net::ProxyConfig::CreateDirect(); |
| |
| for (const auto& proxy_config : proxy_configs) { |
| // Set the proxy configuration to something that does not match the old one. |
| config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation( |
| proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)); |
| WaitForConfig(); |
| EXPECT_EQ(1, observer_.GetAndResetConfigChanges()); |
| EXPECT_TRUE(proxy_config.Equals(observer_.observed_config().value())); |
| net::ProxyConfigWithAnnotation retrieved_config; |
| EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, |
| proxy_config_service_.GetLatestProxyConfig(&retrieved_config)); |
| EXPECT_TRUE(proxy_config.Equals(retrieved_config.value())); |
| |
| // Set the proxy configuration to the same value again. There should be not |
| // be another proxy config changed notification. |
| config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation( |
| proxy_config, TRAFFIC_ANNOTATION_FOR_TESTS)); |
| WaitForConfig(); |
| EXPECT_EQ(0, observer_.GetAndResetConfigChanges()); |
| EXPECT_TRUE(proxy_config.Equals(observer_.observed_config().value())); |
| EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID, |
| proxy_config_service_.GetLatestProxyConfig(&retrieved_config)); |
| EXPECT_TRUE(proxy_config.Equals(retrieved_config.value())); |
| } |
| } |
| |
| // Creates a URL that has length |url::kMaxURLChars + 1|. |
| GURL CreateLargeURL() { |
| std::string spec; |
| spec.reserve(url::kMaxURLChars + 1); |
| spec.assign("http://test.invalid/"); |
| spec.append(url::kMaxURLChars + 1 - spec.size(), 'x'); |
| return GURL(spec); |
| } |
| |
| // Tests what happens when ProxyConfigServiceMojo is updated to using a |
| // ProxyConfig with a large URL. GURL does not impose size limits, however some |
| // internals like url.mojom.Url do. |
| TEST_F(ProxyConfigServiceMojoTest, LargePacUrlNotTruncated) { |
| // Create a config using a large, valid, PAC URL. |
| net::ProxyConfig orig_config; |
| GURL large_url = CreateLargeURL(); |
| EXPECT_TRUE(large_url.is_valid()); |
| EXPECT_EQ(url::kMaxURLChars + 1, large_url.possibly_invalid_spec().size()); |
| orig_config.set_pac_url(large_url); |
| |
| // Notify the ProxyConfigServiceMojo of this URL through the client interface. |
| config_client_->OnProxyConfigUpdated(net::ProxyConfigWithAnnotation( |
| orig_config, TRAFFIC_ANNOTATION_FOR_TESTS)); |
| |
| WaitForConfig(); |
| |
| // Read back the ProxyConfig that was observed (which has been serialized |
| // through a Mojo pipe). |
| const GURL& observed_url = observer_.observed_config().value().pac_url(); |
| |
| // The URL should be unchanged, and not changed by the Mojo serialization. |
| EXPECT_EQ(large_url, observed_url); |
| EXPECT_EQ(url::kMaxURLChars + 1, observed_url.possibly_invalid_spec().size()); |
| } |
| |
| } // namespace |
| |
| } // namespace network |