summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync/invalidations/invalidator_storage.cc93
-rw-r--r--chrome/browser/sync/invalidations/invalidator_storage.h13
-rw-r--r--chrome/browser/sync/invalidations/invalidator_storage_unittest.cc209
-rw-r--r--sync/internal_api/public/base/invalidation.cc57
-rw-r--r--sync/internal_api/public/base/invalidation.h31
-rw-r--r--sync/internal_api/public/base/invalidation_test_util.cc55
-rw-r--r--sync/internal_api/public/base/invalidation_test_util.h4
-rw-r--r--sync/notifier/fake_invalidation_state_tracker.cc31
-rw-r--r--sync/notifier/fake_invalidation_state_tracker.h11
-rw-r--r--sync/notifier/invalidation_state_tracker.cc13
-rw-r--r--sync/notifier/invalidation_state_tracker.h44
-rw-r--r--sync/notifier/p2p_invalidator_unittest.cc6
-rw-r--r--sync/notifier/sync_invalidation_listener.cc15
-rw-r--r--sync/sync.gyp21
-rw-r--r--sync/tools/null_invalidation_state_tracker.cc66
-rw-r--r--sync/tools/null_invalidation_state_tracker.h40
-rw-r--r--sync/tools/sync_client.cc37
-rw-r--r--sync/tools/sync_listen_notifications.cc38
18 files changed, 631 insertions, 153 deletions
diff --git a/chrome/browser/sync/invalidations/invalidator_storage.cc b/chrome/browser/sync/invalidations/invalidator_storage.cc
index dd7dd9e..ebd6dbc 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage.cc
+++ b/chrome/browser/sync/invalidations/invalidator_storage.cc
@@ -5,9 +5,13 @@
#include "chrome/browser/sync/invalidations/invalidator_storage.h"
#include "base/base64.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/string_number_conversions.h"
+#include "base/task_runner.h"
#include "base/values.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/pref_names.h"
@@ -22,35 +26,53 @@ namespace {
const char kSourceKey[] = "source";
const char kNameKey[] = "name";
const char kMaxVersionKey[] = "max-version";
+const char kPayloadKey[] = "payload";
+const char kCurrentAckHandleKey[] = "current-ack";
+const char kExpectedAckHandleKey[] = "expected-ack";
bool ValueToObjectIdAndState(const DictionaryValue& value,
invalidation::ObjectId* id,
syncer::InvalidationState* state) {
std::string source_str;
- int source = 0;
- std::string name;
- std::string max_version_str;
if (!value.GetString(kSourceKey, &source_str)) {
DLOG(WARNING) << "Unable to deserialize source";
return false;
}
+ int source = 0;
+ if (!base::StringToInt(source_str, &source)) {
+ DLOG(WARNING) << "Invalid source: " << source_str;
+ return false;
+ }
+ std::string name;
if (!value.GetString(kNameKey, &name)) {
DLOG(WARNING) << "Unable to deserialize name";
return false;
}
+ *id = invalidation::ObjectId(source, name);
+ std::string max_version_str;
if (!value.GetString(kMaxVersionKey, &max_version_str)) {
DLOG(WARNING) << "Unable to deserialize max version";
return false;
}
- if (!base::StringToInt(source_str, &source)) {
- DLOG(WARNING) << "Invalid source: " << source_str;
- return false;
- }
if (!base::StringToInt64(max_version_str, &state->version)) {
DLOG(WARNING) << "Invalid max invalidation version: " << max_version_str;
return false;
}
- *id = invalidation::ObjectId(source, name);
+ value.GetString(kPayloadKey, &state->payload);
+ // The ack handle fields won't be set if upgrading from previous versions of
+ // Chrome.
+ const base::DictionaryValue* current_ack_handle_value = NULL;
+ if (value.GetDictionary(kCurrentAckHandleKey, &current_ack_handle_value)) {
+ state->current.ResetFromValue(*current_ack_handle_value);
+ }
+ const base::DictionaryValue* expected_ack_handle_value = NULL;
+ if (value.GetDictionary(kExpectedAckHandleKey, &expected_ack_handle_value)) {
+ state->expected.ResetFromValue(*expected_ack_handle_value);
+ } else {
+ // In this case, we should never have a valid current value set.
+ DCHECK(!state->current.IsValid());
+ state->current = syncer::AckHandle::InvalidAckHandle();
+ }
return true;
}
@@ -61,6 +83,11 @@ DictionaryValue* ObjectIdAndStateToValue(
value->SetString(kSourceKey, base::IntToString(id.source()));
value->SetString(kNameKey, id.name());
value->SetString(kMaxVersionKey, base::Int64ToString(state.version));
+ value->SetString(kPayloadKey, state.payload);
+ if (state.current.IsValid())
+ value->Set(kCurrentAckHandleKey, state.current.ToValue().release());
+ if (state.expected.IsValid())
+ value->Set(kExpectedAckHandleKey, state.expected.ToValue().release());
return value;
}
@@ -98,8 +125,10 @@ InvalidationStateMap InvalidatorStorage::GetAllInvalidationStates() const {
return state_map;
}
-void InvalidatorStorage::SetMaxVersion(const invalidation::ObjectId& id,
- int64 max_version) {
+void InvalidatorStorage::SetMaxVersionAndPayload(
+ const invalidation::ObjectId& id,
+ int64 max_version,
+ const std::string& payload) {
DCHECK(thread_checker_.CalledOnValidThread());
CHECK(pref_service_);
InvalidationStateMap state_map = GetAllInvalidationStates();
@@ -109,6 +138,7 @@ void InvalidatorStorage::SetMaxVersion(const invalidation::ObjectId& id,
return;
}
state_map[id].version = max_version;
+ state_map[id].payload = payload;
base::ListValue state_map_list;
SerializeToList(state_map, &state_map_list);
@@ -248,4 +278,47 @@ void InvalidatorStorage::Clear() {
pref_service_->ClearPref(prefs::kInvalidatorInvalidationState);
}
+void InvalidatorStorage::GenerateAckHandles(
+ const syncer::ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ const base::Callback<void(const syncer::AckHandleMap&)> callback) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(pref_service_);
+ InvalidationStateMap state_map = GetAllInvalidationStates();
+
+ syncer::AckHandleMap ack_handles;
+ for (syncer::ObjectIdSet::const_iterator it = ids.begin(); it != ids.end();
+ ++it) {
+ state_map[*it].expected = syncer::AckHandle::CreateUnique();
+ ack_handles.insert(std::make_pair(*it, state_map[*it].expected));
+ }
+
+ base::ListValue state_map_list;
+ SerializeToList(state_map, &state_map_list);
+ pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
+ state_map_list);
+
+ ignore_result(task_runner->PostTask(FROM_HERE,
+ base::Bind(callback, ack_handles)));
+}
+
+void InvalidatorStorage::Acknowledge(const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ CHECK(pref_service_);
+ InvalidationStateMap state_map = GetAllInvalidationStates();
+
+ InvalidationStateMap::iterator it = state_map.find(id);
+ // This could happen if the acknowledgement is delayed and Forget() has
+ // already been called.
+ if (it == state_map.end())
+ return;
+ it->second.current = ack_handle;
+
+ base::ListValue state_map_list;
+ SerializeToList(state_map, &state_map_list);
+ pref_service_->Set(prefs::kInvalidatorMaxInvalidationVersions,
+ state_map_list);
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/invalidations/invalidator_storage.h b/chrome/browser/sync/invalidations/invalidator_storage.h
index c0f480f..1916403 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage.h
+++ b/chrome/browser/sync/invalidations/invalidator_storage.h
@@ -43,12 +43,19 @@ class InvalidatorStorage : public base::SupportsWeakPtr<InvalidatorStorage>,
// InvalidationStateTracker implementation.
virtual syncer::InvalidationStateMap GetAllInvalidationStates() const
OVERRIDE;
- virtual void SetMaxVersion(const invalidation::ObjectId& id,
- int64 max_version) OVERRIDE;
+ virtual void SetMaxVersionAndPayload(const invalidation::ObjectId& id,
+ int64 max_version,
+ const std::string& payload) OVERRIDE;
virtual void Forget(const syncer::ObjectIdSet& ids) OVERRIDE;
// TODO(tim): These are not yet used. Bug 124140.
virtual void SetBootstrapData(const std::string& data) OVERRIDE;
virtual std::string GetBootstrapData() const OVERRIDE;
+ virtual void GenerateAckHandles(
+ const syncer::ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const syncer::AckHandleMap&)> callback) OVERRIDE;
+ virtual void Acknowledge(const invalidation::ObjectId& id,
+ const syncer::AckHandle& ack_handle) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest, SerializeEmptyMap);
@@ -61,6 +68,8 @@ class InvalidatorStorage : public base::SupportsWeakPtr<InvalidatorStorage>,
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest,
DeserializeFromEmptyList);
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest, DeserializeFromListBasic);
+ FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest,
+ DeserializeFromListMissingOptionalValues);
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest, DeserializeMapOutOfRange);
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest, DeserializeMapInvalidFormat);
FRIEND_TEST_ALL_PREFIXES(InvalidatorStorageTest,
diff --git a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc b/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc
index 850c574..8beb9a5 100644
--- a/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc
+++ b/chrome/browser/sync/invalidations/invalidator_storage_unittest.cc
@@ -5,11 +5,14 @@
#include "chrome/browser/sync/invalidations/invalidator_storage.h"
+#include "base/bind.h"
#include "base/message_loop.h"
+#include "base/message_loop_proxy.h"
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service.h"
+#include "sync/internal_api/public/base/invalidation_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -22,9 +25,17 @@ namespace {
const char kSourceKey[] = "source";
const char kNameKey[] = "name";
const char kMaxVersionKey[] = "max-version";
+const char kPayloadKey[] = "payload";
+const char kCurrentAckHandleKey[] = "current-ack";
+const char kExpectedAckHandleKey[] = "expected-ack";
const int kChromeSyncSourceId = 1004;
+void GenerateAckHandlesTestHelper(syncer::AckHandleMap* output,
+ const syncer::AckHandleMap& input) {
+ *output = input;
+}
+
} // namespace
class InvalidatorStorageTest : public testing::Test {
@@ -43,33 +54,35 @@ class InvalidatorStorageTest : public testing::Test {
const invalidation::ObjectId kAppNotificationsId_;
const invalidation::ObjectId kAutofillId_;
- private:
MessageLoop loop_;
};
-// Set max versions for various keys and verify that they are written and read
-// back correctly.
-TEST_F(InvalidatorStorageTest, MaxInvalidationVersions) {
+// Set invalidation states for various keys and verify that they are written and
+// read back correctly.
+TEST_F(InvalidatorStorageTest, SetMaxVersionAndPayload) {
InvalidatorStorage storage(&pref_service_);
- InvalidationStateMap expected_max_versions;
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ InvalidationStateMap expected_states;
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
- expected_max_versions[kBookmarksId_].version = 2;
- storage.SetMaxVersion(kBookmarksId_, 2);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ expected_states[kBookmarksId_].version = 2;
+ expected_states[kBookmarksId_].payload = "hello";
+ storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "hello");
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
- expected_max_versions[kPreferencesId_].version = 5;
- storage.SetMaxVersion(kPreferencesId_, 5);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ expected_states[kPreferencesId_].version = 5;
+ storage.SetMaxVersionAndPayload(kPreferencesId_, 5, std::string());
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
- expected_max_versions[kAppNotificationsId_].version = 3;
- storage.SetMaxVersion(kAppNotificationsId_, 3);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ expected_states[kAppNotificationsId_].version = 3;
+ expected_states[kAppNotificationsId_].payload = "world";
+ storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, "world");
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
- expected_max_versions[kAppNotificationsId_].version = 4;
- storage.SetMaxVersion(kAppNotificationsId_, 4);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ expected_states[kAppNotificationsId_].version = 4;
+ expected_states[kAppNotificationsId_].payload = "again";
+ storage.SetMaxVersionAndPayload(kAppNotificationsId_, 4, "again");
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
}
// Forgetting an entry should cause that entry to be deleted.
@@ -77,18 +90,20 @@ TEST_F(InvalidatorStorageTest, Forget) {
InvalidatorStorage storage(&pref_service_);
EXPECT_TRUE(storage.GetAllInvalidationStates().empty());
- InvalidationStateMap expected_max_versions;
- expected_max_versions[kBookmarksId_].version = 2;
- expected_max_versions[kPreferencesId_].version = 5;
- storage.SetMaxVersion(kBookmarksId_, 2);
- storage.SetMaxVersion(kPreferencesId_, 5);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ InvalidationStateMap expected_states;
+ expected_states[kBookmarksId_].version = 2;
+ expected_states[kBookmarksId_].payload = "a";
+ expected_states[kPreferencesId_].version = 5;
+ expected_states[kPreferencesId_].payload = "b";
+ storage.SetMaxVersionAndPayload(kBookmarksId_, 2, "a");
+ storage.SetMaxVersionAndPayload(kPreferencesId_, 5, "b");
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
- expected_max_versions.erase(kPreferencesId_);
+ expected_states.erase(kPreferencesId_);
syncer::ObjectIdSet to_forget;
to_forget.insert(kPreferencesId_);
storage.Forget(to_forget);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
}
// Clearing the storage should erase all version map entries and the bootstrap
@@ -101,10 +116,10 @@ TEST_F(InvalidatorStorageTest, Clear) {
storage.SetBootstrapData("test");
EXPECT_EQ("test", storage.GetBootstrapData());
{
- InvalidationStateMap expected_max_versions;
- expected_max_versions[kAppNotificationsId_].version = 3;
- storage.SetMaxVersion(kAppNotificationsId_, 3);
- EXPECT_EQ(expected_max_versions, storage.GetAllInvalidationStates());
+ InvalidationStateMap expected_states;
+ expected_states[kAppNotificationsId_].version = 3;
+ storage.SetMaxVersionAndPayload(kAppNotificationsId_, 3, std::string());
+ EXPECT_EQ(expected_states, storage.GetAllInvalidationStates());
}
storage.Clear();
@@ -227,28 +242,82 @@ TEST_F(InvalidatorStorageTest, DeserializeFromEmptyList) {
EXPECT_TRUE(map.empty());
}
-// Tests that deserializing a well-formed value results in the expected version
+// Tests that deserializing a well-formed value results in the expected state
// map.
TEST_F(InvalidatorStorageTest, DeserializeFromListBasic) {
InvalidationStateMap map;
base::ListValue list;
DictionaryValue* value;
+ syncer::AckHandle ack_handle_1 = syncer::AckHandle::CreateUnique();
+ syncer::AckHandle ack_handle_2 = syncer::AckHandle::CreateUnique();
+
+ value = new DictionaryValue();
+ value->SetString(kSourceKey,
+ base::IntToString(kAppNotificationsId_.source()));
+ value->SetString(kNameKey, kAppNotificationsId_.name());
+ value->SetString(kMaxVersionKey, "20");
+ value->SetString(kPayloadKey, "testing");
+ value->Set(kCurrentAckHandleKey, ack_handle_1.ToValue().release());
+ value->Set(kExpectedAckHandleKey, ack_handle_2.ToValue().release());
+ list.Append(value);
+
+ InvalidatorStorage::DeserializeFromList(list, &map);
+ EXPECT_EQ(1U, map.size());
+ EXPECT_EQ(20, map[kAppNotificationsId_].version);
+ EXPECT_EQ("testing", map[kAppNotificationsId_].payload);
+ EXPECT_THAT(map[kAppNotificationsId_].current, Eq(ack_handle_1));
+ EXPECT_THAT(map[kAppNotificationsId_].expected, Eq(ack_handle_2));
+}
+
+// Tests that deserializing well-formed values when optional parameters are
+// omitted works.
+TEST_F(InvalidatorStorageTest, DeserializeFromListMissingOptionalValues) {
+ InvalidationStateMap map;
+ base::ListValue list;
+ DictionaryValue* value;
+ syncer::AckHandle ack_handle = syncer::AckHandle::CreateUnique();
+ // Payload missing because of an upgrade from a previous browser version that
+ // didn't set the field.
value = new DictionaryValue();
value->SetString(kSourceKey, base::IntToString(kAutofillId_.source()));
value->SetString(kNameKey, kAutofillId_.name());
value->SetString(kMaxVersionKey, "10");
list.Append(value);
+ // A crash between SetMaxVersion() and a callback from GenerateAckHandles()
+ // could result in this state.
value = new DictionaryValue();
value->SetString(kSourceKey, base::IntToString(kBookmarksId_.source()));
value->SetString(kNameKey, kBookmarksId_.name());
value->SetString(kMaxVersionKey, "15");
+ value->SetString(kPayloadKey, "hello");
+ list.Append(value);
+ // Never acknowledged, so current ack handle is unset.
+ value = new DictionaryValue();
+ value->SetString(kSourceKey, base::IntToString(kPreferencesId_.source()));
+ value->SetString(kNameKey, kPreferencesId_.name());
+ value->SetString(kMaxVersionKey, "20");
+ value->SetString(kPayloadKey, "world");
+ value->Set(kExpectedAckHandleKey, ack_handle.ToValue().release());
list.Append(value);
InvalidatorStorage::DeserializeFromList(list, &map);
- EXPECT_EQ(2U, map.size());
+ EXPECT_EQ(3U, map.size());
+
EXPECT_EQ(10, map[kAutofillId_].version);
+ EXPECT_EQ("", map[kAutofillId_].payload);
+ EXPECT_FALSE(map[kAutofillId_].current.IsValid());
+ EXPECT_FALSE(map[kAutofillId_].expected.IsValid());
+
EXPECT_EQ(15, map[kBookmarksId_].version);
+ EXPECT_EQ("hello", map[kBookmarksId_].payload);
+ EXPECT_FALSE(map[kBookmarksId_].current.IsValid());
+ EXPECT_FALSE(map[kBookmarksId_].expected.IsValid());
+
+ EXPECT_EQ(20, map[kPreferencesId_].version);
+ EXPECT_EQ("world", map[kPreferencesId_].payload);
+ EXPECT_FALSE(map[kPreferencesId_].current.IsValid());
+ EXPECT_THAT(map[kPreferencesId_].expected, Eq(ack_handle));
}
// Tests for legacy deserialization code.
@@ -340,4 +409,80 @@ TEST_F(InvalidatorStorageTest, SetGetBootstrapData) {
EXPECT_EQ(mess, storage.GetBootstrapData());
}
+// Test that we correctly generate ack handles, acknowledge them, and persist
+// them.
+TEST_F(InvalidatorStorageTest, GenerateAckHandlesAndAcknowledge) {
+ InvalidatorStorage storage(&pref_service_);
+ syncer::ObjectIdSet ids;
+ InvalidationStateMap state_map;
+ syncer::AckHandleMap ack_handle_map;
+ syncer::AckHandleMap::const_iterator it;
+
+ // Test that it works as expected if the key doesn't already exist in the map,
+ // e.g. the first invalidation received for the object ID was not for a
+ // specific version.
+ ids.insert(kAutofillId_);
+ storage.GenerateAckHandles(
+ ids, base::MessageLoopProxy::current(),
+ base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
+ loop_.RunUntilIdle();
+ EXPECT_EQ(1U, ack_handle_map.size());
+ it = ack_handle_map.find(kAutofillId_);
+ // Android STL appears to be buggy and causes gtest's IsContainerTest<> to
+ // treat an iterator as a STL container so we use != instead of ASSERT_NE.
+ ASSERT_TRUE(ack_handle_map.end() != it);
+ EXPECT_TRUE(it->second.IsValid());
+ state_map[kAutofillId_].expected = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+
+ storage.Acknowledge(kAutofillId_, it->second);
+ state_map[kAutofillId_].current = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+
+ ids.clear();
+
+ // Test that it works as expected if the key already exists.
+ state_map[kBookmarksId_].version = 11;
+ state_map[kBookmarksId_].payload = "hello";
+ storage.SetMaxVersionAndPayload(kBookmarksId_, 11, "hello");
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+ ids.insert(kBookmarksId_);
+ storage.GenerateAckHandles(
+ ids, base::MessageLoopProxy::current(),
+ base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
+ loop_.RunUntilIdle();
+ EXPECT_EQ(1U, ack_handle_map.size());
+ it = ack_handle_map.find(kBookmarksId_);
+ ASSERT_TRUE(ack_handle_map.end() != it);
+ EXPECT_TRUE(it->second.IsValid());
+ state_map[kBookmarksId_].expected = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+
+ storage.Acknowledge(kBookmarksId_, it->second);
+ state_map[kBookmarksId_].current = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+
+ // Finally, test that the ack handles are updated if we're asked to generate
+ // another ack handle for the same object ID.
+ state_map[kBookmarksId_].version = 12;
+ state_map[kBookmarksId_].payload = "world";
+ storage.SetMaxVersionAndPayload(kBookmarksId_, 12, "world");
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+ ids.insert(kBookmarksId_);
+ storage.GenerateAckHandles(
+ ids, base::MessageLoopProxy::current(),
+ base::Bind(&GenerateAckHandlesTestHelper, &ack_handle_map));
+ loop_.RunUntilIdle();
+ EXPECT_EQ(1U, ack_handle_map.size());
+ it = ack_handle_map.find(kBookmarksId_);
+ ASSERT_TRUE(ack_handle_map.end() != it);
+ EXPECT_TRUE(it->second.IsValid());
+ state_map[kBookmarksId_].expected = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+
+ storage.Acknowledge(kBookmarksId_, it->second);
+ state_map[kBookmarksId_].current = it->second;
+ EXPECT_EQ(state_map, storage.GetAllInvalidationStates());
+}
+
} // namespace browser_sync
diff --git a/sync/internal_api/public/base/invalidation.cc b/sync/internal_api/public/base/invalidation.cc
index 2ddaa63..58f5cce 100644
--- a/sync/internal_api/public/base/invalidation.cc
+++ b/sync/internal_api/public/base/invalidation.cc
@@ -4,22 +4,67 @@
#include "sync/internal_api/public/base/invalidation.h"
+#include <cstddef>
+#include "base/rand_util.h"
+#include "base/string_number_conversions.h"
#include "base/values.h"
namespace syncer {
+namespace {
+// Hopefully enough bytes for uniqueness.
+const size_t kBytesInHandle = 16;
+} // namespace
+
+AckHandle AckHandle::CreateUnique() {
+ // This isn't a valid UUID, so we don't attempt to format it like one.
+ uint8 random_bytes[kBytesInHandle];
+ base::RandBytes(random_bytes, sizeof(random_bytes));
+ return AckHandle(base::HexEncode(random_bytes, sizeof(random_bytes)),
+ base::Time::Now());
+}
+
+AckHandle AckHandle::InvalidAckHandle() {
+ return AckHandle(std::string(), base::Time());
+}
+
bool AckHandle::Equals(const AckHandle& other) const {
- return true;
+ return state_ == other.state_ && timestamp_ == other.timestamp_;
}
-scoped_ptr<base::Value> AckHandle::ToValue() const {
- return scoped_ptr<base::Value>(new DictionaryValue());
+scoped_ptr<base::DictionaryValue> AckHandle::ToValue() const {
+ scoped_ptr<DictionaryValue> value(new DictionaryValue());
+ value->SetString("state", state_);
+ value->SetString("timestamp",
+ base::Int64ToString(timestamp_.ToInternalValue()));
+ return value.Pass();
}
-bool AckHandle::ResetFromValue(const base::Value& value) {
+bool AckHandle::ResetFromValue(const base::DictionaryValue& value) {
+ if (!value.GetString("state", &state_))
+ return false;
+ std::string timestamp_as_string;
+ if (!value.GetString("timestamp", &timestamp_as_string))
+ return false;
+ int64 timestamp_value;
+ if (!base::StringToInt64(timestamp_as_string, &timestamp_value))
+ return false;
+ timestamp_ = base::Time::FromInternalValue(timestamp_value);
return true;
}
+bool AckHandle::IsValid() const {
+ return !state_.empty();
+}
+
+AckHandle::AckHandle(const std::string& state, base::Time timestamp)
+ : state_(state), timestamp_(timestamp) {
+}
+
+Invalidation::Invalidation()
+ : ack_handle(AckHandle::InvalidAckHandle()) {
+}
+
bool Invalidation::Equals(const Invalidation& other) const {
return (payload == other.payload) && ack_handle.Equals(other.ack_handle);
}
@@ -32,10 +77,10 @@ scoped_ptr<base::DictionaryValue> Invalidation::ToValue() const {
}
bool Invalidation::ResetFromValue(const base::DictionaryValue& value) {
- const base::Value* ack_handle_value = NULL;
+ const DictionaryValue* ack_handle_value = NULL;
return
value.GetString("payload", &payload) &&
- value.Get("ackHandle", &ack_handle_value) &&
+ value.GetDictionary("ackHandle", &ack_handle_value) &&
ack_handle.ResetFromValue(*ack_handle_value);
}
diff --git a/sync/internal_api/public/base/invalidation.h b/sync/internal_api/public/base/invalidation.h
index fc8c361c..f25304b 100644
--- a/sync/internal_api/public/base/invalidation.h
+++ b/sync/internal_api/public/base/invalidation.h
@@ -7,25 +7,36 @@
#include <string>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
+#include "base/time.h"
namespace base {
class DictionaryValue;
-class Value;
} // namespace
namespace syncer {
-// Opaque class that represents an ack handle.
-// TODO(dcheng): This is just a refactoring change, so the class is empty for
-// the moment. It will be filled once we start implementing 'reminders'.
+// Opaque class that represents a local ack handle. We don't reuse the
+// invalidation ack handles to avoid unnecessary dependencies.
class AckHandle {
public:
+ static AckHandle CreateUnique();
+ static AckHandle InvalidAckHandle();
+
bool Equals(const AckHandle& other) const;
- scoped_ptr<base::Value> ToValue() const;
+ scoped_ptr<base::DictionaryValue> ToValue() const;
+ bool ResetFromValue(const base::DictionaryValue& value);
+
+ bool IsValid() const;
+
+ private:
+ // Explicitly copyable and assignable for STL containers.
+ AckHandle(const std::string& state, base::Time timestamp);
- bool ResetFromValue(const base::Value& value);
+ std::string state_;
+ base::Time timestamp_;
};
// Represents a local invalidation, and is roughly analogous to
@@ -34,15 +45,15 @@ class AckHandle {
// acknowledge receipt of the invalidation. It does not embed the object ID,
// since it is typically associated with it through ObjectIdInvalidationMap.
struct Invalidation {
- std::string payload;
- AckHandle ack_handle;
+ Invalidation();
bool Equals(const Invalidation& other) const;
- // Caller owns the returned DictionaryValue.
scoped_ptr<base::DictionaryValue> ToValue() const;
-
bool ResetFromValue(const base::DictionaryValue& value);
+
+ std::string payload;
+ AckHandle ack_handle;
};
} // namespace syncer
diff --git a/sync/internal_api/public/base/invalidation_test_util.cc b/sync/internal_api/public/base/invalidation_test_util.cc
index a95b657..3f3910b 100644
--- a/sync/internal_api/public/base/invalidation_test_util.cc
+++ b/sync/internal_api/public/base/invalidation_test_util.cc
@@ -5,6 +5,9 @@
#include "sync/internal_api/public/base/invalidation_test_util.h"
#include "base/basictypes.h"
+#include "base/json/json_writer.h"
+#include "base/json/string_escape.h"
+#include "base/values.h"
#include "sync/internal_api/public/base/invalidation.h"
namespace syncer {
@@ -17,6 +20,39 @@ using ::testing::PrintToString;
namespace {
+class AckHandleEqMatcher
+ : public MatcherInterface<const AckHandle&> {
+ public:
+ explicit AckHandleEqMatcher(const AckHandle& expected);
+
+ virtual bool MatchAndExplain(const AckHandle& actual,
+ MatchResultListener* listener) const;
+ virtual void DescribeTo(::std::ostream* os) const;
+ virtual void DescribeNegationTo(::std::ostream* os) const;
+
+ private:
+ const AckHandle expected_;
+
+ DISALLOW_COPY_AND_ASSIGN(AckHandleEqMatcher);
+};
+
+AckHandleEqMatcher::AckHandleEqMatcher(const AckHandle& expected)
+ : expected_(expected) {
+}
+
+bool AckHandleEqMatcher::MatchAndExplain(const AckHandle& actual,
+ MatchResultListener* listener) const {
+ return expected_.Equals(actual);
+}
+
+void AckHandleEqMatcher::DescribeTo(::std::ostream* os) const {
+ *os << " is equal to " << PrintToString(expected_);
+}
+
+void AckHandleEqMatcher::DescribeNegationTo(::std::ostream* os) const {
+ *os << " isn't equal to " << PrintToString(expected_);
+}
+
class InvalidationEqMatcher
: public MatcherInterface<const Invalidation&> {
public:
@@ -52,8 +88,23 @@ void InvalidationEqMatcher::DescribeNegationTo(::std::ostream* os) const {
} // namespace
-void PrintTo(const Invalidation& invalidation, ::std::ostream* os) {
- *os << "{ payload: " << invalidation.payload << " }";
+void PrintTo(const AckHandle& ack_handle, ::std::ostream* os ) {
+ scoped_ptr<base::Value> value(ack_handle.ToValue());
+ std::string printable_ack_handle;
+ base::JSONWriter::Write(value.get(), &printable_ack_handle);
+ *os << "{ ack_handle: " << printable_ack_handle << " }";
+}
+
+Matcher<const AckHandle&> Eq(const AckHandle& expected) {
+ return MakeMatcher(new AckHandleEqMatcher(expected));
+}
+
+void PrintTo(const Invalidation& state, ::std::ostream* os) {
+ std::string printable_payload;
+ base::JsonDoubleQuote(state.payload,
+ true /* put_in_quotes */,
+ &printable_payload);
+ *os << "{ payload: " << printable_payload << " }";
}
Matcher<const Invalidation&> Eq(const Invalidation& expected) {
diff --git a/sync/internal_api/public/base/invalidation_test_util.h b/sync/internal_api/public/base/invalidation_test_util.h
index 694081d..9376a28 100644
--- a/sync/internal_api/public/base/invalidation_test_util.h
+++ b/sync/internal_api/public/base/invalidation_test_util.h
@@ -11,8 +11,12 @@
namespace syncer {
+class AckHandle;
struct Invalidation;
+void PrintTo(const AckHandle& ack_handle, ::std::ostream* os);
+::testing::Matcher<const AckHandle&> Eq(const AckHandle& expected);
+
void PrintTo(const Invalidation& invalidation, ::std::ostream* os);
::testing::Matcher<const Invalidation&> Eq(const Invalidation& expected);
diff --git a/sync/notifier/fake_invalidation_state_tracker.cc b/sync/notifier/fake_invalidation_state_tracker.cc
index 9073e45b..2af5db5 100644
--- a/sync/notifier/fake_invalidation_state_tracker.cc
+++ b/sync/notifier/fake_invalidation_state_tracker.cc
@@ -4,6 +4,10 @@
#include "sync/notifier/fake_invalidation_state_tracker.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace syncer {
@@ -25,8 +29,10 @@ FakeInvalidationStateTracker::GetAllInvalidationStates() const {
return state_map_;
}
-void FakeInvalidationStateTracker::SetMaxVersion(
- const invalidation::ObjectId& id, int64 max_version) {
+void FakeInvalidationStateTracker::SetMaxVersionAndPayload(
+ const invalidation::ObjectId& id,
+ int64 max_version,
+ const std::string& payload) {
InvalidationStateMap::const_iterator it = state_map_.find(id);
if ((it != state_map_.end()) && (max_version <= it->second.version)) {
ADD_FAILURE();
@@ -50,4 +56,25 @@ std::string FakeInvalidationStateTracker::GetBootstrapData() const {
return bootstrap_data_;
}
+void FakeInvalidationStateTracker::GenerateAckHandles(
+ const ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const AckHandleMap&)> callback) {
+ AckHandleMap ack_handles;
+ for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+ state_map_[*it].expected = AckHandle::CreateUnique();
+ ack_handles.insert(std::make_pair(*it, state_map_[*it].expected));
+ }
+ if (!task_runner->PostTask(FROM_HERE, base::Bind(callback, ack_handles)))
+ ADD_FAILURE();
+}
+
+void FakeInvalidationStateTracker::Acknowledge(const invalidation::ObjectId& id,
+ const AckHandle& ack_handle) {
+ InvalidationStateMap::iterator it = state_map_.find(id);
+ if (it == state_map_.end())
+ ADD_FAILURE();
+ it->second.current = ack_handle;
+}
+
} // namespace syncer
diff --git a/sync/notifier/fake_invalidation_state_tracker.h b/sync/notifier/fake_invalidation_state_tracker.h
index bd9003b..a3ea0bf 100644
--- a/sync/notifier/fake_invalidation_state_tracker.h
+++ b/sync/notifier/fake_invalidation_state_tracker.h
@@ -23,11 +23,18 @@ class FakeInvalidationStateTracker
// InvalidationStateTracker implementation.
virtual InvalidationStateMap GetAllInvalidationStates() const OVERRIDE;
- virtual void SetMaxVersion(const invalidation::ObjectId& id,
- int64 max_version) OVERRIDE;
+ virtual void SetMaxVersionAndPayload(const invalidation::ObjectId& id,
+ int64 max_version,
+ const std::string& payload) OVERRIDE;
virtual void Forget(const ObjectIdSet& ids) OVERRIDE;
virtual void SetBootstrapData(const std::string& data) OVERRIDE;
virtual std::string GetBootstrapData() const OVERRIDE;
+ virtual void GenerateAckHandles(
+ const ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const AckHandleMap&)> callback) OVERRIDE;
+ virtual void Acknowledge(const invalidation::ObjectId& id,
+ const AckHandle& ack_handle) OVERRIDE;
static const int64 kMinVersion;
diff --git a/sync/notifier/invalidation_state_tracker.cc b/sync/notifier/invalidation_state_tracker.cc
index 9d21807..335f3b2 100644
--- a/sync/notifier/invalidation_state_tracker.cc
+++ b/sync/notifier/invalidation_state_tracker.cc
@@ -6,8 +6,19 @@
namespace syncer {
+InvalidationState::InvalidationState()
+ : version(kint64min),
+ expected(AckHandle::InvalidAckHandle()),
+ current(AckHandle::InvalidAckHandle()) {
+}
+
+InvalidationState::~InvalidationState() {
+}
+
bool operator==(const InvalidationState& lhs, const InvalidationState& rhs) {
- return lhs.version == rhs.version;
+ return lhs.version == rhs.version &&
+ lhs.expected.Equals(rhs.expected) &&
+ lhs.current.Equals(rhs.current);
}
} // namespace syncer
diff --git a/sync/notifier/invalidation_state_tracker.h b/sync/notifier/invalidation_state_tracker.h
index 259ac83..2f26895 100644
--- a/sync/notifier/invalidation_state_tracker.h
+++ b/sync/notifier/invalidation_state_tracker.h
@@ -2,22 +2,40 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-// An InvalidationVersionTracker is an interface that handles getting
-// and setting (persisting) max invalidation versions.
+// An InvalidationStateTracker is an interface that handles persisting state
+// needed for invalidations. Currently, it is responsible for managing the
+// following information:
+// - Max version seen from the invalidation server to help dedupe invalidations.
+// - Bootstrap data for the invalidation client.
+// - Payloads and locally generated ack handles, to support local acking.
#ifndef SYNC_NOTIFIER_INVALIDATION_STATE_TRACKER_H_
#define SYNC_NOTIFIER_INVALIDATION_STATE_TRACKER_H_
#include <map>
+#include <string>
#include "base/basictypes.h"
+#include "base/callback_forward.h"
+#include "base/memory/ref_counted.h"
#include "google/cacheinvalidation/include/types.h"
+#include "sync/internal_api/public/base/invalidation.h"
#include "sync/notifier/invalidation_util.h"
+namespace base {
+class TaskRunner;
+} // namespace base
+
namespace syncer {
struct InvalidationState {
+ InvalidationState();
+ ~InvalidationState();
+
int64 version;
+ std::string payload;
+ AckHandle expected;
+ AckHandle current;
};
// TODO(dcheng): Remove this in favor of adding an Equals() method.
@@ -25,6 +43,8 @@ bool operator==(const InvalidationState& lhs, const InvalidationState& rhs);
typedef std::map<invalidation::ObjectId, InvalidationState, ObjectIdLessThan>
InvalidationStateMap;
+typedef std::map<invalidation::ObjectId, AckHandle, ObjectIdLessThan>
+ AckHandleMap;
class InvalidationStateTracker {
public:
@@ -34,8 +54,9 @@ class InvalidationStateTracker {
// |max_version| should be strictly greater than any existing max
// version for |model_type|.
- virtual void SetMaxVersion(const invalidation::ObjectId& id,
- int64 max_version) = 0;
+ virtual void SetMaxVersionAndPayload(const invalidation::ObjectId& id,
+ int64 max_version,
+ const std::string& payload) = 0;
// Removes all state tracked for |ids|.
virtual void Forget(const ObjectIdSet& ids) = 0;
@@ -46,6 +67,21 @@ class InvalidationStateTracker {
virtual void SetBootstrapData(const std::string& data) = 0;
virtual std::string GetBootstrapData() const = 0;
+ // Used for generating our own local ack handles. Generates a new ack handle
+ // for each object id in |ids|. The result is returned via |callback| posted
+ // to |task_runner|.
+ virtual void GenerateAckHandles(
+ const ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const AckHandleMap&)> callback) = 0;
+
+ // Records an acknowledgement for |id|. Note that no attempt at ordering is
+ // made. Acknowledge() only records the last ack_handle it received, even if
+ // the last ack_handle it received was generated before the value currently
+ // recorded.
+ virtual void Acknowledge(const invalidation::ObjectId& id,
+ const AckHandle& ack_handle) = 0;
+
protected:
virtual ~InvalidationStateTracker() {}
};
diff --git a/sync/notifier/p2p_invalidator_unittest.cc b/sync/notifier/p2p_invalidator_unittest.cc
index 6be2c21..e8a1b86 100644
--- a/sync/notifier/p2p_invalidator_unittest.cc
+++ b/sync/notifier/p2p_invalidator_unittest.cc
@@ -194,9 +194,11 @@ TEST_F(P2PInvalidatorTest, P2PNotificationDataNonDefault) {
EXPECT_EQ(
"{\"idInvalidationMap\":["
"{\"objectId\":{\"name\":\"BOOKMARK\",\"source\":1004},"
- "\"state\":{\"ackHandle\":{},\"payload\":\"\"}},"
+ "\"state\":{\"ackHandle\":{\"state\":\"\",\"timestamp\":\"0\"},"
+ "\"payload\":\"\"}},"
"{\"objectId\":{\"name\":\"THEME\",\"source\":1004},"
- "\"state\":{\"ackHandle\":{},\"payload\":\"\"}}"
+ "\"state\":{\"ackHandle\":{\"state\":\"\",\"timestamp\":\"0\"},"
+ "\"payload\":\"\"}}"
"],\"notificationType\":\"notifyAll\","
"\"senderId\":\"sender\",\"source\":1}", notification_data_str);
diff --git a/sync/notifier/sync_invalidation_listener.cc b/sync/notifier/sync_invalidation_listener.cc
index 1b23501..e84bc38 100644
--- a/sync/notifier/sync_invalidation_listener.cc
+++ b/sync/notifier/sync_invalidation_listener.cc
@@ -148,19 +148,20 @@ void SyncInvalidationListener::Invalidate(
client->Acknowledge(ack_handle);
return;
}
- DVLOG(2) << "Setting max invalidation version for " << ObjectIdToString(id)
- << " to " << invalidation.version();
- invalidation_state_map_[id].version = invalidation.version();
- invalidation_state_tracker_.Call(
- FROM_HERE,
- &InvalidationStateTracker::SetMaxVersion,
- id, invalidation.version());
std::string payload;
// payload() CHECK()'s has_payload(), so we must check it ourselves first.
if (invalidation.has_payload())
payload = invalidation.payload();
+ DVLOG(2) << "Setting max invalidation version for " << ObjectIdToString(id)
+ << " to " << invalidation.version();
+ invalidation_state_map_[id].version = invalidation.version();
+ invalidation_state_tracker_.Call(
+ FROM_HERE,
+ &InvalidationStateTracker::SetMaxVersionAndPayload,
+ id, invalidation.version(), payload);
+
ObjectIdInvalidationMap invalidation_map;
invalidation_map[id].payload = payload;
EmitInvalidation(invalidation_map);
diff --git a/sync/sync.gyp b/sync/sync.gyp
index 6a2bf58..af859d1 100644
--- a/sync/sync.gyp
+++ b/sync/sync.gyp
@@ -921,6 +921,25 @@
'conditions': [
['OS != "ios"', {
'targets': [
+ {
+ 'target_name': 'sync_tools_helper',
+ 'type': 'static_library',
+ 'include_dirs': [
+ '..',
+ ],
+ 'dependencies': [
+ '../base/base.gyp:base',
+ 'sync_notifier',
+ ],
+ 'export_dependent_settings': [
+ '../base/base.gyp:base',
+ 'sync_notifier',
+ ],
+ 'sources': [
+ 'tools/null_invalidation_state_tracker.cc',
+ 'tools/null_invalidation_state_tracker.h',
+ ],
+ },
# A tool to listen to sync notifications and print them out.
{
'target_name': 'sync_listen_notifications',
@@ -931,6 +950,7 @@
'../net/net.gyp:net',
'../net/net.gyp:net_test_support',
'sync',
+ 'sync_tools_helper',
],
'sources': [
'tools/sync_listen_notifications.cc',
@@ -950,6 +970,7 @@
'../net/net.gyp:net',
'../net/net.gyp:net_test_support',
'sync',
+ 'sync_tools_helper',
],
'sources': [
'tools/sync_client.cc',
diff --git a/sync/tools/null_invalidation_state_tracker.cc b/sync/tools/null_invalidation_state_tracker.cc
new file mode 100644
index 0000000..5eb5f78
--- /dev/null
+++ b/sync/tools/null_invalidation_state_tracker.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2012 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 "sync/tools/null_invalidation_state_tracker.h"
+
+#include "base/base64.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/task_runner.h"
+#include "sync/notifier/invalidation_util.h"
+
+namespace syncer {
+
+NullInvalidationStateTracker::NullInvalidationStateTracker() {}
+NullInvalidationStateTracker::~NullInvalidationStateTracker() {}
+
+InvalidationStateMap
+NullInvalidationStateTracker::GetAllInvalidationStates() const {
+ return InvalidationStateMap();
+}
+
+void NullInvalidationStateTracker::SetMaxVersionAndPayload(
+ const invalidation::ObjectId& id,
+ int64 max_invalidation_version,
+ const std::string& payload) {
+ LOG(INFO) << "Setting max invalidation version for "
+ << ObjectIdToString(id) << " to " << max_invalidation_version
+ << " with payload " << payload;
+}
+
+void NullInvalidationStateTracker::Forget(const ObjectIdSet& ids) {
+ for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+ LOG(INFO) << "Forgetting invalidation state for " << ObjectIdToString(*it);
+ }
+}
+
+std::string NullInvalidationStateTracker::GetBootstrapData() const {
+ return std::string();
+}
+
+void NullInvalidationStateTracker::SetBootstrapData(const std::string& data) {
+ std::string base64_data;
+ CHECK(base::Base64Encode(data, &base64_data));
+ LOG(INFO) << "Setting bootstrap data to: " << base64_data;
+}
+
+void NullInvalidationStateTracker::GenerateAckHandles(
+ const ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const AckHandleMap&)> callback) {
+ AckHandleMap ack_handles;
+ for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+ ack_handles.insert(std::make_pair(*it, AckHandle::InvalidAckHandle()));
+ }
+ CHECK(task_runner->PostTask(FROM_HERE, base::Bind(callback, ack_handles)));
+}
+
+void NullInvalidationStateTracker::Acknowledge(const invalidation::ObjectId& id,
+ const AckHandle& ack_handle) {
+ LOG(INFO) << "Received ack for " << ObjectIdToString(id);
+}
+
+} // namespace syncer
diff --git a/sync/tools/null_invalidation_state_tracker.h b/sync/tools/null_invalidation_state_tracker.h
new file mode 100644
index 0000000..13e55c7
--- /dev/null
+++ b/sync/tools/null_invalidation_state_tracker.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 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 SYNC_TOOLS_NULL_INVALIDATION_STATE_TRACKER_H_
+#define SYNC_TOOLS_NULL_INVALIDATION_STATE_TRACKER_H_
+
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "sync/notifier/invalidation_state_tracker.h"
+
+namespace syncer {
+
+class NullInvalidationStateTracker
+ : public base::SupportsWeakPtr<NullInvalidationStateTracker>,
+ public InvalidationStateTracker {
+ public:
+ NullInvalidationStateTracker();
+ virtual ~NullInvalidationStateTracker();
+
+ virtual InvalidationStateMap GetAllInvalidationStates() const OVERRIDE;
+ virtual void SetMaxVersionAndPayload(const invalidation::ObjectId& id,
+ int64 max_invalidation_version,
+ const std::string& payload) OVERRIDE;
+ virtual void Forget(const ObjectIdSet& ids) OVERRIDE;
+
+ virtual std::string GetBootstrapData() const OVERRIDE;
+ virtual void SetBootstrapData(const std::string& data) OVERRIDE;
+
+ virtual void GenerateAckHandles(
+ const ObjectIdSet& ids,
+ const scoped_refptr<base::TaskRunner>& task_runner,
+ base::Callback<void(const AckHandleMap&)> callback) OVERRIDE;
+ virtual void Acknowledge(const invalidation::ObjectId& id,
+ const AckHandle& ack_handle) OVERRIDE;
+};
+
+} // namespace syncer
+
+#endif // SYNC_TOOLS_NULL_INVALIDATION_STATE_TRACKER_H_
diff --git a/sync/tools/sync_client.cc b/sync/tools/sync_client.cc
index c2dc657..d973093 100644
--- a/sync/tools/sync_client.cc
+++ b/sync/tools/sync_client.cc
@@ -7,7 +7,6 @@
#include <string>
#include "base/at_exit.h"
-#include "base/base64.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/stack_trace.h"
@@ -44,6 +43,7 @@
#include "sync/notifier/invalidator.h"
#include "sync/notifier/invalidator_factory.h"
#include "sync/test/fake_encryptor.h"
+#include "sync/tools/null_invalidation_state_tracker.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
@@ -65,41 +65,6 @@ const char kXmppAllowInsecureConnectionSwitch[] =
"xmpp-allow-insecure-connection";
const char kNotificationMethodSwitch[] = "notification-method";
-class NullInvalidationStateTracker
- : public base::SupportsWeakPtr<NullInvalidationStateTracker>,
- public InvalidationStateTracker {
- public:
- NullInvalidationStateTracker() {}
- virtual ~NullInvalidationStateTracker() {}
-
- virtual InvalidationStateMap GetAllInvalidationStates() const OVERRIDE {
- return InvalidationStateMap();
- }
-
- virtual void SetMaxVersion(
- const invalidation::ObjectId& id,
- int64 max_invalidation_version) OVERRIDE {
- VLOG(1) << "Setting max invalidation version for "
- << ObjectIdToString(id) << " to " << max_invalidation_version;
- }
-
- virtual void Forget(const ObjectIdSet& ids) OVERRIDE {
- for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
- VLOG(1) << "Forgetting invalidation state for " << ObjectIdToString(*it);
- }
- }
-
- virtual std::string GetBootstrapData() const OVERRIDE {
- return std::string();
- }
-
- virtual void SetBootstrapData(const std::string& data) OVERRIDE {
- std::string base64_data;
- CHECK(base::Base64Encode(data, &base64_data));
- VLOG(1) << "Setting bootstrap data to: " << base64_data;
- }
-};
-
// Needed to use a real host resolver.
class MyTestURLRequestContext : public net::TestURLRequestContext {
public:
diff --git a/sync/tools/sync_listen_notifications.cc b/sync/tools/sync_listen_notifications.cc
index bc90088..ce901a4 100644
--- a/sync/tools/sync_listen_notifications.cc
+++ b/sync/tools/sync_listen_notifications.cc
@@ -7,13 +7,11 @@
#include <string>
#include "base/at_exit.h"
-#include "base/base64.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
#include "jingle/notifier/base/notification_method.h"
@@ -30,6 +28,7 @@
#include "sync/notifier/invalidation_util.h"
#include "sync/notifier/invalidator_factory.h"
#include "sync/notifier/invalidator.h"
+#include "sync/tools/null_invalidation_state_tracker.h"
#if defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
@@ -78,41 +77,6 @@ class NotificationPrinter : public InvalidationHandler {
DISALLOW_COPY_AND_ASSIGN(NotificationPrinter);
};
-class NullInvalidationStateTracker
- : public base::SupportsWeakPtr<NullInvalidationStateTracker>,
- public InvalidationStateTracker {
- public:
- NullInvalidationStateTracker() {}
- virtual ~NullInvalidationStateTracker() {}
-
- virtual InvalidationStateMap GetAllInvalidationStates() const OVERRIDE {
- return InvalidationStateMap();
- }
-
- virtual void SetMaxVersion(
- const invalidation::ObjectId& id,
- int64 max_invalidation_version) OVERRIDE {
- LOG(INFO) << "Setting max invalidation version for "
- << ObjectIdToString(id) << " to " << max_invalidation_version;
- }
-
- virtual void Forget(const ObjectIdSet& ids) OVERRIDE {
- for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
- LOG(INFO) << "Forgetting saved state for " << ObjectIdToString(*it);
- }
- }
-
- virtual std::string GetBootstrapData() const OVERRIDE {
- return std::string();
- }
-
- virtual void SetBootstrapData(const std::string& data) OVERRIDE {
- std::string base64_data;
- CHECK(base::Base64Encode(data, &base64_data));
- LOG(INFO) << "Setting bootstrap data to: " << base64_data;
- }
-};
-
// Needed to use a real host resolver.
class MyTestURLRequestContext : public net::TestURLRequestContext {
public: