summaryrefslogtreecommitdiffstats
path: root/components/invalidation
diff options
context:
space:
mode:
authorrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 23:17:47 +0000
committerrlarocque@chromium.org <rlarocque@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-09 23:17:47 +0000
commit7315c9652fb59c675cdffbc54c878adbe39532d1 (patch)
treedb7efe4c2ae154ce0436ed1fa1c8accca7dedfaa /components/invalidation
parenta0a15ed2b985456951e9918461d9a27a59ed9cdd (diff)
downloadchromium_src-7315c9652fb59c675cdffbc54c878adbe39532d1.zip
chromium_src-7315c9652fb59c675cdffbc54c878adbe39532d1.tar.gz
chromium_src-7315c9652fb59c675cdffbc54c878adbe39532d1.tar.bz2
First step towards invalidations componentization
Moves some files from chrome/browser/invalidation to components/invalidation. The files moved in this CL are those that do not have dependencies on chrome/, so they can be moved without significant refactoring. This refactoring touches a lot of files, but none of the changes are meaningful. Most of it inovlves changing #include paths, updating DEPS, changing header guards, and other trivial changes. One part of this change that is significant is that it creates two new static libraries and moves some of the symbols formerly defined in chrome/browser/invalidation into those libraries. There is some risk of linker errors if this was done wrong. TBR=bartfab,blundell BUG=336571 Review URL: https://codereview.chromium.org/255273002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@269462 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components/invalidation')
-rw-r--r--components/invalidation/DEPS10
-rw-r--r--components/invalidation/OWNERS5
-rw-r--r--components/invalidation/invalidation_logger.cc122
-rw-r--r--components/invalidation/invalidation_logger.h101
-rw-r--r--components/invalidation/invalidation_logger_observer.h46
-rw-r--r--components/invalidation/invalidation_logger_unittest.cc286
-rw-r--r--components/invalidation/invalidation_service.h122
-rw-r--r--components/invalidation/ticl_settings_provider.cc30
-rw-r--r--components/invalidation/ticl_settings_provider.h44
9 files changed, 766 insertions, 0 deletions
diff --git a/components/invalidation/DEPS b/components/invalidation/DEPS
new file mode 100644
index 0000000..8c519c1
--- /dev/null
+++ b/components/invalidation/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+ "-content",
+
+ "+components/keyed_service",
+
+ "+google/cacheinvalidation",
+
+ "+sync/internal_api/public/base",
+ "+sync/notifier",
+]
diff --git a/components/invalidation/OWNERS b/components/invalidation/OWNERS
new file mode 100644
index 0000000..beb88df4
--- /dev/null
+++ b/components/invalidation/OWNERS
@@ -0,0 +1,5 @@
+dcheng@chromium.org
+nyquist@chromium.org
+rlarocque@chromium.org
+tim@chromium.org
+pavely@chromium.org
diff --git a/components/invalidation/invalidation_logger.cc b/components/invalidation/invalidation_logger.cc
new file mode 100644
index 0000000..c685ca0
--- /dev/null
+++ b/components/invalidation/invalidation_logger.cc
@@ -0,0 +1,122 @@
+// Copyright 2014 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 "components/invalidation/invalidation_logger.h"
+
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "components/invalidation/invalidation_logger_observer.h"
+#include "sync/notifier/invalidation_handler.h"
+
+namespace invalidation {
+class InvalidationLoggerObserver;
+
+InvalidationLogger::InvalidationLogger()
+ : last_invalidator_state_(syncer::TRANSIENT_INVALIDATION_ERROR),
+ last_invalidator_state_timestamp_(base::Time::Now()) { }
+
+InvalidationLogger::~InvalidationLogger() {}
+
+void InvalidationLogger::OnRegistration(const std::string& registrar_name) {
+ registered_handlers_.insert(registrar_name);
+ EmitRegisteredHandlers();
+}
+
+void InvalidationLogger::OnUnregistration(const std::string& registrar_name) {
+ DCHECK(registered_handlers_.find(registrar_name) !=
+ registered_handlers_.end());
+ std::multiset<std::string>::iterator it =
+ registered_handlers_.find(registrar_name);
+ // Delete only one instance of registrar_name.
+ registered_handlers_.erase(it);
+ EmitRegisteredHandlers();
+}
+
+void InvalidationLogger::EmitRegisteredHandlers() {
+ FOR_EACH_OBSERVER(InvalidationLoggerObserver, observer_list_,
+ OnRegistrationChange(registered_handlers_));
+}
+
+void InvalidationLogger::OnStateChange(
+ const syncer::InvalidatorState& new_state) {
+ // Prevent spurious same state emissions from updating the timestamp.
+ if (new_state != last_invalidator_state_)
+ last_invalidator_state_timestamp_ = base::Time::Now();
+ last_invalidator_state_ = new_state;
+ EmitState();
+}
+
+void InvalidationLogger::EmitState() {
+ FOR_EACH_OBSERVER(InvalidationLoggerObserver,
+ observer_list_,
+ OnStateChange(last_invalidator_state_,
+ last_invalidator_state_timestamp_));
+}
+
+void InvalidationLogger::OnUpdateIds(
+ std::map<std::string, syncer::ObjectIdSet> updated_ids) {
+ for (std::map<std::string, syncer::ObjectIdSet>::const_iterator it =
+ updated_ids.begin(); it != updated_ids.end(); ++it) {
+ latest_ids_[it->first] = syncer::ObjectIdSet(it->second);
+ }
+ EmitUpdatedIds();
+}
+
+void InvalidationLogger::EmitUpdatedIds() {
+ for (std::map<std::string, syncer::ObjectIdSet>::const_iterator it =
+ latest_ids_.begin(); it != latest_ids_.end(); ++it) {
+ const syncer::ObjectIdSet& object_ids_for_handler = it->second;
+ syncer::ObjectIdCountMap per_object_invalidation_count;
+ for (syncer::ObjectIdSet::const_iterator oid_it =
+ object_ids_for_handler.begin();
+ oid_it != object_ids_for_handler.end();
+ ++oid_it) {
+ per_object_invalidation_count[*oid_it] = invalidation_count_[*oid_it];
+ }
+ FOR_EACH_OBSERVER(InvalidationLoggerObserver,
+ observer_list_,
+ OnUpdateIds(it->first, per_object_invalidation_count));
+ }
+}
+
+void InvalidationLogger::OnDebugMessage(const base::DictionaryValue& details) {
+ FOR_EACH_OBSERVER(
+ InvalidationLoggerObserver, observer_list_, OnDebugMessage(details));
+}
+
+void InvalidationLogger::OnInvalidation(
+ const syncer::ObjectIdInvalidationMap& details) {
+ std::vector<syncer::Invalidation> internal_invalidations;
+ details.GetAllInvalidations(&internal_invalidations);
+ for (std::vector<syncer::Invalidation>::const_iterator it =
+ internal_invalidations.begin();
+ it != internal_invalidations.end();
+ ++it) {
+ invalidation_count_[it->object_id()]++;
+ }
+ FOR_EACH_OBSERVER(
+ InvalidationLoggerObserver, observer_list_, OnInvalidation(details));
+}
+
+void InvalidationLogger::EmitContent() {
+ EmitState();
+ EmitUpdatedIds();
+ EmitRegisteredHandlers();
+}
+
+void InvalidationLogger::RegisterObserver(
+ InvalidationLoggerObserver* debug_observer) {
+ observer_list_.AddObserver(debug_observer);
+}
+
+void InvalidationLogger::UnregisterObserver(
+ InvalidationLoggerObserver* debug_observer) {
+ observer_list_.RemoveObserver(debug_observer);
+}
+
+bool InvalidationLogger::IsObserverRegistered(
+ InvalidationLoggerObserver* debug_observer) {
+ return observer_list_.HasObserver(debug_observer);
+}
+} // namespace invalidation
diff --git a/components/invalidation/invalidation_logger.h b/components/invalidation/invalidation_logger.h
new file mode 100644
index 0000000..d14dabbb
--- /dev/null
+++ b/components/invalidation/invalidation_logger.h
@@ -0,0 +1,101 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_H_
+#define COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_H_
+
+#include <map>
+#include <set>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
+#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/invalidator_state.h"
+
+namespace base {
+class DictionaryValue;
+} // namespace base
+
+namespace syncer {
+class InvalidationHandler;
+class ObjectIdInvalidationMap;
+} // namespace syncer
+
+namespace invalidation {
+
+class InvalidationLoggerObserver;
+
+// This class is in charge of logging invalidation-related information.
+// It is used store the state of the InvalidatorService that owns this object
+// and then rebroadcast it to observers than can display it accordingly
+// (like a debugging page). This class only stores lightweight state, as in
+// which services are registered and listening for certain objects, and the
+// status of the InvalidatorService (in order not to increase unnecesary
+// memory usage).
+//
+// Observers can be registered and will be called to be notified of any
+// status change immediatly. They can log there the history of what messages
+// they receive.
+
+class InvalidationLogger {
+
+ public:
+ InvalidationLogger();
+ ~InvalidationLogger();
+
+ // Pass through to any registered InvalidationLoggerObservers.
+ // We will do local logging here too.
+ void OnRegistration(const std::string& details);
+ void OnUnregistration(const std::string& details);
+ void OnStateChange(const syncer::InvalidatorState& new_state);
+ void OnUpdateIds(std::map<std::string, syncer::ObjectIdSet> updated_ids);
+ void OnDebugMessage(const base::DictionaryValue& details);
+ void OnInvalidation(const syncer::ObjectIdInvalidationMap& details);
+
+ // Triggers messages to be sent to the Observers to provide them with
+ // the current state of the logging.
+ void EmitContent();
+
+ // Add and remove observers listening for messages.
+ void RegisterObserver(InvalidationLoggerObserver* debug_observer);
+ void UnregisterObserver(InvalidationLoggerObserver* debug_observer);
+ bool IsObserverRegistered(InvalidationLoggerObserver* debug_observer);
+
+ private:
+ // Send to every Observer a OnStateChange event with the latest state.
+ void EmitState();
+
+ // Send to every Observer many OnUpdateIds events, each with one registrar
+ // and every objectId it currently has registered.
+ void EmitUpdatedIds();
+
+ // Send to every Observer a vector with the all the current registered
+ // handlers.
+ void EmitRegisteredHandlers();
+
+ // The list of every observer currently listening for notifications.
+ ObserverList<InvalidationLoggerObserver> observer_list_;
+
+ // The last InvalidatorState updated by the InvalidatorService.
+ syncer::InvalidatorState last_invalidator_state_;
+ base::Time last_invalidator_state_timestamp_;
+
+ // The map that contains every object id that is currently registered
+ // and its owner.
+ std::map<std::string, syncer::ObjectIdSet> latest_ids_;
+
+ // The map that counts how many invalidations per objectId there has been.
+ syncer::ObjectIdCountMap invalidation_count_;
+
+ // The name of all invalidatorHandler registered (note that this is not
+ // necessarily the same as the keys of latest_ids_, because they might
+ // have not registered any object id).
+ std::multiset<std::string> registered_handlers_;
+
+ DISALLOW_COPY_AND_ASSIGN(InvalidationLogger);
+};
+
+} // namespace invalidation
+
+#endif // COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_H_
diff --git a/components/invalidation/invalidation_logger_observer.h b/components/invalidation/invalidation_logger_observer.h
new file mode 100644
index 0000000..dc0fd5a
--- /dev/null
+++ b/components/invalidation/invalidation_logger_observer.h
@@ -0,0 +1,46 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_OBSERVER_H_
+#define COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_OBSERVER_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/invalidator_state.h"
+#include "sync/notifier/object_id_invalidation_map.h"
+
+namespace base {
+class DictionaryValue;
+} // namespace base
+
+namespace syncer {
+class InvalidationHandler;
+class ObjectIdInvalidationMap;
+} // namespace syncer
+
+namespace invalidation {
+// This class provides the possibilty to register as an observer for the
+// InvalidationLogger notifications whenever an InvalidatorService changes
+// its internal state.
+// (i.e. A new registration, a new invalidation, a TICL/GCM state change)
+class InvalidationLoggerObserver {
+ public:
+ virtual void OnRegistrationChange(
+ const std::multiset<std::string>& registered_handlers) = 0;
+ virtual void OnStateChange(const syncer::InvalidatorState& new_state,
+ const base::Time& last_change_timestamp) = 0;
+ virtual void OnUpdateIds(const std::string& handler_name,
+ const syncer::ObjectIdCountMap& details) = 0;
+ virtual void OnDebugMessage(const base::DictionaryValue& details) = 0;
+ virtual void OnInvalidation(
+ const syncer::ObjectIdInvalidationMap& details) = 0;
+ virtual void OnDetailedStatus(const base::DictionaryValue& details) = 0;
+
+ protected:
+ virtual ~InvalidationLoggerObserver() {}
+};
+
+} // namespace invalidation
+
+#endif // COMPONENTS_INVALIDATION_INVALIDATION_LOGGER_OBSERVER_H_
diff --git a/components/invalidation/invalidation_logger_unittest.cc b/components/invalidation/invalidation_logger_unittest.cc
new file mode 100644
index 0000000..2ee0f8d
--- /dev/null
+++ b/components/invalidation/invalidation_logger_unittest.cc
@@ -0,0 +1,286 @@
+// Copyright 2014 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 "components/invalidation/invalidation_logger.h"
+#include "components/invalidation/invalidation_logger_observer.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace invalidation {
+
+class InvalidationLoggerObserverTest : public InvalidationLoggerObserver {
+ public:
+ InvalidationLoggerObserverTest() { ResetStates(); }
+
+ void ResetStates() {
+ registration_change_received = false;
+ state_received = false;
+ update_id_received = false;
+ debug_message_received = false;
+ invalidation_received = false;
+ detailed_status_received = false;
+ update_id_replicated = std::map<std::string, syncer::ObjectIdCountMap>();
+ registered_handlers = std::multiset<std::string>();
+ }
+
+ virtual void OnRegistrationChange(const std::multiset<std::string>& handlers)
+ OVERRIDE {
+ registered_handlers = handlers;
+ registration_change_received = true;
+ }
+
+ virtual void OnStateChange(const syncer::InvalidatorState& new_state,
+ const base::Time& last_change_timestamp)
+ OVERRIDE {
+ state_received = true;
+ }
+
+ virtual void OnUpdateIds(const std::string& handler,
+ const syncer::ObjectIdCountMap& details) OVERRIDE {
+ update_id_received = true;
+ update_id_replicated[handler] = details;
+ }
+
+ virtual void OnDebugMessage(const base::DictionaryValue& details) OVERRIDE {
+ debug_message_received = true;
+ }
+
+ virtual void OnInvalidation(
+ const syncer::ObjectIdInvalidationMap& new_invalidations) OVERRIDE {
+ invalidation_received = true;
+ }
+
+ virtual void OnDetailedStatus(const base::DictionaryValue& details) OVERRIDE {
+ detailed_status_received = true;
+ }
+
+ bool registration_change_received;
+ bool state_received;
+ bool update_id_received;
+ bool debug_message_received;
+ bool invalidation_received;
+ bool detailed_status_received;
+ std::map<std::string, syncer::ObjectIdCountMap> update_id_replicated;
+ std::multiset<std::string> registered_handlers;
+};
+
+// Test that the callbacks are actually being called when observers are
+// registered and don't produce any other callback in the meantime.
+TEST(InvalidationLoggerTest, TestCallbacks) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+
+ log.RegisterObserver(&observer_test);
+ log.OnStateChange(syncer::INVALIDATIONS_ENABLED);
+ EXPECT_TRUE(observer_test.state_received);
+ EXPECT_FALSE(observer_test.update_id_received);
+ EXPECT_FALSE(observer_test.registration_change_received);
+ EXPECT_FALSE(observer_test.invalidation_received);
+ EXPECT_FALSE(observer_test.debug_message_received);
+ EXPECT_FALSE(observer_test.detailed_status_received);
+
+ observer_test.ResetStates();
+
+ log.OnInvalidation(syncer::ObjectIdInvalidationMap());
+ EXPECT_TRUE(observer_test.invalidation_received);
+ EXPECT_FALSE(observer_test.state_received);
+ EXPECT_FALSE(observer_test.update_id_received);
+ EXPECT_FALSE(observer_test.registration_change_received);
+ EXPECT_FALSE(observer_test.debug_message_received);
+ EXPECT_FALSE(observer_test.detailed_status_received);
+
+ log.UnregisterObserver(&observer_test);
+}
+
+// Test that after registering an observer and then unregistering it
+// no callbacks regarding that observer are called.
+// (i.e. the observer is cleanly removed)
+TEST(InvalidationLoggerTest, TestReleaseOfObserver) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+
+ log.RegisterObserver(&observer_test);
+ log.UnregisterObserver(&observer_test);
+
+ log.OnInvalidation(syncer::ObjectIdInvalidationMap());
+ log.OnStateChange(syncer::INVALIDATIONS_ENABLED);
+ log.OnRegistration(std::string());
+ log.OnUnregistration(std::string());
+ log.OnDebugMessage(base::DictionaryValue());
+ log.OnUpdateIds(std::map<std::string, syncer::ObjectIdSet>());
+ EXPECT_FALSE(observer_test.registration_change_received);
+ EXPECT_FALSE(observer_test.update_id_received);
+ EXPECT_FALSE(observer_test.invalidation_received);
+ EXPECT_FALSE(observer_test.state_received);
+ EXPECT_FALSE(observer_test.debug_message_received);
+ EXPECT_FALSE(observer_test.detailed_status_received);
+}
+
+// Test the EmitContet in InvalidationLogger is actually
+// sending state and updateIds notifications.
+TEST(InvalidationLoggerTest, TestEmitContent) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+
+ log.RegisterObserver(&observer_test);
+ EXPECT_FALSE(observer_test.state_received);
+ EXPECT_FALSE(observer_test.update_id_received);
+ log.EmitContent();
+ // Expect state and registered handlers only because no Ids were registered.
+ EXPECT_TRUE(observer_test.state_received);
+ EXPECT_TRUE(observer_test.registration_change_received);
+ EXPECT_FALSE(observer_test.update_id_received);
+ EXPECT_FALSE(observer_test.invalidation_received);
+ EXPECT_FALSE(observer_test.debug_message_received);
+ EXPECT_FALSE(observer_test.detailed_status_received);
+
+ observer_test.ResetStates();
+ std::map<std::string, syncer::ObjectIdSet> test_map;
+ test_map["Test"] = syncer::ObjectIdSet();
+ log.OnUpdateIds(test_map);
+ EXPECT_TRUE(observer_test.update_id_received);
+ observer_test.ResetStates();
+
+ log.EmitContent();
+ // Expect now state, ids and registered handlers change.
+ EXPECT_TRUE(observer_test.state_received);
+ EXPECT_TRUE(observer_test.update_id_received);
+ EXPECT_TRUE(observer_test.registration_change_received);
+ EXPECT_FALSE(observer_test.invalidation_received);
+ EXPECT_FALSE(observer_test.debug_message_received);
+ EXPECT_FALSE(observer_test.detailed_status_received);
+ log.UnregisterObserver(&observer_test);
+}
+
+// Test that the updateId notification actually sends the same ObjectId that
+// was sent to the Observer.
+// The ObserverTest rebuilds the map that was sent in pieces by the logger.
+TEST(InvalidationLoggerTest, TestUpdateIdsMap) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+ std::map<std::string, syncer::ObjectIdSet> send_test_map;
+ std::map<std::string, syncer::ObjectIdCountMap> expected_received_map;
+ log.RegisterObserver(&observer_test);
+
+ syncer::ObjectIdSet sync_set_A;
+ syncer::ObjectIdCountMap counted_sync_set_A;
+
+ ObjectId o1(1000, "DataType1");
+ sync_set_A.insert(o1);
+ counted_sync_set_A[o1] = 0;
+
+ ObjectId o2(1000, "DataType2");
+ sync_set_A.insert(o2);
+ counted_sync_set_A[o2] = 0;
+
+ syncer::ObjectIdSet sync_set_B;
+ syncer::ObjectIdCountMap counted_sync_set_B;
+
+ ObjectId o3(1020, "DataTypeA");
+ sync_set_B.insert(o3);
+ counted_sync_set_B[o3] = 0;
+
+ send_test_map["TestA"] = sync_set_A;
+ send_test_map["TestB"] = sync_set_B;
+ expected_received_map["TestA"] = counted_sync_set_A;
+ expected_received_map["TestB"] = counted_sync_set_B;
+
+ // Send the objects ids registered for the two different handler name.
+ log.OnUpdateIds(send_test_map);
+ EXPECT_EQ(expected_received_map, observer_test.update_id_replicated);
+
+ syncer::ObjectIdSet sync_set_B2;
+ syncer::ObjectIdCountMap counted_sync_set_B2;
+
+ ObjectId o4(1020, "DataTypeF");
+ sync_set_B2.insert(o4);
+ counted_sync_set_B2[o4] = 0;
+
+ ObjectId o5(1020, "DataTypeG");
+ sync_set_B2.insert(o5);
+ counted_sync_set_B2[o5] = 0;
+
+ send_test_map["TestB"] = sync_set_B2;
+ expected_received_map["TestB"] = counted_sync_set_B2;
+
+ // Test now that if we replace the registered datatypes for TestB, the
+ // original don't show up again.
+ log.OnUpdateIds(send_test_map);
+ EXPECT_EQ(expected_received_map, observer_test.update_id_replicated);
+
+ // The emit content should return the same map too.
+ observer_test.ResetStates();
+ log.EmitContent();
+ EXPECT_EQ(expected_received_map, observer_test.update_id_replicated);
+ log.UnregisterObserver(&observer_test);
+}
+
+// Test that the invalidation notification changes the total count
+// of invalidations received for that datatype.
+TEST(InvalidationLoggerTest, TestInvalidtionsTotalCount) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+ log.RegisterObserver(&observer_test);
+
+ std::map<std::string, syncer::ObjectIdSet> send_test_map;
+ std::map<std::string, syncer::ObjectIdCountMap> expected_received_map;
+ syncer::ObjectIdSet sync_set;
+ syncer::ObjectIdCountMap counted_sync_set;
+
+ ObjectId o1(1020, "DataTypeA");
+ sync_set.insert(o1);
+ counted_sync_set[o1] = 1;
+
+ // Generate invalidation for datatype A only.
+ syncer::ObjectIdInvalidationMap fake_invalidations =
+ syncer::ObjectIdInvalidationMap::InvalidateAll(sync_set);
+
+ ObjectId o2(1040, "DataTypeB");
+ sync_set.insert(o2);
+ counted_sync_set[o2] = 0;
+
+ // Registed the two objectIds and send an invalidation only for the
+ // Datatype A.
+ send_test_map["Test"] = sync_set;
+ log.OnUpdateIds(send_test_map);
+ log.OnInvalidation(fake_invalidations);
+
+ expected_received_map["Test"] = counted_sync_set;
+
+ // Reset the state of the observer to receive the ObjectIds with the
+ // count of invalidations received (1 and 0).
+ observer_test.ResetStates();
+ log.EmitContent();
+ EXPECT_EQ(expected_received_map, observer_test.update_id_replicated);
+
+ log.UnregisterObserver(&observer_test);
+}
+
+// Test that registered handlers are being sent to the observers.
+TEST(InvalidationLoggerTest, TestRegisteredHandlers) {
+ InvalidationLogger log;
+ InvalidationLoggerObserverTest observer_test;
+ log.RegisterObserver(&observer_test);
+
+ log.OnRegistration(std::string("FakeHandler1"));
+ std::multiset<std::string> test_multiset;
+ test_multiset.insert("FakeHandler1");
+ EXPECT_TRUE(observer_test.registration_change_received);
+ EXPECT_EQ(observer_test.registered_handlers, test_multiset);
+
+ observer_test.ResetStates();
+ log.OnRegistration(std::string("FakeHandler2"));
+ test_multiset.insert("FakeHandler2");
+ EXPECT_TRUE(observer_test.registration_change_received);
+ EXPECT_EQ(observer_test.registered_handlers, test_multiset);
+
+ observer_test.ResetStates();
+ log.OnUnregistration(std::string("FakeHandler2"));
+ test_multiset.erase("FakeHandler2");
+ EXPECT_TRUE(observer_test.registration_change_received);
+ EXPECT_EQ(observer_test.registered_handlers, test_multiset);
+
+ log.UnregisterObserver(&observer_test);
+}
+} // namespace invalidation
diff --git a/components/invalidation/invalidation_service.h b/components/invalidation/invalidation_service.h
new file mode 100644
index 0000000..456d411
--- /dev/null
+++ b/components/invalidation/invalidation_service.h
@@ -0,0 +1,122 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_H_
+#define COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_H_
+
+#include "base/callback_forward.h"
+#include "components/keyed_service/core/keyed_service.h"
+#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/invalidator_state.h"
+
+class IdentityProvider;
+
+namespace syncer {
+class InvalidationHandler;
+} // namespace syncer
+
+namespace invalidation {
+class InvalidationLogger;
+
+// Interface for classes that handle invalidation registrations and send out
+// invalidations to register handlers.
+//
+// Invalidation clients should follow the pattern below:
+//
+// When starting the client:
+//
+// frontend->RegisterInvalidationHandler(client_handler);
+//
+// When the set of IDs to register changes for the client during its lifetime
+// (i.e., between calls to RegisterInvalidationHandler(client_handler) and
+// UnregisterInvalidationHandler(client_handler):
+//
+// frontend->UpdateRegisteredInvalidationIds(client_handler, client_ids);
+//
+// When shutting down the client for browser shutdown:
+//
+// frontend->UnregisterInvalidationHandler(client_handler);
+//
+// Note that there's no call to UpdateRegisteredIds() -- this is because the
+// invalidation API persists registrations across browser restarts.
+//
+// When permanently shutting down the client, e.g. when disabling the related
+// feature:
+//
+// frontend->UpdateRegisteredInvalidationIds(client_handler, ObjectIdSet());
+// frontend->UnregisterInvalidationHandler(client_handler);
+//
+// If an invalidation handler cares about the invalidator state, it should also
+// do the following when starting the client:
+//
+// invalidator_state = frontend->GetInvalidatorState();
+//
+// It can also do the above in OnInvalidatorStateChange(), or it can use the
+// argument to OnInvalidatorStateChange().
+//
+// It is an error to have registered handlers when an
+// InvalidationFrontend is shut down; clients must ensure that they
+// unregister themselves before then. (Depending on the
+// InvalidationFrontend, shutdown may be equivalent to destruction, or
+// a separate function call like Shutdown()).
+//
+// NOTE(akalin): Invalidations that come in during browser shutdown may get
+// dropped. This won't matter once we have an Acknowledge API, though: see
+// http://crbug.com/78462 and http://crbug.com/124149.
+//
+// This class inherits from ProfileKeyedService to make it possible to correctly
+// cast from various InvalidationService implementations to ProfileKeyedService
+// in InvalidationServiceFactory.
+class InvalidationService : public KeyedService {
+ public:
+ // Starts sending notifications to |handler|. |handler| must not be NULL,
+ // and it must not already be registered.
+ //
+ // Handler registrations are persisted across restarts of sync.
+ virtual void RegisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) = 0;
+
+ // Updates the set of ObjectIds associated with |handler|. |handler| must
+ // not be NULL, and must already be registered. An ID must be registered for
+ // at most one handler.
+ //
+ // Registered IDs are persisted across restarts of sync.
+ virtual void UpdateRegisteredInvalidationIds(
+ syncer::InvalidationHandler* handler,
+ const syncer::ObjectIdSet& ids) = 0;
+
+ // Stops sending notifications to |handler|. |handler| must not be NULL, and
+ // it must already be registered. Note that this doesn't unregister the IDs
+ // associated with |handler|.
+ //
+ // Handler registrations are persisted across restarts of sync.
+ virtual void UnregisterInvalidationHandler(
+ syncer::InvalidationHandler* handler) = 0;
+
+ // Returns the current invalidator state. When called from within
+ // InvalidationHandler::OnInvalidatorStateChange(), this must return
+ // the updated state.
+ virtual syncer::InvalidatorState GetInvalidatorState() const = 0;
+
+ // Returns the ID belonging to this invalidation client. Can be used to
+ // prevent the receipt of notifications of our own changes.
+ virtual std::string GetInvalidatorClientId() const = 0;
+
+ // Return the logger used to debug invalidations
+ virtual InvalidationLogger* GetInvalidationLogger() = 0;
+
+ // Triggers requests of internal status.
+ virtual void RequestDetailedStatus(
+ base::Callback<void(const base::DictionaryValue&)> post_caller) const = 0;
+
+ // Returns the identity provider.
+ virtual IdentityProvider* GetIdentityProvider() = 0;
+
+ protected:
+ virtual ~InvalidationService() { }
+};
+
+} // namespace invalidation
+
+#endif // COMPONENTS_INVALIDATION_INVALIDATION_SERVICE_H_
diff --git a/components/invalidation/ticl_settings_provider.cc b/components/invalidation/ticl_settings_provider.cc
new file mode 100644
index 0000000..dfe5dd0
--- /dev/null
+++ b/components/invalidation/ticl_settings_provider.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 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 "components/invalidation/ticl_settings_provider.h"
+
+namespace invalidation {
+
+TiclSettingsProvider::Observer::~Observer() {
+}
+
+TiclSettingsProvider::TiclSettingsProvider() {
+}
+
+TiclSettingsProvider::~TiclSettingsProvider() {
+}
+
+void TiclSettingsProvider::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void TiclSettingsProvider::RemoveObserver(Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void TiclSettingsProvider::FireOnUseGCMChannelChanged() {
+ FOR_EACH_OBSERVER(Observer, observers_, OnUseGCMChannelChanged());
+}
+
+} // namespace invalidation
diff --git a/components/invalidation/ticl_settings_provider.h b/components/invalidation/ticl_settings_provider.h
new file mode 100644
index 0000000..c62a4d0
--- /dev/null
+++ b/components/invalidation/ticl_settings_provider.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+#ifndef COMPONENTS_INVALIDATION_TICL_SETTINGS_PROVIDER_H_
+#define COMPONENTS_INVALIDATION_TICL_SETTINGS_PROVIDER_H_
+
+#include "base/macros.h"
+#include "base/observer_list.h"
+
+namespace invalidation {
+
+// Provides configuration settings to TiclInvalidationService and notifies it
+// when the settings change.
+class TiclSettingsProvider {
+ public:
+ class Observer {
+ public:
+ virtual void OnUseGCMChannelChanged() = 0;
+
+ protected:
+ virtual ~Observer();
+ };
+
+ TiclSettingsProvider();
+ virtual ~TiclSettingsProvider();
+
+ virtual bool UseGCMChannel() const = 0;
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ protected:
+ void FireOnUseGCMChannelChanged();
+
+ private:
+ ObserverList<Observer, true> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(TiclSettingsProvider);
+};
+
+} // namespace invalidation
+
+#endif // COMPONENTS_INVALIDATION_TICL_SETTINGS_PROVIDER_H_