1 // Copyright (c) 2011 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.
5 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
9 #include "base/command_line.h"
10 #include "base/files/file_path.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/prefs/pref_registry_simple.h"
13 #include "base/prefs/testing_pref_service.h"
14 #include "base/test/histogram_tester.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "components/proxy_config/proxy_config_dictionary.h"
17 #include "components/proxy_config/proxy_config_pref_names.h"
18 #include "net/proxy/proxy_info.h"
19 #include "net/proxy/proxy_list.h"
20 #include "testing/gmock/include/gmock/gmock.h"
21 #include "testing/gtest/include/gtest/gtest.h"
29 const char kFixedPacUrl
[] = "http://chromium.org/fixed_pac_url";
31 // Testing proxy config service that allows us to fire notifications at will.
32 class TestProxyConfigService
: public net::ProxyConfigService
{
34 TestProxyConfigService(const net::ProxyConfig
& config
,
35 ConfigAvailability availability
)
37 availability_(availability
) {}
39 void SetProxyConfig(const net::ProxyConfig config
,
40 ConfigAvailability availability
) {
42 availability_
= availability
;
43 FOR_EACH_OBSERVER(net::ProxyConfigService::Observer
, observers_
,
44 OnProxyConfigChanged(config
, availability
));
48 void AddObserver(net::ProxyConfigService::Observer
* observer
) override
{
49 observers_
.AddObserver(observer
);
52 void RemoveObserver(net::ProxyConfigService::Observer
* observer
) override
{
53 observers_
.RemoveObserver(observer
);
56 net::ProxyConfigService::ConfigAvailability
GetLatestProxyConfig(
57 net::ProxyConfig
* config
) override
{
62 net::ProxyConfig config_
;
63 ConfigAvailability availability_
;
64 base::ObserverList
<net::ProxyConfigService::Observer
, true> observers_
;
67 // A mock observer for capturing callbacks.
68 class MockObserver
: public net::ProxyConfigService::Observer
{
70 MOCK_METHOD2(OnProxyConfigChanged
,
71 void(const net::ProxyConfig
&,
72 net::ProxyConfigService::ConfigAvailability
));
75 class PrefProxyConfigTrackerImplTest
: public testing::Test
{
77 PrefProxyConfigTrackerImplTest() {
78 pref_service_
.reset(new TestingPrefServiceSimple());
79 PrefProxyConfigTrackerImpl::RegisterPrefs(pref_service_
->registry());
80 fixed_config_
.set_pac_url(GURL(kFixedPacUrl
));
82 new TestProxyConfigService(fixed_config_
,
83 net::ProxyConfigService::CONFIG_VALID
);
84 proxy_config_tracker_
.reset(new PrefProxyConfigTrackerImpl(
85 pref_service_
.get(), base::ThreadTaskRunnerHandle::Get()));
86 proxy_config_service_
=
87 proxy_config_tracker_
->CreateTrackingProxyConfigService(
88 scoped_ptr
<net::ProxyConfigService
>(delegate_service_
));
89 // SetProxyConfigServiceImpl triggers update of initial prefs proxy
90 // config by tracker to chrome proxy config service, so flush all pending
91 // tasks so that tests start fresh.
95 ~PrefProxyConfigTrackerImplTest() override
{
96 proxy_config_tracker_
->DetachFromPrefService();
98 proxy_config_tracker_
.reset();
99 proxy_config_service_
.reset();
102 base::MessageLoop loop_
;
103 scoped_ptr
<TestingPrefServiceSimple
> pref_service_
;
104 TestProxyConfigService
* delegate_service_
; // weak
105 scoped_ptr
<net::ProxyConfigService
> proxy_config_service_
;
106 net::ProxyConfig fixed_config_
;
109 scoped_ptr
<PrefProxyConfigTrackerImpl
> proxy_config_tracker_
;
112 TEST_F(PrefProxyConfigTrackerImplTest
, BaseConfiguration
) {
113 net::ProxyConfig actual_config
;
114 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID
,
115 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
116 EXPECT_EQ(GURL(kFixedPacUrl
), actual_config
.pac_url());
119 TEST_F(PrefProxyConfigTrackerImplTest
, DynamicPrefOverrides
) {
120 pref_service_
->SetManagedPref(proxy_config::prefs::kProxy
,
121 ProxyConfigDictionary::CreateFixedServers(
122 "http://example.com:3128", std::string()));
123 loop_
.RunUntilIdle();
125 net::ProxyConfig actual_config
;
126 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID
,
127 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
128 EXPECT_FALSE(actual_config
.auto_detect());
129 EXPECT_EQ(net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY
,
130 actual_config
.proxy_rules().type
);
131 EXPECT_EQ(actual_config
.proxy_rules().single_proxies
.Get(),
132 net::ProxyServer::FromURI("http://example.com:3128",
133 net::ProxyServer::SCHEME_HTTP
));
135 pref_service_
->SetManagedPref(proxy_config::prefs::kProxy
,
136 ProxyConfigDictionary::CreateAutoDetect());
137 loop_
.RunUntilIdle();
139 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID
,
140 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
141 EXPECT_TRUE(actual_config
.auto_detect());
144 // Compares proxy configurations, but allows different identifiers.
145 MATCHER_P(ProxyConfigMatches
, config
, "") {
146 net::ProxyConfig
reference(config
);
147 reference
.set_id(arg
.id());
148 return reference
.Equals(arg
);
151 TEST_F(PrefProxyConfigTrackerImplTest
, Observers
) {
152 const net::ProxyConfigService::ConfigAvailability CONFIG_VALID
=
153 net::ProxyConfigService::CONFIG_VALID
;
154 MockObserver observer
;
155 proxy_config_service_
->AddObserver(&observer
);
157 // Firing the observers in the delegate should trigger a notification.
158 net::ProxyConfig config2
;
159 config2
.set_auto_detect(true);
160 EXPECT_CALL(observer
, OnProxyConfigChanged(ProxyConfigMatches(config2
),
161 CONFIG_VALID
)).Times(1);
162 delegate_service_
->SetProxyConfig(config2
, CONFIG_VALID
);
163 loop_
.RunUntilIdle();
164 Mock::VerifyAndClearExpectations(&observer
);
166 // Override configuration, this should trigger a notification.
167 net::ProxyConfig pref_config
;
168 pref_config
.set_pac_url(GURL(kFixedPacUrl
));
170 EXPECT_CALL(observer
, OnProxyConfigChanged(ProxyConfigMatches(pref_config
),
171 CONFIG_VALID
)).Times(1);
172 pref_service_
->SetManagedPref(
173 proxy_config::prefs::kProxy
,
174 ProxyConfigDictionary::CreatePacScript(kFixedPacUrl
, false));
175 loop_
.RunUntilIdle();
176 Mock::VerifyAndClearExpectations(&observer
);
178 // Since there are pref overrides, delegate changes should be ignored.
179 net::ProxyConfig config3
;
180 config3
.proxy_rules().ParseFromString("http=config3:80");
181 EXPECT_CALL(observer
, OnProxyConfigChanged(_
, _
)).Times(0);
182 fixed_config_
.set_auto_detect(true);
183 delegate_service_
->SetProxyConfig(config3
, CONFIG_VALID
);
184 loop_
.RunUntilIdle();
185 Mock::VerifyAndClearExpectations(&observer
);
187 // Clear the override should switch back to the fixed configuration.
188 EXPECT_CALL(observer
, OnProxyConfigChanged(ProxyConfigMatches(config3
),
189 CONFIG_VALID
)).Times(1);
190 pref_service_
->RemoveManagedPref(proxy_config::prefs::kProxy
);
191 loop_
.RunUntilIdle();
192 Mock::VerifyAndClearExpectations(&observer
);
194 // Delegate service notifications should show up again.
195 net::ProxyConfig config4
;
196 config4
.proxy_rules().ParseFromString("socks:config4");
197 EXPECT_CALL(observer
, OnProxyConfigChanged(ProxyConfigMatches(config4
),
198 CONFIG_VALID
)).Times(1);
199 delegate_service_
->SetProxyConfig(config4
, CONFIG_VALID
);
200 loop_
.RunUntilIdle();
201 Mock::VerifyAndClearExpectations(&observer
);
203 proxy_config_service_
->RemoveObserver(&observer
);
206 TEST_F(PrefProxyConfigTrackerImplTest
, Fallback
) {
207 const net::ProxyConfigService::ConfigAvailability CONFIG_VALID
=
208 net::ProxyConfigService::CONFIG_VALID
;
209 MockObserver observer
;
210 net::ProxyConfig actual_config
;
211 delegate_service_
->SetProxyConfig(net::ProxyConfig::CreateDirect(),
212 net::ProxyConfigService::CONFIG_UNSET
);
213 proxy_config_service_
->AddObserver(&observer
);
215 // Prepare test data.
216 net::ProxyConfig recommended_config
= net::ProxyConfig::CreateAutoDetect();
217 net::ProxyConfig user_config
=
218 net::ProxyConfig::CreateFromCustomPacURL(GURL(kFixedPacUrl
));
220 // Set a recommended pref.
221 EXPECT_CALL(observer
,
222 OnProxyConfigChanged(ProxyConfigMatches(recommended_config
),
223 CONFIG_VALID
)).Times(1);
224 pref_service_
->SetRecommendedPref(proxy_config::prefs::kProxy
,
225 ProxyConfigDictionary::CreateAutoDetect());
226 loop_
.RunUntilIdle();
227 Mock::VerifyAndClearExpectations(&observer
);
228 EXPECT_EQ(CONFIG_VALID
,
229 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
230 EXPECT_TRUE(actual_config
.Equals(recommended_config
));
232 // Override in user prefs.
233 EXPECT_CALL(observer
,
234 OnProxyConfigChanged(ProxyConfigMatches(user_config
),
235 CONFIG_VALID
)).Times(1);
236 pref_service_
->SetManagedPref(
237 proxy_config::prefs::kProxy
,
238 ProxyConfigDictionary::CreatePacScript(kFixedPacUrl
, false));
239 loop_
.RunUntilIdle();
240 Mock::VerifyAndClearExpectations(&observer
);
241 EXPECT_EQ(CONFIG_VALID
,
242 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
243 EXPECT_TRUE(actual_config
.Equals(user_config
));
245 // Go back to recommended pref.
246 EXPECT_CALL(observer
,
247 OnProxyConfigChanged(ProxyConfigMatches(recommended_config
),
248 CONFIG_VALID
)).Times(1);
249 pref_service_
->RemoveManagedPref(proxy_config::prefs::kProxy
);
250 loop_
.RunUntilIdle();
251 Mock::VerifyAndClearExpectations(&observer
);
252 EXPECT_EQ(CONFIG_VALID
,
253 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
254 EXPECT_TRUE(actual_config
.Equals(recommended_config
));
256 proxy_config_service_
->RemoveObserver(&observer
);
259 TEST_F(PrefProxyConfigTrackerImplTest
, ExplicitSystemSettings
) {
260 pref_service_
->SetRecommendedPref(proxy_config::prefs::kProxy
,
261 ProxyConfigDictionary::CreateAutoDetect());
262 pref_service_
->SetUserPref(proxy_config::prefs::kProxy
,
263 ProxyConfigDictionary::CreateSystem());
264 loop_
.RunUntilIdle();
266 // Test if we actually use the system setting, which is |kFixedPacUrl|.
267 net::ProxyConfig actual_config
;
268 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID
,
269 proxy_config_service_
->GetLatestProxyConfig(&actual_config
));
270 EXPECT_EQ(GURL(kFixedPacUrl
), actual_config
.pac_url());
273 void CheckResolvedProxyMatches(net::ProxyConfig
* config
,
275 const std::string
& result_string
) {
276 net::ProxyInfo expected_result
;
277 expected_result
.UseNamedProxy(result_string
);
279 net::ProxyInfo result
;
280 config
->proxy_rules().Apply(url
, &result
);
282 EXPECT_TRUE(expected_result
.proxy_list().Equals(result
.proxy_list()))
283 << "expected: " << expected_result
.proxy_list().ToPacString()
284 << "\nactual: " << result
.proxy_list().ToPacString();
287 TEST_F(PrefProxyConfigTrackerImplTest
, ExcludeGooglezipDataReductionProxies
) {
288 const std::string kDataReductionProxies
=
289 "https://proxy.googlezip.net:443,compress.googlezip.net,"
290 "https://proxy-dev.googlezip.net:443,proxy-dev.googlezip.net,"
291 "quic://proxy.googlezip.net";
292 const int kNumDataReductionProxies
= 5;
295 std::string initial_proxy_rules
;
296 const char* http_proxy_info
;
297 const char* https_proxy_info
;
298 const char* ftp_proxy_info
;
299 int expected_num_removed_proxies
;
301 {"http=foopyhttp," + kDataReductionProxies
+
302 ",direct://;https=foopyhttps," + kDataReductionProxies
+
303 ",direct://;ftp=foopyftp," + kDataReductionProxies
+ ",direct://",
304 "foopyhttp;direct://",
305 "foopyhttps;direct://",
306 "foopyftp;direct://",
307 kNumDataReductionProxies
* 3},
309 {"foopy," + kDataReductionProxies
+ ",direct://",
313 kNumDataReductionProxies
},
315 {"http=" + kDataReductionProxies
+ ";https=" + kDataReductionProxies
+
316 ";ftp=" + kDataReductionProxies
,
320 kNumDataReductionProxies
* 3},
322 {"http=" + kDataReductionProxies
+ ",foopy,direct://",
326 kNumDataReductionProxies
},
341 // Test setting the proxy from a user pref.
342 for (const auto& test
: test_cases
) {
343 base::HistogramTester histogram_tester
;
344 pref_service_
->SetUserPref(proxy_config::prefs::kProxy
,
345 ProxyConfigDictionary::CreateFixedServers(
346 test
.initial_proxy_rules
, std::string()));
347 loop_
.RunUntilIdle();
349 net::ProxyConfig config
;
350 EXPECT_EQ(net::ProxyConfigService::CONFIG_VALID
,
351 proxy_config_service_
->GetLatestProxyConfig(&config
));
352 histogram_tester
.ExpectUniqueSample(
353 "Net.PrefProxyConfig.GooglezipProxyRemovalCount",
354 test
.expected_num_removed_proxies
, 1);
356 CheckResolvedProxyMatches(&config
, GURL("http://google.com"),
357 test
.http_proxy_info
);
358 CheckResolvedProxyMatches(&config
, GURL("https://google.com"),
359 test
.https_proxy_info
);
360 CheckResolvedProxyMatches(&config
, GURL("ftp://google.com"),
361 test
.ftp_proxy_info
);