1 // Copyright 2015 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 "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h"
6
7 #include <stddef.h>
8 #include <stdint.h>
9
10 #include <string>
11 #include <vector>
12
13 #include "base/base64.h"
14 #include "base/command_line.h"
15 #include "base/metrics/field_trial.h"
16 #include "base/run_loop.h"
17 #include "base/stl_util.h"
18 #include "base/test/bind.h"
19 #include "base/test/metrics/histogram_tester.h"
20 #include "base/test/mock_entropy_provider.h"
21 #include "base/test/scoped_feature_list.h"
22 #include "base/test/task_environment.h"
23 #include "base/time/default_clock.h"
24 #include "base/time/time.h"
25 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_test_utils.h"
26 #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h"
27 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
28 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h"
29 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h"
30 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h"
31 #include "components/data_reduction_proxy/proto/client_config.pb.h"
32 #include "components/prefs/pref_registry_simple.h"
33 #include "net/base/network_change_notifier.h"
34 #include "net/base/proxy_server.h"
35 #include "net/http/http_request_headers.h"
36 #include "net/http/http_response_headers.h"
37 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
38 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
39 #include "services/network/test/test_url_loader_factory.h"
40 #include "services/network/test/test_utils.h"
41 #include "testing/gmock/include/gmock/gmock.h"
42 #include "testing/gtest/include/gtest/gtest.h"
43 #include "url/gurl.h"
44
45 namespace {
46
47 // The following values should match those in
48 // DataReductionProxyConfigServiceClientTest.config_:
49 const char kSuccessSessionKey[] = "SecretSessionKey";
50
51 // The following values should match those in
52 // DataReductionProxyConfigServiceClientTest.previous_config_:
53 const char kOldSuccessSessionKey[] = "OldSecretSessionKey";
54
55 // The following values should match those in
56 // DataReductionProxyConfigServiceClientTest.loaded_config_:
57 const char kPersistedSessionKey[] = "PersistedSessionKey";
58
59 // Duration (in seconds) after which the config should be refreshed.
60 const int kConfigRefreshDurationSeconds = 600;
61
62 #if defined(OS_ANDROID)
63 // Maximum duration to wait before fetching the config, while the application
64 // is in background.
65 const uint32_t kMaxBackgroundFetchIntervalSeconds = 6 * 60 * 60; // 6 hours.
66 #endif
67
68 } // namespace
69
70 namespace data_reduction_proxy {
71
72 class DataReductionProxyConfigServiceClientTest : public testing::Test {
73 protected:
DataReductionProxyConfigServiceClientTest(bool enable_aggressive_config_fetch_feature=false)74 DataReductionProxyConfigServiceClientTest(
75 bool enable_aggressive_config_fetch_feature = false)
76 : test_shared_url_loader_factory_(
77 base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
78 &test_url_loader_factory_)) {
79 if (enable_aggressive_config_fetch_feature) {
80 scoped_feature_list_.InitAndEnableFeature(
81 features::kDataReductionProxyAggressiveConfigFetch);
82 } else {
83 scoped_feature_list_.InitAndDisableFeature(
84 features::kDataReductionProxyAggressiveConfigFetch);
85 }
86 }
87
SetUp()88 void SetUp() override {
89 testing::Test::SetUp();
90
91 // Install an interceptor here to process the queue of responses
92 // (fed by calls to AddMock{Success,PreviousSuccess,Failure}.
93 test_url_loader_factory_.SetInterceptor(base::BindLambdaForTesting(
94 [&](const network::ResourceRequest& request) {
95 // Some tests trigger loading, without having an respective
96 // mock response set. Ignore such cases.
97 if (mock_responses_.size() <= curr_mock_response_index_) {
98 test_url_loader_factory_.pending_requests()->clear();
99 return;
100 }
101 test_url_loader_factory_.ClearResponses();
102 test_url_loader_factory_.AddResponse(
103 request.url.spec(),
104 mock_responses_[curr_mock_response_index_].response,
105 mock_responses_[curr_mock_response_index_].http_code);
106 curr_mock_response_index_++;
107 RunUntilIdle();
108 }));
109 }
110
Init()111 void Init() {
112 test_context_ = DataReductionProxyTestContext::Builder()
113 .WithURLLoaderFactory(test_shared_url_loader_factory_)
114 .WithMockRequestOptions()
115 .WithTestConfigClient()
116 .SkipSettingsInitialization()
117 .Build();
118
119 test_context_->InitSettings();
120 ResetBackoffEntryReleaseTime();
121 test_context_->test_config_client()->SetNow(base::Time::UnixEpoch());
122 test_context_->test_config_client()->SetEnabled(true);
123 test_context_->test_config_client()->SetConfigServiceURL(
124 GURL("http://configservice.com"));
125
126 // Set up the various test ClientConfigs.
127 ClientConfig config = CreateClientConfig(kSuccessSessionKey,
128 kConfigRefreshDurationSeconds, 0);
129 config.SerializeToString(&config_);
130 encoded_config_ = EncodeConfig(config);
131
132 ClientConfig previous_config = CreateClientConfig(
133 kOldSuccessSessionKey, kConfigRefreshDurationSeconds, 0);
134 previous_config.SerializeToString(&previous_config_);
135
136 ClientConfig persisted = CreateClientConfig(
137 kPersistedSessionKey, kConfigRefreshDurationSeconds, 0);
138 loaded_config_ = EncodeConfig(persisted);
139
140 ClientConfig ignore_block_list_config = CreateClientConfig(
141 kSuccessSessionKey, kConfigRefreshDurationSeconds, 0);
142 ignore_block_list_encoded_config_ = EncodeConfig(ignore_block_list_config);
143
144 ClientConfig no_proxies_config;
145 no_proxies_config.set_session_key(kSuccessSessionKey);
146 no_proxies_config.mutable_refresh_duration()->set_seconds(
147 kConfigRefreshDurationSeconds);
148 no_proxies_config.mutable_refresh_duration()->set_nanos(0);
149 no_proxies_config_ = EncodeConfig(no_proxies_config);
150 }
151
ResetBackoffEntryReleaseTime()152 void ResetBackoffEntryReleaseTime() {
153 config_client()->SetCustomReleaseTime(base::TimeTicks::UnixEpoch());
154 }
155
VerifyRemoteSuccess(bool expect_secure_proxies)156 void VerifyRemoteSuccess(bool expect_secure_proxies) {
157 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
158 config_client()->GetDelay());
159 EXPECT_EQ(kSuccessSessionKey, request_options()->GetSecureSession());
160 // The config should be persisted on the pref.
161 EXPECT_EQ(encoded_config(), persisted_config());
162 }
163
VerifyRemoteSuccessWithOldConfig()164 void VerifyRemoteSuccessWithOldConfig() {
165 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
166 config_client()->GetDelay());
167 EXPECT_EQ(kOldSuccessSessionKey, request_options()->GetSecureSession());
168 }
169
VerifySuccessWithLoadedConfig(bool expect_secure_proxies)170 void VerifySuccessWithLoadedConfig(bool expect_secure_proxies) {
171 EXPECT_EQ(kPersistedSessionKey, request_options()->GetSecureSession());
172 }
173
config_client()174 TestDataReductionProxyConfigServiceClient* config_client() {
175 return test_context_->test_config_client();
176 }
177
request_options()178 MockDataReductionProxyRequestOptions* request_options() {
179 return test_context_->mock_request_options();
180 }
181
RunUntilIdle()182 void RunUntilIdle() { test_context_->RunUntilIdle(); }
183
AddMockSuccess()184 void AddMockSuccess() {
185 mock_responses_.push_back({success_response(), net::HTTP_OK});
186 }
187
AddMockPreviousSuccess()188 void AddMockPreviousSuccess() {
189 mock_responses_.push_back({previous_success_response(), net::HTTP_OK});
190 }
191
AddMockFailure()192 void AddMockFailure() {
193 mock_responses_.push_back({std::string(), net::HTTP_NOT_FOUND});
194 }
195
persisted_config() const196 std::string persisted_config() const {
197 return test_context_->pref_service()->GetString(
198 prefs::kDataReductionProxyConfig);
199 }
200
persisted_config_retrieval_time() const201 base::Time persisted_config_retrieval_time() const {
202 return base::Time() +
203 base::TimeDelta::FromMicroseconds(
204 test_context_->pref_service()->GetInt64(
205 prefs::kDataReductionProxyLastConfigRetrievalTime));
206 }
207
success_response() const208 const std::string& success_response() const { return config_; }
209
encoded_config() const210 const std::string& encoded_config() const { return encoded_config_; }
211
previous_success_response() const212 const std::string& previous_success_response() const {
213 return previous_config_;
214 }
ignore_block_list_encoded_config() const215 const std::string& ignore_block_list_encoded_config() const {
216 return ignore_block_list_encoded_config_;
217 }
no_proxies_config() const218 const std::string& no_proxies_config() const { return no_proxies_config_; }
219
loaded_config() const220 const std::string& loaded_config() const { return loaded_config_; }
221
222 private:
223 base::test::ScopedFeatureList scoped_feature_list_;
224 base::test::SingleThreadTaskEnvironment task_environment_;
225
226 network::TestURLLoaderFactory test_url_loader_factory_;
227 scoped_refptr<network::SharedURLLoaderFactory>
228 test_shared_url_loader_factory_;
229
230 protected:
231 std::unique_ptr<DataReductionProxyTestContext> test_context_;
232
233 private:
234 std::unique_ptr<DataReductionProxyRequestOptions> request_options_;
235
236 // A configuration from the current remote request. The encoded version is
237 // also stored.
238 std::string config_;
239 std::string encoded_config_;
240
241 // A configuration from a previous remote request.
242 std::string previous_config_;
243
244 // An encoded config that represents a previously saved configuration.
245 std::string loaded_config_;
246
247 // A configuration where the block list rules are ignored.
248 std::string ignore_block_list_encoded_config_;
249
250 // A configuration where no proxies are configured.
251 std::string no_proxies_config_;
252
253 struct MockResponse {
254 std::string response;
255 net::HttpStatusCode http_code;
256 };
257 std::vector<MockResponse> mock_responses_;
258 size_t curr_mock_response_index_ = 0;
259
260 DISALLOW_COPY_AND_ASSIGN(DataReductionProxyConfigServiceClientTest);
261 };
262
263 // Tests that backoff values increases with every time config cannot be fetched.
TEST_F(DataReductionProxyConfigServiceClientTest,EnsureBackoff)264 TEST_F(DataReductionProxyConfigServiceClientTest, EnsureBackoff) {
265 Init();
266 // Use a local/static config.
267 base::HistogramTester histogram_tester;
268 AddMockFailure();
269 AddMockFailure();
270 AddMockSuccess();
271
272 EXPECT_EQ(0, config_client()->failed_attempts_before_success());
273
274 // First attempt should be unsuccessful.
275 config_client()->RetrieveConfig();
276 RunUntilIdle();
277 EXPECT_EQ(base::TimeDelta::FromSeconds(30), config_client()->GetDelay());
278
279 #if defined(OS_ANDROID)
280 EXPECT_FALSE(config_client()->foreground_fetch_pending());
281 #endif
282
283 // Second attempt should be unsuccessful and backoff time should increase.
284 config_client()->RetrieveConfig();
285 RunUntilIdle();
286 EXPECT_EQ(base::TimeDelta::FromSeconds(90), config_client()->GetDelay());
287 EXPECT_TRUE(persisted_config().empty());
288 EXPECT_TRUE(persisted_config_retrieval_time().is_null());
289
290 #if defined(OS_ANDROID)
291 EXPECT_FALSE(config_client()->foreground_fetch_pending());
292 #endif
293
294 EXPECT_EQ(2, config_client()->failed_attempts_before_success());
295 histogram_tester.ExpectTotalCount(
296 "DataReductionProxy.ConfigService.FetchFailedAttemptsBeforeSuccess", 0);
297 }
298
299 // Tests that the config is read successfully on the first attempt.
TEST_F(DataReductionProxyConfigServiceClientTest,RemoteConfigSuccess)300 TEST_F(DataReductionProxyConfigServiceClientTest, RemoteConfigSuccess) {
301 Init();
302 base::HistogramTester histogram_tester;
303
304 AddMockSuccess();
305 config_client()->RetrieveConfig();
306 RunUntilIdle();
307 VerifyRemoteSuccess(true);
308 histogram_tester.ExpectTotalCount(
309 "DataReductionProxy.ConfigService.HttpRequestRTT", 1);
310 #if defined(OS_ANDROID)
311 EXPECT_FALSE(config_client()->foreground_fetch_pending());
312 #endif
313 }
314
315 // Tests that the config is read successfully on the first attempt, and secure
316 // proxies are not used if the secure check failed.
TEST_F(DataReductionProxyConfigServiceClientTest,RemoteConfigSuccessWithSecureCheckFail)317 TEST_F(DataReductionProxyConfigServiceClientTest,
318 RemoteConfigSuccessWithSecureCheckFail) {
319 Init();
320 AddMockSuccess();
321 config_client()->RetrieveConfig();
322 RunUntilIdle();
323 VerifyRemoteSuccess(false);
324 #if defined(OS_ANDROID)
325 EXPECT_FALSE(config_client()->foreground_fetch_pending());
326 #endif
327 }
328
329
330 // Tests that the config is read successfully on the second attempt.
TEST_F(DataReductionProxyConfigServiceClientTest,RemoteConfigSuccessAfterFailure)331 TEST_F(DataReductionProxyConfigServiceClientTest,
332 RemoteConfigSuccessAfterFailure) {
333 Init();
334 base::HistogramTester histogram_tester;
335
336 AddMockFailure();
337 AddMockSuccess();
338
339 EXPECT_EQ(0, config_client()->failed_attempts_before_success());
340
341 // First attempt should be unsuccessful.
342 config_client()->RetrieveConfig();
343 RunUntilIdle();
344 EXPECT_EQ(1, config_client()->failed_attempts_before_success());
345 EXPECT_EQ(base::TimeDelta::FromSeconds(30), config_client()->GetDelay());
346 EXPECT_TRUE(request_options()->GetSecureSession().empty());
347
348 // Second attempt should be successful.
349 config_client()->RetrieveConfig();
350 RunUntilIdle();
351 VerifyRemoteSuccess(true);
352 EXPECT_EQ(0, config_client()->failed_attempts_before_success());
353
354 histogram_tester.ExpectUniqueSample(
355 "DataReductionProxy.ConfigService.FetchFailedAttemptsBeforeSuccess", 1,
356 1);
357 histogram_tester.ExpectTotalCount(
358 "DataReductionProxy.ConfigService.HttpRequestRTT", 1);
359 }
360
361 // Verifies that the config is fetched successfully after IP address changes.
TEST_F(DataReductionProxyConfigServiceClientTest,OnIPAddressChange)362 TEST_F(DataReductionProxyConfigServiceClientTest, OnIPAddressChange) {
363 Init();
364 const struct {
365 bool secure_proxies_allowed;
366 } tests[] = {
367 {
368 true,
369 },
370 {
371 false,
372 },
373 };
374
375 for (size_t i = 0; i < base::size(tests); ++i) {
376 config_client()->RetrieveConfig();
377
378 const int kFailureCount = 5;
379
380 for (int i = 0; i < kFailureCount; ++i) {
381 AddMockFailure();
382 config_client()->RetrieveConfig();
383 RunUntilIdle();
384 }
385
386 // Verify that the backoff increased exponentially.
387 EXPECT_EQ(base::TimeDelta::FromSeconds(2430),
388 config_client()->GetDelay()); // 2430 = 30 * 3^(5-1)
389 EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount());
390
391 // IP address change should reset.
392 config_client()->OnConnectionChanged(
393 network::mojom::ConnectionType::CONNECTION_WIFI);
394 EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
395 EXPECT_EQ(i == 0, persisted_config().empty());
396 EXPECT_EQ(i == 0, persisted_config_retrieval_time().is_null());
397 ResetBackoffEntryReleaseTime();
398
399 // Fetching the config should be successful.
400 AddMockSuccess();
401 config_client()->RetrieveConfig();
402 RunUntilIdle();
403 VerifyRemoteSuccess(tests[i].secure_proxies_allowed);
404 }
405 }
406
407 // Verifies that the config is fetched successfully after IP address changes,
408 // and secure proxies are not used if the secure proxy check fails later after
409 // some time.
TEST_F(DataReductionProxyConfigServiceClientTest,OnIPAddressChangeDelayedSecureProxyCheckFail)410 TEST_F(DataReductionProxyConfigServiceClientTest,
411 OnIPAddressChangeDelayedSecureProxyCheckFail) {
412 Init();
413
414 config_client()->RetrieveConfig();
415
416 const int kFailureCount = 5;
417
418 for (int i = 0; i < kFailureCount; ++i) {
419 AddMockFailure();
420 config_client()->RetrieveConfig();
421 RunUntilIdle();
422 }
423
424 // Verify that the backoff increased exponentially.
425 EXPECT_EQ(base::TimeDelta::FromSeconds(2430),
426 config_client()->GetDelay()); // 2430 = 30 * 3^(5-1)
427 EXPECT_EQ(kFailureCount, config_client()->GetBackoffErrorCount());
428
429 // IP address change should reset.
430 config_client()->OnConnectionChanged(
431 network::mojom::ConnectionType::CONNECTION_WIFI);
432 EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
433 EXPECT_TRUE(persisted_config().empty());
434 EXPECT_TRUE(persisted_config_retrieval_time().is_null());
435 ResetBackoffEntryReleaseTime();
436
437 // Fetching the config should be successful.
438 AddMockSuccess();
439 config_client()->RetrieveConfig();
440 RunUntilIdle();
441 VerifyRemoteSuccess(true);
442
443 }
444
445 // Verifies that fetching the remote config has no effect if the config client
446 // is disabled.
TEST_F(DataReductionProxyConfigServiceClientTest,OnIPAddressChangeDisabled)447 TEST_F(DataReductionProxyConfigServiceClientTest, OnIPAddressChangeDisabled) {
448 Init();
449 config_client()->SetEnabled(false);
450 config_client()->RetrieveConfig();
451 EXPECT_TRUE(request_options()->GetSecureSession().empty());
452
453 enum : int { kFailureCount = 5 };
454
455 for (int i = 0; i < kFailureCount; ++i) {
456 config_client()->RetrieveConfig();
457 RunUntilIdle();
458 EXPECT_TRUE(request_options()->GetSecureSession().empty());
459 }
460
461 EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
462 config_client()->OnConnectionChanged(
463 network::mojom::ConnectionType::CONNECTION_WIFI);
464 EXPECT_EQ(0, config_client()->GetBackoffErrorCount());
465
466 config_client()->RetrieveConfig();
467 RunUntilIdle();
468
469 EXPECT_TRUE(request_options()->GetSecureSession().empty());
470 }
471
472 // Verifies that the persisted client config is fetched from the disk at
473 // startup, and that the persisted client config is used only if it is less
474 // than 24 hours old.
TEST_F(DataReductionProxyConfigServiceClientTest,ValidatePersistedClientConfig)475 TEST_F(DataReductionProxyConfigServiceClientTest,
476 ValidatePersistedClientConfig) {
477 Init();
478
479 const struct {
480 base::Optional<base::TimeDelta> staleness;
481 bool expect_valid_config;
482 } tests[] = {
483 {
484 base::nullopt,
485 true,
486 },
487 {
488 base::TimeDelta::FromHours(25),
489 false,
490 },
491 {
492 base::TimeDelta::FromHours(1),
493 true,
494 },
495 };
496
497 for (const auto& test : tests) {
498 base::HistogramTester histogram_tester;
499 // Reset the state.
500 request_options()->Invalidate();
501 test_context_->pref_service()->ClearPref(
502 prefs::kDataReductionProxyLastConfigRetrievalTime);
503 RunUntilIdle();
504 EXPECT_TRUE(request_options()->GetSecureSession().empty());
505
506 // Apply a valid config. This should be stored on the disk.
507 AddMockSuccess();
508 config_client()->RetrieveConfig();
509
510 RunUntilIdle();
511 EXPECT_EQ(kSuccessSessionKey, request_options()->GetSecureSession());
512
513 if (test.staleness) {
514 base::TimeDelta last_config_retrieval_time =
515 base::Time::Now() - base::Time() - test.staleness.value();
516
517 test_context_->pref_service()->SetInt64(
518 prefs::kDataReductionProxyLastConfigRetrievalTime,
519 last_config_retrieval_time.InMicroseconds());
520 test_context_->pref_service()->SchedulePendingLossyWrites();
521 test_context_->pref_service()->CommitPendingWrite();
522 }
523
524 RunUntilIdle();
525 EXPECT_FALSE(persisted_config().empty());
526 EXPECT_FALSE(persisted_config_retrieval_time().is_null());
527
528 // Simulate startup which should cause the empty persisted client config to
529 // be read from the disk.
530 config_client()->SetRemoteConfigApplied(false);
531 request_options()->Invalidate();
532 test_context_->data_reduction_proxy_service()->ReadPersistedClientConfig();
533 RunUntilIdle();
534 EXPECT_NE(test.expect_valid_config,
535 request_options()->GetSecureSession().empty());
536 if (test.expect_valid_config) {
537 EXPECT_EQ(kSuccessSessionKey, request_options()->GetSecureSession());
538 }
539 }
540 }
541
542 // Tests that the config is overriden by kDataReductionProxyServerClientConfig.
TEST_F(DataReductionProxyConfigServiceClientTest,ApplyClientConfigOverride)543 TEST_F(DataReductionProxyConfigServiceClientTest, ApplyClientConfigOverride) {
544 const std::string override_key = "OverrideSecureSession";
545 std::string encoded_config;
546 ClientConfig config =
547 CreateClientConfig(override_key, kConfigRefreshDurationSeconds, 0);
548 config.SerializeToString(&encoded_config);
549 base::Base64Encode(encoded_config, &encoded_config);
550
551 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
552 data_reduction_proxy::switches::kDataReductionProxyServerClientConfig,
553 encoded_config);
554 Init();
555
556 AddMockSuccess();
557 config_client()->RetrieveConfig();
558 RunUntilIdle();
559 // Make sure repeated fetches won't change the overridden config.
560 config_client()->RetrieveConfig();
561 RunUntilIdle();
562 EXPECT_EQ(request_options()->GetSecureSession(), override_key);
563 }
564
565 // Tests that remote config can be applied after the serialized config has
566 // been applied.
TEST_F(DataReductionProxyConfigServiceClientTest,ApplySerializedConfig)567 TEST_F(DataReductionProxyConfigServiceClientTest, ApplySerializedConfig) {
568 Init();
569 AddMockSuccess();
570
571 config_client()->ApplySerializedConfig(loaded_config());
572 VerifySuccessWithLoadedConfig(true);
573 EXPECT_TRUE(persisted_config().empty());
574
575 config_client()->RetrieveConfig();
576 RunUntilIdle();
577 VerifyRemoteSuccess(true);
578 }
579
580 // Tests that remote config can be applied after the serialized config has
581 // been applied. Verifies that if the secure transport is restricted, then the
582 // secure proxies are not used.
TEST_F(DataReductionProxyConfigServiceClientTest,ApplySerializedConfigWithSecureTransportRestricted)583 TEST_F(DataReductionProxyConfigServiceClientTest,
584 ApplySerializedConfigWithSecureTransportRestricted) {
585 Init();
586
587 AddMockSuccess();
588
589 config_client()->ApplySerializedConfig(loaded_config());
590 VerifySuccessWithLoadedConfig(false);
591 EXPECT_TRUE(persisted_config().empty());
592
593 config_client()->RetrieveConfig();
594 RunUntilIdle();
595 VerifyRemoteSuccess(false);
596 }
597
598 // Tests that serialized config has no effect after the config has been
599 // retrieved successfully.
TEST_F(DataReductionProxyConfigServiceClientTest,ApplySerializedConfigAfterReceipt)600 TEST_F(DataReductionProxyConfigServiceClientTest,
601 ApplySerializedConfigAfterReceipt) {
602 Init();
603 AddMockSuccess();
604
605 EXPECT_TRUE(request_options()->GetSecureSession().empty());
606
607 // Retrieve the remote config.
608 config_client()->RetrieveConfig();
609 RunUntilIdle();
610 VerifyRemoteSuccess(true);
611
612 // ApplySerializedConfig should not have any effect since the remote config
613 // is already applied.
614 config_client()->ApplySerializedConfig(encoded_config());
615 VerifyRemoteSuccess(true);
616 }
617
618 // Tests that a local serialized config can be applied successfully if remote
619 // config has not been fetched so far.
TEST_F(DataReductionProxyConfigServiceClientTest,ApplySerializedConfigLocal)620 TEST_F(DataReductionProxyConfigServiceClientTest, ApplySerializedConfigLocal) {
621 Init();
622 EXPECT_TRUE(request_options()->GetSecureSession().empty());
623 EXPECT_TRUE(persisted_config_retrieval_time().is_null());
624
625 // ApplySerializedConfig should apply the encoded config.
626 config_client()->ApplySerializedConfig(encoded_config());
627 EXPECT_TRUE(persisted_config().empty());
628 EXPECT_TRUE(persisted_config_retrieval_time().is_null());
629 EXPECT_FALSE(request_options()->GetSecureSession().empty());
630 }
631
TEST_F(DataReductionProxyConfigServiceClientTest,EmptyConfigDisablesDRP)632 TEST_F(DataReductionProxyConfigServiceClientTest, EmptyConfigDisablesDRP) {
633 Init();
634
635 config_client()->ApplySerializedConfig(no_proxies_config());
636 }
637
638 #if defined(OS_ANDROID)
639 // Verifies the correctness of fetching config when Chromium is in background
640 // and foreground.
TEST_F(DataReductionProxyConfigServiceClientTest,FetchConfigOnForeground)641 TEST_F(DataReductionProxyConfigServiceClientTest, FetchConfigOnForeground) {
642 Init();
643
644 {
645 // Tests that successful config fetches while Chromium is in background,
646 // does not trigger refetches when Chromium comes to foreground.
647 base::HistogramTester histogram_tester;
648 AddMockSuccess();
649 config_client()->set_application_state_background(true);
650 config_client()->RetrieveConfig();
651 RunUntilIdle();
652 VerifyRemoteSuccess(true);
653 EXPECT_FALSE(config_client()->foreground_fetch_pending());
654 histogram_tester.ExpectTotalCount(
655 "DataReductionProxy.ConfigService.FetchLatency", 1);
656 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
657 config_client()->GetDelay());
658 config_client()->set_application_state_background(false);
659 config_client()->TriggerApplicationStatusToForeground();
660 RunUntilIdle();
661 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
662 config_client()->GetDelay());
663 histogram_tester.ExpectTotalCount(
664 "DataReductionProxy.ConfigService.FetchLatency", 1);
665 }
666
667 {
668 // Tests that config fetch failures while Chromium is in foreground does not
669 // trigger refetches when Chromium comes to foreground again.
670 base::HistogramTester histogram_tester;
671 AddMockFailure();
672 config_client()->set_application_state_background(false);
673 config_client()->RetrieveConfig();
674 RunUntilIdle();
675 EXPECT_FALSE(config_client()->foreground_fetch_pending());
676 histogram_tester.ExpectTotalCount(
677 "DataReductionProxy.ConfigService.FetchLatency", 0);
678 EXPECT_EQ(base::TimeDelta::FromSeconds(30), config_client()->GetDelay());
679 config_client()->TriggerApplicationStatusToForeground();
680 RunUntilIdle();
681 histogram_tester.ExpectTotalCount(
682 "DataReductionProxy.ConfigService.FetchLatency", 0);
683 EXPECT_EQ(base::TimeDelta::FromSeconds(30), config_client()->GetDelay());
684 }
685
686 {
687 // Tests that config fetch failures while Chromium is in background, trigger
688 // a refetch when Chromium comes to foreground.
689 base::HistogramTester histogram_tester;
690 AddMockFailure();
691 AddMockSuccess();
692 config_client()->set_application_state_background(true);
693 config_client()->RetrieveConfig();
694 RunUntilIdle();
695 EXPECT_TRUE(config_client()->foreground_fetch_pending());
696 histogram_tester.ExpectTotalCount(
697 "DataReductionProxy.ConfigService.FetchLatency", 0);
698 EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxBackgroundFetchIntervalSeconds),
699 config_client()->GetDelay());
700 config_client()->set_application_state_background(false);
701 config_client()->TriggerApplicationStatusToForeground();
702 RunUntilIdle();
703 EXPECT_FALSE(config_client()->foreground_fetch_pending());
704 histogram_tester.ExpectTotalCount(
705 "DataReductionProxy.ConfigService.FetchLatency", 1);
706 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
707 config_client()->GetDelay());
708 VerifyRemoteSuccess(true);
709 }
710 }
711
712 class DataReductionProxyAggressiveConfigServiceClientTest
713 : public DataReductionProxyConfigServiceClientTest {
714 public:
DataReductionProxyAggressiveConfigServiceClientTest()715 DataReductionProxyAggressiveConfigServiceClientTest()
716 : DataReductionProxyConfigServiceClientTest(true) {}
717 };
718
TEST_F(DataReductionProxyAggressiveConfigServiceClientTest,AggressiveFetchConfigOnBackground)719 TEST_F(DataReductionProxyAggressiveConfigServiceClientTest,
720 AggressiveFetchConfigOnBackground) {
721 Init();
722
723 // Tests that config fetch failures while Chromium is in background, trigger
724 // refetches while still in background, and no refetch happens Chromium
725 // comes to foreground, when the aggressive client config fetch feature is
726 // enabled.
727 base::HistogramTester histogram_tester;
728 AddMockFailure();
729 AddMockFailure();
730 AddMockSuccess();
731 config_client()->set_application_state_background(true);
732 config_client()->RetrieveConfig();
733 RunUntilIdle();
734 // Three fetches are triggered in background without any backoff. First two
735 // fail, while the third succeeds.
736 EXPECT_EQ(base::TimeDelta::FromSeconds(0),
737 config_client()->GetBackoffTimeUntilRelease());
738 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
739 config_client()->GetDelay());
740 EXPECT_FALSE(config_client()->foreground_fetch_pending());
741 histogram_tester.ExpectTotalCount(
742 "DataReductionProxy.ConfigService.FetchLatency", 1);
743 histogram_tester.ExpectBucketCount(
744 "DataReductionProxy.ConfigService.FetchFailedAttemptsBeforeSuccess", 2,
745 1);
746
747 // No new fetch should happen when Chromium comes to foreground.
748 config_client()->set_application_state_background(false);
749 config_client()->TriggerApplicationStatusToForeground();
750 RunUntilIdle();
751 EXPECT_FALSE(config_client()->foreground_fetch_pending());
752 histogram_tester.ExpectTotalCount(
753 "DataReductionProxy.ConfigService.FetchLatency", 1);
754 EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds),
755 config_client()->GetDelay());
756 VerifyRemoteSuccess(true);
757 }
758
759 #endif
760
761 } // namespace data_reduction_proxy
762