diff options
author | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 05:31:12 +0000 |
---|---|---|
committer | dcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-12-05 05:31:12 +0000 |
commit | 0e7f2b7f4023f10cc1d4d4a9eabca701faedec01 (patch) | |
tree | 5eed13dfa3d07adf11853b833434fa785ee34776 | |
parent | 5fbd63798b997475fded3cc90f456425c607edcd (diff) | |
download | chromium_src-0e7f2b7f4023f10cc1d4d4a9eabca701faedec01.zip chromium_src-0e7f2b7f4023f10cc1d4d4a9eabca701faedec01.tar.gz chromium_src-0e7f2b7f4023f10cc1d4d4a9eabca701faedec01.tar.bz2 |
Implement features needed for local ack handling in InvalidationStateTracker.
Adds the ability to save payloads in InvalidationStateTracker, and also adds
the functionality to generate, track, and acknowledge local ack handles.
BUG=124149
Review URL: https://codereview.chromium.org/11415049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@171165 0039d316-1c4b-4281-b951-d872f2087c98
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, ¤t_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", ×tamp_as_string)) + return false; + int64 timestamp_value; + if (!base::StringToInt64(timestamp_as_string, ×tamp_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: |