diff options
Diffstat (limited to 'components/data_reduction_proxy')
5 files changed, 212 insertions, 10 deletions
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc index 96d8647e..a3bb98e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.cc @@ -62,6 +62,12 @@ const char kUMAConfigServiceFetchLatency[] = const char kUMAConfigServiceAuthExpired[] = "DataReductionProxy.ConfigService.AuthExpired"; +#if defined(OS_ANDROID) +// Maximum duration to wait before fetching the config, while the application +// is in background. +const uint32_t kMaxBackgroundFetchIntervalSeconds = 6 * 60 * 60; // 6 hours. +#endif + #if defined(USE_GOOGLE_API_KEYS) // Used in all Data Reduction Proxy URLs to specify API Key. const char kApiKeyName[] = "key"; @@ -156,6 +162,9 @@ DataReductionProxyConfigServiceClient::DataReductionProxyConfigServiceClient( enabled_(false), remote_config_applied_(false), url_request_context_getter_(nullptr), +#if defined(OS_ANDROID) + foreground_fetch_pending_(false), +#endif previous_request_failed_authentication_(false), failed_attempts_before_success_(0) { DCHECK(request_options); @@ -177,8 +186,21 @@ base::TimeDelta DataReductionProxyConfigServiceClient::CalculateNextConfigRefreshTime( bool fetch_succeeded, const base::TimeDelta& config_expiration_delta, - const base::TimeDelta& backoff_delay) const { + const base::TimeDelta& backoff_delay) { DCHECK(backoff_delay >= base::TimeDelta()); + +#if defined(OS_ANDROID) + foreground_fetch_pending_ = false; + if (!fetch_succeeded && IsApplicationStateBackground()) { + // If Chromium is in background, then fetch the config when Chromium comes + // to foreground or after max of |kMaxBackgroundFetchIntervalSeconds| and + // |backoff_delay|. + foreground_fetch_pending_ = true; + return std::max(backoff_delay, base::TimeDelta::FromSeconds( + kMaxBackgroundFetchIntervalSeconds)); + } +#endif + if (fetch_succeeded) { return std::max(backoff_delay, config_expiration_delta); } @@ -189,6 +211,14 @@ DataReductionProxyConfigServiceClient::CalculateNextConfigRefreshTime( void DataReductionProxyConfigServiceClient::InitializeOnIOThread( net::URLRequestContextGetter* url_request_context_getter) { DCHECK(url_request_context_getter); +#if defined(OS_ANDROID) + // It is okay to use Unretained here because |app_status_listener| would be + // destroyed before |this|. + app_status_listener_.reset( + new base::android::ApplicationStatusListener(base::Bind( + &DataReductionProxyConfigServiceClient::OnApplicationStateChange, + base::Unretained(this)))); +#endif net::NetworkChangeNotifier::AddIPAddressObserver(this); url_request_context_getter_ = url_request_context_getter; } @@ -418,6 +448,7 @@ void DataReductionProxyConfigServiceClient::HandleResponse( GetBackoffEntry()->InformOfRequest(succeeded); base::TimeDelta next_config_refresh_time = CalculateNextConfigRefreshTime( succeeded, refresh_duration, GetBackoffEntry()->GetTimeUntilRelease()); + SetConfigRefreshTimer(next_config_refresh_time); event_creator_->EndConfigRequest(bound_net_log_, status.error(), response_code, @@ -462,4 +493,22 @@ bool DataReductionProxyConfigServiceClient::ParseAndApplyProxyConfig( return true; } +#if defined(OS_ANDROID) +bool DataReductionProxyConfigServiceClient::IsApplicationStateBackground() + const { + return base::android::ApplicationStatusListener::GetState() != + base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES; +} + +void DataReductionProxyConfigServiceClient::OnApplicationStateChange( + base::android::ApplicationState new_state) { + DCHECK(thread_checker_.CalledOnValidThread()); + if (new_state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES && + foreground_fetch_pending_) { + foreground_fetch_pending_ = false; + RetrieveConfig(); + } +} +#endif + } // namespace data_reduction_proxy diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h index 2024a26..3124c6c 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client.h @@ -22,6 +22,10 @@ #include "net/url_request/url_fetcher_delegate.h" #include "url/gurl.h" +#if defined(OS_ANDROID) +#include "base/android/application_status_listener.h" +#endif // OS_ANDROID + namespace net { class HostPortPair; class HttpRequestHeaders; @@ -110,6 +114,12 @@ class DataReductionProxyConfigServiceClient // configuration. void SetConfigRefreshTimer(const base::TimeDelta& delay); +#if defined(OS_ANDROID) + // Returns true if Chromium is in background. + // Virtualized for mocking. + virtual bool IsApplicationStateBackground() const; +#endif + private: friend class TestDataReductionProxyConfigServiceClient; @@ -118,7 +128,7 @@ class DataReductionProxyConfigServiceClient base::TimeDelta CalculateNextConfigRefreshTime( bool fetch_succeeded, const base::TimeDelta& config_expiration, - const base::TimeDelta& backoff_delay) const; + const base::TimeDelta& backoff_delay); // Override of net::NetworkChangeNotifier::IPAddressObserver. void OnIPAddressChanged() override; @@ -153,6 +163,12 @@ class DataReductionProxyConfigServiceClient // parsed and applied. bool ParseAndApplyProxyConfig(const ClientConfig& config); +#if defined(OS_ANDROID) + // Listens to when Chromium comes to foreground and fetches new client config + // if the config fetch is pending. + void OnApplicationStateChange(base::android::ApplicationState new_state); +#endif + scoped_ptr<DataReductionProxyParams> params_; // The caller must ensure that the |request_options_| outlives this instance. @@ -203,6 +219,16 @@ class DataReductionProxyConfigServiceClient // configuration. base::TimeTicks config_fetch_start_time_; +#if defined(OS_ANDROID) + // Listens to the application transitions from foreground to background or + // vice versa. + scoped_ptr<base::android::ApplicationStatusListener> app_status_listener_; + + // True if config needs to be fetched when the application comes to + // foreground. + bool foreground_fetch_pending_; +#endif + // Keeps track of whether the previous request to a Data Reduction Proxy // failed to authenticate. This is necessary in the situation where a new // configuration with a bad session key is obtained, but the previous request diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc index 90100fc..f67548f 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_config_service_client_unittest.cc @@ -58,7 +58,13 @@ const char kPersistedFallback[] = "persisted.net:80"; const char kPersistedSessionKey[] = "PersistedSessionKey"; // Duration (in seconds) after which the config should be refreshed. -const int kConfingRefreshDurationSeconds = 600; +const int kConfigRefreshDurationSeconds = 600; + +#if defined(OS_ANDROID) +// Maximum duration to wait before fetching the config, while the application +// is in background. +const uint32_t kMaxBackgroundFetchIntervalSeconds = 6 * 60 * 60; // 6 hours. +#endif } // namespace @@ -144,20 +150,20 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test { // Set up the various test ClientConfigs. ClientConfig config = - CreateConfig(kSuccessSessionKey, kConfingRefreshDurationSeconds, 0, + CreateConfig(kSuccessSessionKey, kConfigRefreshDurationSeconds, 0, ProxyServer_ProxyScheme_HTTPS, "origin.net", 443, ProxyServer_ProxyScheme_HTTP, "fallback.net", 80); config.SerializeToString(&config_); encoded_config_ = EncodeConfig(config); ClientConfig previous_config = - CreateConfig(kOldSuccessSessionKey, kConfingRefreshDurationSeconds, 0, + CreateConfig(kOldSuccessSessionKey, kConfigRefreshDurationSeconds, 0, ProxyServer_ProxyScheme_HTTPS, "old.origin.net", 443, ProxyServer_ProxyScheme_HTTP, "old.fallback.net", 80); previous_config.SerializeToString(&previous_config_); ClientConfig persisted = - CreateConfig(kPersistedSessionKey, kConfingRefreshDurationSeconds, 0, + CreateConfig(kPersistedSessionKey, kConfigRefreshDurationSeconds, 0, ProxyServer_ProxyScheme_HTTPS, "persisted.net", 443, ProxyServer_ProxyScheme_HTTP, "persisted.net", 80); loaded_config_ = EncodeConfig(persisted); @@ -190,7 +196,7 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test { kSuccessOrigin, net::ProxyServer::SCHEME_HTTP)); expected_http_proxies.push_back(net::ProxyServer::FromURI( kSuccessFallback, net::ProxyServer::SCHEME_HTTP)); - EXPECT_EQ(base::TimeDelta::FromSeconds(kConfingRefreshDurationSeconds), + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), config_client()->GetDelay()); EXPECT_THAT(configurator()->proxies_for_http(), testing::ContainerEq(expected_http_proxies)); @@ -206,7 +212,7 @@ class DataReductionProxyConfigServiceClientTest : public testing::Test { kOldSuccessOrigin, net::ProxyServer::SCHEME_HTTP)); expected_http_proxies.push_back(net::ProxyServer::FromURI( kOldSuccessFallback, net::ProxyServer::SCHEME_HTTP)); - EXPECT_EQ(base::TimeDelta::FromSeconds(kConfingRefreshDurationSeconds), + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), config_client()->GetDelay()); EXPECT_THAT(configurator()->proxies_for_http(), testing::ContainerEq(expected_http_proxies)); @@ -387,7 +393,7 @@ TEST_F(DataReductionProxyConfigServiceClientTest, DevRolloutAndQuic) { config_client()->RetrieveConfig(); RunUntilIdle(); - EXPECT_EQ(base::TimeDelta::FromSeconds(kConfingRefreshDurationSeconds), + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), config_client()->GetDelay()) << i; @@ -450,6 +456,10 @@ TEST_F(DataReductionProxyConfigServiceClientTest, EnsureBackoff) { EXPECT_TRUE(configurator()->proxies_for_https().empty()); EXPECT_EQ(base::TimeDelta::FromSeconds(20), config_client()->GetDelay()); +#if defined(OS_ANDROID) + EXPECT_FALSE(config_client()->foreground_fetch_pending()); +#endif + // Second attempt should be unsuccessful and backoff time should increase. config_client()->RetrieveConfig(); RunUntilIdle(); @@ -458,6 +468,10 @@ TEST_F(DataReductionProxyConfigServiceClientTest, EnsureBackoff) { EXPECT_EQ(base::TimeDelta::FromSeconds(40), config_client()->GetDelay()); EXPECT_TRUE(persisted_config().empty()); +#if defined(OS_ANDROID) + EXPECT_FALSE(config_client()->foreground_fetch_pending()); +#endif + EXPECT_EQ(2, config_client()->failed_attempts_before_success()); histogram_tester.ExpectTotalCount( "DataReductionProxy.ConfigService.FetchFailedAttemptsBeforeSuccess", 0); @@ -473,6 +487,9 @@ TEST_F(DataReductionProxyConfigServiceClientTest, RemoteConfigSuccess) { config_client()->RetrieveConfig(); RunUntilIdle(); VerifyRemoteSuccess(); +#if defined(OS_ANDROID) + EXPECT_FALSE(config_client()->foreground_fetch_pending()); +#endif } // Tests that the config is read successfully on the second attempt. @@ -822,4 +839,80 @@ TEST_F(DataReductionProxyConfigServiceClientTest, ApplySerializedConfigLocal) { EXPECT_FALSE(request_options()->GetSecureSession().empty()); } +#if defined(OS_ANDROID) +// Verifies the correctness of fetching config when Chromium is in background +// and foreground. +TEST_F(DataReductionProxyConfigServiceClientTest, FetchConfigOnForeground) { + Init(true); + SetDataReductionProxyEnabled(true); + + { + // Tests that successful config fetches while Chromium is in background, + // does not trigger refetches when Chromium comes to foreground. + base::HistogramTester histogram_tester; + AddMockSuccess(); + config_client()->set_application_state_background(true); + config_client()->RetrieveConfig(); + RunUntilIdle(); + VerifyRemoteSuccess(); + EXPECT_FALSE(config_client()->foreground_fetch_pending()); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 1); + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), + config_client()->GetDelay()); + config_client()->set_application_state_background(false); + config_client()->TriggerApplicationStatusToForeground(); + RunUntilIdle(); + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), + config_client()->GetDelay()); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 1); + } + + { + // Tests that config fetch failures while Chromium is in foreground does not + // trigger refetches when Chromium comes to foreground again. + base::HistogramTester histogram_tester; + AddMockFailure(); + config_client()->set_application_state_background(false); + config_client()->RetrieveConfig(); + RunUntilIdle(); + EXPECT_FALSE(config_client()->foreground_fetch_pending()); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 0); + EXPECT_EQ(base::TimeDelta::FromSeconds(20), config_client()->GetDelay()); + config_client()->TriggerApplicationStatusToForeground(); + RunUntilIdle(); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 0); + EXPECT_EQ(base::TimeDelta::FromSeconds(20), config_client()->GetDelay()); + } + + { + // Tests that config fetch failures while Chromium is in background, trigger + // a refetch when Chromium comes to foreground. + base::HistogramTester histogram_tester; + AddMockFailure(); + AddMockSuccess(); + config_client()->set_application_state_background(true); + config_client()->RetrieveConfig(); + RunUntilIdle(); + EXPECT_TRUE(config_client()->foreground_fetch_pending()); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 0); + EXPECT_EQ(base::TimeDelta::FromSeconds(kMaxBackgroundFetchIntervalSeconds), + config_client()->GetDelay()); + config_client()->set_application_state_background(false); + config_client()->TriggerApplicationStatusToForeground(); + RunUntilIdle(); + EXPECT_FALSE(config_client()->foreground_fetch_pending()); + histogram_tester.ExpectTotalCount( + "DataReductionProxy.ConfigService.FetchLatency", 1); + EXPECT_EQ(base::TimeDelta::FromSeconds(kConfigRefreshDurationSeconds), + config_client()->GetDelay()); + VerifyRemoteSuccess(); + } +} +#endif + } // namespace data_reduction_proxy diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc index cc72d68..d1a7a72 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.cc @@ -110,8 +110,12 @@ TestDataReductionProxyConfigServiceClient:: event_creator, net_log, config_storer), +#if defined(OS_ANDROID) + is_application_state_background_(false), +#endif tick_clock_(base::Time::UnixEpoch()), - test_backoff_entry_(&kTestBackoffPolicy, &tick_clock_) {} + test_backoff_entry_(&kTestBackoffPolicy, &tick_clock_) { +} TestDataReductionProxyConfigServiceClient:: ~TestDataReductionProxyConfigServiceClient() { @@ -174,6 +178,19 @@ void TestDataReductionProxyConfigServiceClient::TestTickClock::SetTime( time_ = time; } +#if defined(OS_ANDROID) +bool TestDataReductionProxyConfigServiceClient::IsApplicationStateBackground() + const { + return is_application_state_background_; +} + +void TestDataReductionProxyConfigServiceClient:: + TriggerApplicationStatusToForeground() { + OnApplicationStateChange( + base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES); +} +#endif + MockDataReductionProxyService::MockDataReductionProxyService( DataReductionProxySettings* settings, PrefService* prefs, diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h index 1e3594b..c10d794 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h @@ -121,6 +121,19 @@ class TestDataReductionProxyConfigServiceClient int32_t failed_attempts_before_success() const; +#if defined(OS_ANDROID) + bool IsApplicationStateBackground() const override; + + void set_application_state_background(bool new_state) { + is_application_state_background_ = new_state; + } + + bool foreground_fetch_pending() const { return foreground_fetch_pending_; } + + // Triggers the callback for Chromium status change to foreground. + void TriggerApplicationStatusToForeground(); +#endif + protected: // Overrides of DataReductionProxyConfigServiceClient base::Time Now() override; @@ -145,6 +158,10 @@ class TestDataReductionProxyConfigServiceClient base::Time time_; }; +#if defined(OS_ANDROID) + bool is_application_state_background_; +#endif + TestTickClock tick_clock_; net::BackoffEntry test_backoff_entry_; }; |