summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpavely@chromium.org <pavely@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 22:17:13 +0000
committerpavely@chromium.org <pavely@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-21 22:17:13 +0000
commitad3995ca5fe927c846f08e17044e14603d1a8b19 (patch)
tree28d89cd4ecbe42d00fbfe1f545634934479bb41e
parent2c9ba710edbc2cc3cd771524ef072a52fdb0d82b (diff)
downloadchromium_src-ad3995ca5fe927c846f08e17044e14603d1a8b19.zip
chromium_src-ad3995ca5fe927c846f08e17044e14603d1a8b19.tar.gz
chromium_src-ad3995ca5fe927c846f08e17044e14603d1a8b19.tar.bz2
Control invalidations network channel from syncer experiment
- Created new experiment protobuf. - ProfileSyncService writes value to prefs - TiclInvalidationService registers for changes to both gcm enabled and invalidations over GCM pref settings. When prefs change it decides which channel to use and restarts invalidator if needed. BUG=325020 R=zea@chromium.org Review URL: https://codereview.chromium.org/205333003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@258689 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/invalidation/invalidation_service_factory.cc6
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service.cc46
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service.h15
-rw-r--r--chrome/browser/invalidation/ticl_invalidation_service_unittest.cc83
-rw-r--r--chrome/browser/sync/profile_sync_service.cc3
-rw-r--r--chrome/common/pref_names.cc5
-rw-r--r--chrome/common/pref_names.h1
-rw-r--r--sync/internal_api/public/util/experiments.h10
-rw-r--r--sync/internal_api/sync_manager_impl.cc12
-rw-r--r--sync/protocol/experiments_specifics.proto6
-rw-r--r--sync/protocol/proto_value_conversions.cc1
11 files changed, 177 insertions, 11 deletions
diff --git a/chrome/browser/invalidation/invalidation_service_factory.cc b/chrome/browser/invalidation/invalidation_service_factory.cc
index b0907b5..ec5f01f 100644
--- a/chrome/browser/invalidation/invalidation_service_factory.cc
+++ b/chrome/browser/invalidation/invalidation_service_factory.cc
@@ -18,8 +18,10 @@
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h"
+#include "chrome/common/pref_names.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/signin/core/profile_oauth2_token_service.h"
+#include "components/user_prefs/pref_registry_syncable.h"
#if defined(OS_ANDROID)
#include "chrome/browser/invalidation/invalidation_controller_android.h"
@@ -107,6 +109,10 @@ KeyedService* InvalidationServiceFactory::BuildServiceInstanceFor(
void InvalidationServiceFactory::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
+ registry->RegisterBooleanPref(
+ prefs::kInvalidationServiceUseGCMChannel,
+ false,
+ user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
InvalidatorStorage::RegisterProfilePrefs(registry);
}
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.cc b/chrome/browser/invalidation/ticl_invalidation_service.cc
index 8da391e..1ecdf4c 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service.cc
@@ -6,13 +6,16 @@
#include "base/command_line.h"
#include "base/metrics/histogram.h"
+#include "base/prefs/pref_service.h"
#include "chrome/browser/invalidation/gcm_invalidation_bridge.h"
#include "chrome/browser/invalidation/invalidation_auth_provider.h"
#include "chrome/browser/invalidation/invalidation_logger.h"
#include "chrome/browser/invalidation/invalidation_service_util.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/services/gcm/gcm_profile_service.h"
#include "chrome/browser/services/gcm/gcm_profile_service_factory.h"
#include "chrome/common/chrome_content_client.h"
+#include "chrome/common/pref_names.h"
#include "components/signin/core/profile_oauth2_token_service.h"
#include "google_apis/gaia/gaia_constants.h"
#include "sync/notifier/gcm_network_channel_delegate.h"
@@ -64,6 +67,7 @@ TiclInvalidationService::TiclInvalidationService(
auth_provider_(auth_provider.Pass()),
invalidator_registrar_(new syncer::InvalidatorRegistrar()),
request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
+ network_channel_type_(PUSH_CLIENT_CHANNEL),
logger_() {}
TiclInvalidationService::~TiclInvalidationService() {
@@ -80,8 +84,20 @@ void TiclInvalidationService::Init() {
invalidator_storage_->SetInvalidatorClientId(GenerateInvalidatorClientId());
}
+ pref_change_registrar_.Init(profile_->GetPrefs());
+ pref_change_registrar_.Add(
+ prefs::kInvalidationServiceUseGCMChannel,
+ base::Bind(&TiclInvalidationService::UpdateInvalidationNetworkChannel,
+ base::Unretained(this)));
+ pref_change_registrar_.Add(
+ prefs::kGCMChannelEnabled,
+ base::Bind(&TiclInvalidationService::UpdateInvalidationNetworkChannel,
+ base::Unretained(this)));
+
+ UpdateInvalidationNetworkChannel();
+
if (IsReadyToStart()) {
- StartInvalidator(PUSH_CLIENT_CHANNEL);
+ StartInvalidator(network_channel_type_);
}
auth_provider_->AddObserver(this);
@@ -195,7 +211,7 @@ void TiclInvalidationService::OnGetTokenSuccess(
request_access_token_backoff_.Reset();
access_token_ = access_token;
if (!IsStarted() && IsReadyToStart()) {
- StartInvalidator(PUSH_CLIENT_CHANNEL);
+ StartInvalidator(network_channel_type_);
} else {
UpdateInvalidatorCredentials();
}
@@ -235,7 +251,7 @@ void TiclInvalidationService::OnRefreshTokenAvailable(
const std::string& account_id) {
if (auth_provider_->GetAccountId() == account_id) {
if (!IsStarted() && IsReadyToStart()) {
- StartInvalidator(PUSH_CLIENT_CHANNEL);
+ StartInvalidator(network_channel_type_);
}
}
}
@@ -346,7 +362,9 @@ void TiclInvalidationService::StartInvalidator(
DCHECK(invalidator_storage_);
DCHECK(!invalidator_storage_->GetInvalidatorClientId().empty());
- if (access_token_.empty()) {
+ // Request access token for PushClientChannel. GCMNetworkChannel will request
+ // access token before sending message to server.
+ if (network_channel == PUSH_CLIENT_CHANNEL && access_token_.empty()) {
DVLOG(1)
<< "TiclInvalidationService: "
<< "Deferring start until we have an access token.";
@@ -405,6 +423,26 @@ void TiclInvalidationService::StartInvalidator(
invalidator_registrar_->GetAllRegisteredIds());
}
+void TiclInvalidationService::UpdateInvalidationNetworkChannel() {
+ InvalidationNetworkChannel network_channel_type = PUSH_CLIENT_CHANNEL;
+// For now don't use GCM on iOS.
+#if !defined(OS_IOS)
+ if (profile_->GetPrefs()->GetBoolean(
+ prefs::kInvalidationServiceUseGCMChannel) &&
+ gcm::GCMProfileService::GetGCMEnabledState(profile_) ==
+ gcm::GCMProfileService::ALWAYS_ENABLED) {
+ network_channel_type = GCM_NETWORK_CHANNEL;
+ }
+#endif
+ if (network_channel_type_ == network_channel_type)
+ return;
+ network_channel_type_ = network_channel_type;
+ if (IsStarted()) {
+ StopInvalidator();
+ StartInvalidator(network_channel_type_);
+ }
+}
+
void TiclInvalidationService::UpdateInvalidatorCredentials() {
std::string email = auth_provider_->GetAccountId();
diff --git a/chrome/browser/invalidation/ticl_invalidation_service.h b/chrome/browser/invalidation/ticl_invalidation_service.h
index c28e585..17f35d2 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service.h
+++ b/chrome/browser/invalidation/ticl_invalidation_service.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_change_registrar.h"
#include "base/threading/non_thread_safe.h"
#include "base/timer/timer.h"
#include "chrome/browser/invalidation/invalidation_auth_provider.h"
@@ -39,6 +40,11 @@ class TiclInvalidationService : public base::NonThreadSafe,
public InvalidationAuthProvider::Observer,
public syncer::InvalidationHandler {
public:
+ enum InvalidationNetworkChannel {
+ PUSH_CLIENT_CHANNEL = 0,
+ GCM_NETWORK_CHANNEL = 1
+ };
+
TiclInvalidationService(scoped_ptr<InvalidationAuthProvider> auth_provider,
Profile* profile);
virtual ~TiclInvalidationService();
@@ -94,17 +100,14 @@ class TiclInvalidationService : public base::NonThreadSafe,
void InitForTest(syncer::Invalidator* invalidator);
friend class TiclInvalidationServiceTestDelegate;
+ friend class TiclInvalidationServiceChannelTest;
private:
- enum InvalidationNetworkChannel {
- PUSH_CLIENT_CHANNEL = 0,
- GCM_NETWORK_CHANNEL = 1
- };
-
bool IsReadyToStart();
bool IsStarted();
void StartInvalidator(InvalidationNetworkChannel network_channel);
+ void UpdateInvalidationNetworkChannel();
void UpdateInvalidatorCredentials();
void StopInvalidator();
@@ -125,6 +128,8 @@ class TiclInvalidationService : public base::NonThreadSafe,
base::OneShotTimer<TiclInvalidationService> request_access_token_retry_timer_;
net::BackoffEntry request_access_token_backoff_;
+ PrefChangeRegistrar pref_change_registrar_;
+ InvalidationNetworkChannel network_channel_type_;
scoped_ptr<GCMInvalidationBridge> gcm_invalidation_bridge_;
// The invalidation logger object we use to record state changes
diff --git a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
index f86dc5a..3a193bc 100644
--- a/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
+++ b/chrome/browser/invalidation/ticl_invalidation_service_unittest.cc
@@ -4,12 +4,15 @@
#include "chrome/browser/invalidation/ticl_invalidation_service.h"
+#include "base/prefs/pref_service.h"
#include "chrome/browser/invalidation/invalidation_service_factory.h"
#include "chrome/browser/invalidation/invalidation_service_test_template.h"
#include "chrome/browser/invalidation/profile_invalidation_auth_provider.h"
#include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
+#include "chrome/browser/signin/fake_signin_manager.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
+#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "sync/notifier/fake_invalidation_handler.h"
#include "sync/notifier/fake_invalidator.h"
@@ -67,4 +70,84 @@ INSTANTIATE_TYPED_TEST_CASE_P(
TiclInvalidationServiceTest, InvalidationServiceTest,
TiclInvalidationServiceTestDelegate);
+class TiclInvalidationServiceChannelTest : public ::testing::Test {
+ public:
+ TiclInvalidationServiceChannelTest() {}
+ virtual ~TiclInvalidationServiceChannelTest() {}
+
+ virtual void SetUp() OVERRIDE {
+ profile_.reset(new TestingProfile());
+ fake_signin_manager_ = static_cast<SigninManagerBase*>(
+ SigninManagerFactory::GetInstance()->SetTestingFactoryAndUse(
+ profile_.get(), FakeSigninManagerBase::Build));
+ token_service_.reset(new FakeProfileOAuth2TokenService);
+
+ scoped_ptr<InvalidationAuthProvider> auth_provider(
+ new ProfileInvalidationAuthProvider(
+ fake_signin_manager_, token_service_.get(), NULL));
+ invalidation_service_.reset(
+ new TiclInvalidationService(auth_provider.Pass(), profile_.get()));
+ invalidation_service_->Init();
+ }
+
+ virtual void TearDown() OVERRIDE {
+ invalidation_service_->Shutdown();
+ }
+
+ TiclInvalidationService::InvalidationNetworkChannel GetNetworkChannel() {
+ return invalidation_service_->network_channel_type_;
+ }
+
+ protected:
+ scoped_ptr<TestingProfile> profile_;
+ SigninManagerBase* fake_signin_manager_;
+ scoped_ptr<FakeProfileOAuth2TokenService> token_service_;
+ scoped_ptr<TiclInvalidationService> invalidation_service_;
+};
+
+TEST_F(TiclInvalidationServiceChannelTest, ChannelSelectionTest) {
+ TiclInvalidationService::InvalidationNetworkChannel expected_gcm_channel =
+ TiclInvalidationService::GCM_NETWORK_CHANNEL;
+#if defined(OS_IOS)
+ expected_gcm_channel = TiclInvalidationService::PUSH_CLIENT_CHANNEL;
+#endif
+
+ EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+ // If stars allign use GCM channel.
+ profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+ profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+ true);
+ EXPECT_EQ(expected_gcm_channel, GetNetworkChannel());
+
+ // If Invalidation channel setting is not set or says false fall back to push
+ // channel.
+ profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+
+ profile_->GetPrefs()->ClearPref(prefs::kInvalidationServiceUseGCMChannel);
+ EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+ profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+ false);
+ EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+ // If invalidation channel setting says use GCM but GCM is not ALWAYS_ENABLED
+ // then fall back to push channel.
+ profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+ false);
+
+ profile_->GetPrefs()->ClearPref(prefs::kGCMChannelEnabled);
+ EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+ profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, false);
+ EXPECT_EQ(TiclInvalidationService::PUSH_CLIENT_CHANNEL, GetNetworkChannel());
+
+ // If first invalidation setting gets enabled and after that gcm setting gets
+ // enabled then should still switch to GCM channel.
+ profile_->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+ true);
+ profile_->GetPrefs()->SetBoolean(prefs::kGCMChannelEnabled, true);
+ EXPECT_EQ(expected_gcm_channel, GetNetworkChannel());
+}
+
} // namespace invalidation
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 57f6c2c..e68bfb5 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -1022,6 +1022,9 @@ void ProfileSyncService::OnExperimentsChanged(
profile()->GetPrefs()->ClearPref(prefs::kGCMChannelEnabled);
}
+ profile()->GetPrefs()->SetBoolean(prefs::kInvalidationServiceUseGCMChannel,
+ experiments.gcm_invalidations_enabled);
+
int bookmarks_experiment_state_before = profile_->GetPrefs()->GetInteger(
sync_driver::prefs::kEnhancedBookmarksExperimentEnabled);
// kEnhancedBookmarksExperiment flag could have values "", "1" and "0".
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index cfdbd72..6953a8a 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1835,6 +1835,11 @@ const char kInvalidatorInvalidationState[] = "invalidator.invalidation_state";
// yet. Used to keep invalidation clients in sync in case of a restart.
const char kInvalidatorSavedInvalidations[] = "invalidator.saved_invalidations";
+// Boolean indicating that TiclInvalidationService should use GCM channel.
+// False or lack of settings means XMPPPushClient channel.
+const char kInvalidationServiceUseGCMChannel[] =
+ "invalidation_service.use_gcm_channel";
+
// String the identifies the last user that logged into sync and other
// google services. As opposed to kGoogleServicesUsername, this value is not
// cleared on signout, but while the user is signed in the two values will
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 3306eb4..545d5c0 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -612,6 +612,7 @@ extern const char kGoogleServicesPasswordHash[];
extern const char kInvalidatorClientId[];
extern const char kInvalidatorInvalidationState[];
extern const char kInvalidatorSavedInvalidations[];
+extern const char kInvalidationServiceUseGCMChannel[];
extern const char kSignInPromoStartupCount[];
extern const char kSignInPromoUserSkipped[];
diff --git a/sync/internal_api/public/util/experiments.h b/sync/internal_api/public/util/experiments.h
index 18a0887..9063cbb 100644
--- a/sync/internal_api/public/util/experiments.h
+++ b/sync/internal_api/public/util/experiments.h
@@ -15,6 +15,7 @@ const char kFaviconSyncTag[] = "favicon_sync";
const char kPreCommitUpdateAvoidanceTag[] = "pre_commit_update_avoidance";
const char kGCMChannelTag[] = "gcm_channel";
const char kEnhancedBookmarksTag[] = "enhanced_bookmarks";
+const char kGCMInvalidationsTag[] = "gcm_invalidations";
// A structure to hold the enable status of experimental sync features.
struct Experiments {
@@ -27,13 +28,15 @@ struct Experiments {
Experiments()
: favicon_sync_limit(200),
gcm_channel_state(UNSET),
- enhanced_bookmarks_enabled(false) {}
+ enhanced_bookmarks_enabled(false),
+ gcm_invalidations_enabled(false) {}
bool Matches(const Experiments& rhs) {
return (favicon_sync_limit == rhs.favicon_sync_limit &&
gcm_channel_state == rhs.gcm_channel_state &&
enhanced_bookmarks_enabled == rhs.enhanced_bookmarks_enabled &&
- enhanced_bookmarks_ext_id == rhs.enhanced_bookmarks_ext_id);
+ enhanced_bookmarks_ext_id == rhs.enhanced_bookmarks_ext_id &&
+ gcm_invalidations_enabled == rhs.gcm_invalidations_enabled);
}
// The number of favicons that a client is permitted to sync.
@@ -45,6 +48,9 @@ struct Experiments {
// Enable the enhanced bookmarks sync datatype.
bool enhanced_bookmarks_enabled;
+ // Enable invalidations over GCM channel.
+ bool gcm_invalidations_enabled;
+
// Enhanced bookmarks extension id.
std::string enhanced_bookmarks_ext_id;
};
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc
index 8ecb29f..3b4a1fd 100644
--- a/sync/internal_api/sync_manager_impl.cc
+++ b/sync/internal_api/sync_manager_impl.cc
@@ -1129,6 +1129,18 @@ bool SyncManagerImpl::ReceivedExperiment(Experiments* experiments) {
found_experiment = true;
}
+ ReadNode gcm_invalidations_node(&trans);
+ if (gcm_invalidations_node.InitByClientTagLookup(
+ syncer::EXPERIMENTS, syncer::kGCMInvalidationsTag) ==
+ BaseNode::INIT_OK) {
+ const sync_pb::GcmInvalidationsFlags& gcm_invalidations =
+ gcm_invalidations_node.GetExperimentsSpecifics().gcm_invalidations();
+ if (gcm_invalidations.has_enabled()) {
+ experiments->gcm_invalidations_enabled = gcm_invalidations.enabled();
+ found_experiment = true;
+ }
+ }
+
return found_experiment;
}
diff --git a/sync/protocol/experiments_specifics.proto b/sync/protocol/experiments_specifics.proto
index 790cf02..723fe55 100644
--- a/sync/protocol/experiments_specifics.proto
+++ b/sync/protocol/experiments_specifics.proto
@@ -50,6 +50,11 @@ message EnhancedBookmarksFlags {
optional string extension_id = 2;
}
+// Flags for enabling GCM channel for invalidations.
+message GcmInvalidationsFlags {
+ optional bool enabled = 1;
+}
+
// Contains one flag or set of related flags. Each node of the experiments type
// will have a unique_client_tag identifying which flags it contains. By
// convention, the tag name should match the sub-message name.
@@ -61,4 +66,5 @@ message ExperimentsSpecifics {
optional PreCommitUpdateAvoidanceFlags pre_commit_update_avoidance = 5;
optional GcmChannelFlags gcm_channel = 6;
optional EnhancedBookmarksFlags enhanced_bookmarks = 7;
+ optional GcmInvalidationsFlags gcm_invalidations = 8;
}
diff --git a/sync/protocol/proto_value_conversions.cc b/sync/protocol/proto_value_conversions.cc
index 83748faa..496a35d 100644
--- a/sync/protocol/proto_value_conversions.cc
+++ b/sync/protocol/proto_value_conversions.cc
@@ -503,6 +503,7 @@ base::DictionaryValue* ExperimentsSpecificsToValue(
SET(favicon_sync, FaviconSyncFlagsToValue);
SET_EXPERIMENT_ENABLED_FIELD(gcm_channel);
SET_EXPERIMENT_ENABLED_FIELD(enhanced_bookmarks);
+ SET_EXPERIMENT_ENABLED_FIELD(gcm_invalidations);
return value;
}