summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc23
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h10
-rw-r--r--chrome/browser/sync/glue/sync_backend_host_unittest.cc3
-rw-r--r--chrome/browser/sync/notifier/DEPS1
-rw-r--r--chrome/browser/sync/notifier/chrome_invalidation_client.cc36
-rw-r--r--chrome/browser/sync/notifier/chrome_invalidation_client.h16
-rw-r--r--chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc38
-rw-r--r--chrome/browser/sync/notifier/invalidation_notifier.cc16
-rw-r--r--chrome/browser/sync/notifier/invalidation_notifier.h13
-rw-r--r--chrome/browser/sync/notifier/invalidation_notifier_unittest.cc12
-rw-r--r--chrome/browser/sync/notifier/invalidation_version_tracker.h38
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc25
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h6
-rw-r--r--chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc11
-rw-r--r--chrome/browser/sync/notifier/sync_notifier.h6
-rw-r--r--chrome/browser/sync/notifier/sync_notifier_factory.cc16
-rw-r--r--chrome/browser/sync/notifier/sync_notifier_factory.h13
-rw-r--r--chrome/browser/sync/profile_sync_service.cc3
-rw-r--r--chrome/browser/sync/sync_prefs.cc76
-rw-r--r--chrome/browser/sync/sync_prefs.h15
-rw-r--r--chrome/browser/sync/sync_prefs_unittest.cc32
-rw-r--r--chrome/browser/sync/test_profile_sync_service.cc4
-rw-r--r--chrome/browser/sync/test_profile_sync_service.h3
-rw-r--r--chrome/browser/sync/tools/sync_listen_notifications.cc43
-rw-r--r--chrome/chrome.gyp1
-rw-r--r--chrome/common/pref_names.cc4
-rw-r--r--chrome/common/pref_names.h1
27 files changed, 418 insertions, 47 deletions
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index 1a322cb..4e6c7c4 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -58,7 +58,7 @@ using sync_api::SyncCredentials;
SyncBackendHost::SyncBackendHost(const std::string& name,
Profile* profile,
- SyncPrefs* sync_prefs)
+ const base::WeakPtr<SyncPrefs>& sync_prefs)
: core_(new Core(name, ALLOW_THIS_IN_INITIALIZER_LIST(this))),
initialization_state_(NOT_ATTEMPTED),
sync_thread_("Chrome_SyncThread"),
@@ -66,14 +66,15 @@ SyncBackendHost::SyncBackendHost(const std::string& name,
profile_(profile),
sync_prefs_(sync_prefs),
name_(name),
- sync_notifier_factory_(webkit_glue::GetUserAgent(GURL()),
- profile_->GetRequestContext(),
- *CommandLine::ForCurrentProcess()),
+ sync_notifier_factory_(
+ webkit_glue::GetUserAgent(GURL()),
+ profile_->GetRequestContext(),
+ sync_prefs,
+ *CommandLine::ForCurrentProcess()),
frontend_(NULL),
sync_data_folder_path_(
profile_->GetPath().Append(kSyncDataFolderName)),
last_auth_error_(AuthError::None()) {
- CHECK(sync_prefs_);
}
SyncBackendHost::SyncBackendHost()
@@ -81,11 +82,12 @@ SyncBackendHost::SyncBackendHost()
sync_thread_("Chrome_SyncThread"),
frontend_loop_(MessageLoop::current()),
profile_(NULL),
- sync_prefs_(NULL),
name_("Unknown"),
- sync_notifier_factory_(webkit_glue::GetUserAgent(GURL()),
- NULL,
- *CommandLine::ForCurrentProcess()),
+ sync_notifier_factory_(
+ webkit_glue::GetUserAgent(GURL()),
+ NULL,
+ base::WeakPtr<sync_notifier::InvalidationVersionTracker>(),
+ *CommandLine::ForCurrentProcess()),
frontend_(NULL),
last_auth_error_(AuthError::None()) {
}
@@ -109,6 +111,7 @@ void SyncBackendHost::Initialize(
DCHECK(frontend);
syncable::ModelTypeSet initial_types_with_nigori(initial_types);
+ CHECK(sync_prefs_.get());
if (sync_prefs_->HasSyncSetupCompleted()) {
initial_types_with_nigori.insert(syncable::NIGORI);
}
@@ -884,6 +887,7 @@ void SyncBackendHost::HandleInitializationCompletedOnFrontendLoop(
// If setup has completed, start off in DOWNLOADING_NIGORI so that
// we start off by refreshing encryption.
+ CHECK(sync_prefs_.get());
if (sync_prefs_->HasSyncSetupCompleted() &&
initialization_state_ < DOWNLOADING_NIGORI) {
initialization_state_ = DOWNLOADING_NIGORI;
@@ -994,6 +998,7 @@ sync_api::HttpPostProviderFactory* SyncBackendHost::MakeHttpBridgeFactory(
void SyncBackendHost::PersistEncryptionBootstrapToken(
const std::string& token) {
+ CHECK(sync_prefs_.get());
sync_prefs_->SetEncryptionBootstrapToken(token);
}
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index f92c7d4..0fba6ca 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -15,6 +15,7 @@
#include "base/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/thread.h"
#include "base/timer.h"
#include "chrome/browser/sync/engine/model_safe_worker.h"
@@ -122,10 +123,11 @@ class SyncBackendHost {
// Create a SyncBackendHost with a reference to the |frontend| that
// it serves and communicates to via the SyncFrontend interface (on
- // the same thread it used to call the constructor). Does not take
- // ownership of |sync_prefs|.
+ // the same thread it used to call the constructor). Must outlive
+ // |sync_prefs|.
SyncBackendHost(const std::string& name,
- Profile* profile, SyncPrefs* sync_prefs);
+ Profile* profile,
+ const base::WeakPtr<SyncPrefs>& sync_prefs);
// For testing.
// TODO(skrul): Extract an interface so this is not needed.
SyncBackendHost();
@@ -552,7 +554,7 @@ class SyncBackendHost {
Profile* const profile_;
- SyncPrefs* const sync_prefs_;
+ const base::WeakPtr<SyncPrefs> sync_prefs_;
// Name used for debugging (set from profile_->GetDebugName()).
const std::string name_;
diff --git a/chrome/browser/sync/glue/sync_backend_host_unittest.cc b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
index dac72d5..57822ed 100644
--- a/chrome/browser/sync/glue/sync_backend_host_unittest.cc
+++ b/chrome/browser/sync/glue/sync_backend_host_unittest.cc
@@ -85,7 +85,8 @@ TEST_F(SyncBackendHostTest, InitShutdown) {
profile.CreateRequestContext();
SyncPrefs sync_prefs(profile.GetPrefs());
- SyncBackendHost backend(profile.GetDebugName(), &profile, &sync_prefs);
+ SyncBackendHost backend(profile.GetDebugName(),
+ &profile, sync_prefs.AsWeakPtr());
MockSyncFrontend mock_frontend;
sync_api::SyncCredentials credentials;
diff --git a/chrome/browser/sync/notifier/DEPS b/chrome/browser/sync/notifier/DEPS
index 96351bd..9c39f61 100644
--- a/chrome/browser/sync/notifier/DEPS
+++ b/chrome/browser/sync/notifier/DEPS
@@ -7,6 +7,7 @@ include_rules = [
"+chrome/browser/sync/syncable/model_type.h",
"+chrome/browser/sync/syncable/model_type_payload_map.h",
"+chrome/browser/sync/protocol/service_constants.h",
+ "+chrome/browser/sync/util",
"+chrome/common/chrome_switches.h",
"+google/cacheinvalidation",
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.cc b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
index 6478857..8c70c08 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.cc
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.cc
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/logging.h"
+#include "base/tracked_objects.h"
#include "chrome/browser/sync/notifier/cache_invalidation_packet_handler.h"
#include "chrome/browser/sync/notifier/invalidation_util.h"
#include "chrome/browser/sync/notifier/registration_manager.h"
@@ -43,7 +44,11 @@ ChromeInvalidationClient::~ChromeInvalidationClient() {
void ChromeInvalidationClient::Start(
const std::string& client_id, const std::string& client_info,
- const std::string& state, Listener* listener,
+ const std::string& state,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
+ Listener* listener,
StateWriter* state_writer,
base::WeakPtr<buzz::XmppTaskParentInterface> base_task) {
DCHECK(non_thread_safe_.CalledOnValidThread());
@@ -57,6 +62,21 @@ void ChromeInvalidationClient::Start(
// update the in-memory cache, while reads just return the cached state.
chrome_system_resources_.storage()->SetInitialState(state);
+ max_invalidation_versions_ = initial_max_invalidation_versions;
+ if (max_invalidation_versions_.empty()) {
+ VLOG(2) << "No initial max invalidation versions for any type";
+ } else {
+ for (InvalidationVersionMap::const_iterator it =
+ max_invalidation_versions_.begin();
+ it != max_invalidation_versions_.end(); ++it) {
+ VLOG(2) << "Initial max invalidation version for "
+ << syncable::ModelTypeToString(it->first) << " is "
+ << it->second;
+ }
+ }
+ invalidation_version_tracker_ = invalidation_version_tracker;
+ DCHECK(invalidation_version_tracker_.IsInitialized());
+
DCHECK(!listener_);
DCHECK(listener);
listener_ = listener;
@@ -104,6 +124,9 @@ void ChromeInvalidationClient::Stop() {
invalidation_client_.reset();
state_writer_ = NULL;
listener_ = NULL;
+
+ invalidation_version_tracker_.Reset();
+ max_invalidation_versions_.clear();
}
void ChromeInvalidationClient::RegisterTypes(
@@ -145,9 +168,7 @@ void ChromeInvalidationClient::Invalidate(
// should drop invalidations for unregistered types. We may also
// have to filter it at a higher level, as invalidations for
// newly-unregistered types may already be in flight.
- //
- // TODO(akalin): Persist |max_invalidation_versions_| somehow.
- std::map<syncable::ModelType, int64>::const_iterator it =
+ InvalidationVersionMap::const_iterator it =
max_invalidation_versions_.find(model_type);
if ((it != max_invalidation_versions_.end()) &&
(invalidation.version() <= it->second)) {
@@ -155,7 +176,14 @@ void ChromeInvalidationClient::Invalidate(
client->Acknowledge(ack_handle);
return;
}
+ VLOG(2) << "Setting max invalidation version for "
+ << syncable::ModelTypeToString(model_type) << " to "
+ << invalidation.version();
max_invalidation_versions_[model_type] = invalidation.version();
+ invalidation_version_tracker_.Call(
+ FROM_HERE,
+ &InvalidationVersionTracker::SetMaxVersion,
+ model_type, invalidation.version());
std::string payload;
// payload() CHECK()'s has_payload(), so we must check it ourselves first.
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client.h b/chrome/browser/sync/notifier/chrome_invalidation_client.h
index 1adb40c..6b7e69f 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client.h
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client.h
@@ -9,7 +9,6 @@
#define CHROME_BROWSER_SYNC_NOTIFIER_CHROME_INVALIDATION_CLIENT_H_
#pragma once
-#include <map>
#include <string>
#include "base/basictypes.h"
@@ -19,9 +18,11 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/sync/notifier/chrome_system_resources.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/state_writer.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "google/cacheinvalidation/v2/invalidation-listener.h"
// TODO(akalin): Move invalidation::InvalidationListener into its own
@@ -39,6 +40,8 @@ using invalidation::InvalidationListener;
class CacheInvalidationPacketHandler;
class RegistrationManager;
+// ChromeInvalidationClient is not thread-safe and lives on the sync
+// thread.
class ChromeInvalidationClient
: public InvalidationListener,
public StateWriter {
@@ -59,10 +62,15 @@ class ChromeInvalidationClient
virtual ~ChromeInvalidationClient();
// Does not take ownership of |listener| or |state_writer|.
+ // |invalidation_version_tracker| must be initialized.
// |base_task| must still be non-NULL.
void Start(
const std::string& client_id, const std::string& client_info,
- const std::string& state, Listener* listener,
+ const std::string& state,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
+ Listener* listener,
StateWriter* state_writer,
base::WeakPtr<buzz::XmppTaskParentInterface> base_task);
@@ -120,13 +128,15 @@ class ChromeInvalidationClient
ChromeSystemResources chrome_system_resources_;
base::ScopedCallbackFactory<ChromeInvalidationClient>
scoped_callback_factory_;
+ InvalidationVersionMap max_invalidation_versions_;
+ browser_sync::WeakHandle<InvalidationVersionTracker>
+ invalidation_version_tracker_;
Listener* listener_;
StateWriter* state_writer_;
scoped_ptr<invalidation::InvalidationClient> invalidation_client_;
scoped_ptr<CacheInvalidationPacketHandler>
cache_invalidation_packet_handler_;
scoped_ptr<RegistrationManager> registration_manager_;
- std::map<syncable::ModelType, int64> max_invalidation_versions_;
// Stored to pass to |registration_manager_| on start.
syncable::ModelTypeSet registered_types_;
bool ticl_ready_;
diff --git a/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc b/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
index 80f896f..b581d6a 100644
--- a/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
+++ b/chrome/browser/sync/notifier/chrome_invalidation_client_unittest.cc
@@ -9,6 +9,7 @@
#include "chrome/browser/sync/notifier/state_writer.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "google/cacheinvalidation/v2/invalidation-client.h"
#include "google/cacheinvalidation/v2/types.h"
#include "google/cacheinvalidation/v2/types.pb.h"
@@ -45,6 +46,14 @@ class MockListener : public ChromeInvalidationClient::Listener {
MOCK_METHOD1(OnSessionStatusChanged, void(bool));
};
+class MockInvalidationVersionTracker
+ : public InvalidationVersionTracker,
+ public base::SupportsWeakPtr<MockInvalidationVersionTracker> {
+ public:
+ MOCK_CONST_METHOD0(GetAllMaxVersions, InvalidationVersionMap());
+ MOCK_METHOD2(SetMaxVersion, void(syncable::ModelType, int64));
+};
+
class MockStateWriter : public StateWriter {
public:
MOCK_METHOD1(WriteState, void(const std::string&));
@@ -65,6 +74,9 @@ class ChromeInvalidationClientTest : public testing::Test {
protected:
virtual void SetUp() {
client_.Start(kClientId, kClientInfo, kState,
+ InvalidationVersionMap(),
+ browser_sync::WeakHandle<InvalidationVersionTracker>(
+ mock_invalidation_version_tracker_.AsWeakPtr()),
&mock_listener_, &mock_state_writer_,
fake_base_task_.AsWeakPtr());
}
@@ -89,6 +101,9 @@ class ChromeInvalidationClientTest : public testing::Test {
invalidation::AckHandle ack_handle("fakedata");
EXPECT_CALL(mock_invalidation_client_, Acknowledge(ack_handle));
client_.Invalidate(&mock_invalidation_client_, inv, ack_handle);
+ // Pump message loop to trigger
+ // InvalidationVersionTracker::SetMaxVersion().
+ message_loop_.RunAllPending();
}
// |payload| can be NULL, but not |type_name|.
@@ -110,6 +125,8 @@ class ChromeInvalidationClientTest : public testing::Test {
MessageLoop message_loop_;
StrictMock<MockListener> mock_listener_;
+ StrictMock<MockInvalidationVersionTracker>
+ mock_invalidation_version_tracker_;
StrictMock<MockStateWriter> mock_state_writer_;
StrictMock<MockInvalidationClient> mock_invalidation_client_;
notifier::FakeBaseTask fake_base_task_;
@@ -150,12 +167,16 @@ TEST_F(ChromeInvalidationClientTest, InvalidateBadObjectId) {
TEST_F(ChromeInvalidationClientTest, InvalidateNoPayload) {
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::BOOKMARKS, "")));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::BOOKMARKS, 1));
FireInvalidate("BOOKMARK", 1, NULL);
}
TEST_F(ChromeInvalidationClientTest, InvalidateWithPayload) {
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::PREFERENCES, "payload")));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::PREFERENCES, 1));
FireInvalidate("PREFERENCE", 1, "payload");
}
@@ -164,6 +185,8 @@ TEST_F(ChromeInvalidationClientTest, InvalidateVersion) {
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::APPS, "")));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::APPS, 1));
// Should trigger.
FireInvalidate("APP", 1, NULL);
@@ -197,23 +220,31 @@ TEST_F(ChromeInvalidationClientTest, InvalidateVersionMultipleTypes) {
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::EXTENSIONS, "")));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::APPS, 3));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::EXTENSIONS, 2));
+
// Should trigger both.
FireInvalidate("APP", 3, NULL);
FireInvalidate("EXTENSION", 2, NULL);
Mock::VerifyAndClearExpectations(&mock_listener_);
+ Mock::VerifyAndClearExpectations(&mock_invalidation_version_tracker_);
// Should both be dropped.
FireInvalidate("APP", 1, NULL);
FireInvalidate("EXTENSION", 1, NULL);
Mock::VerifyAndClearExpectations(&mock_listener_);
+ Mock::VerifyAndClearExpectations(&mock_invalidation_version_tracker_);
// InvalidateAll shouldn't change any version state.
EXPECT_CALL(mock_listener_, OnInvalidate(MakeMapFromSet(types, "")));
FireInvalidateAll();
Mock::VerifyAndClearExpectations(&mock_listener_);
+ Mock::VerifyAndClearExpectations(&mock_invalidation_version_tracker_);
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::PREFERENCES, "")));
@@ -222,6 +253,13 @@ TEST_F(ChromeInvalidationClientTest, InvalidateVersionMultipleTypes) {
EXPECT_CALL(mock_listener_,
OnInvalidate(MakeMap(syncable::APPS, "")));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::PREFERENCES, 5));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::EXTENSIONS, 3));
+ EXPECT_CALL(mock_invalidation_version_tracker_,
+ SetMaxVersion(syncable::APPS, 4));
+
// Should trigger all three.
FireInvalidate("PREFERENCE", 5, NULL);
FireInvalidate("EXTENSION", 3, NULL);
diff --git a/chrome/browser/sync/notifier/invalidation_notifier.cc b/chrome/browser/sync/notifier/invalidation_notifier.cc
index 2433ad5..8f7616e 100644
--- a/chrome/browser/sync/notifier/invalidation_notifier.cc
+++ b/chrome/browser/sync/notifier/invalidation_notifier.cc
@@ -21,9 +21,14 @@ namespace sync_notifier {
InvalidationNotifier::InvalidationNotifier(
const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info)
: state_(STOPPED),
notifier_options_(notifier_options),
+ initial_max_invalidation_versions_(initial_max_invalidation_versions),
+ invalidation_version_tracker_(invalidation_version_tracker),
client_info_(client_info) {
DCHECK_EQ(notifier::NOTIFICATION_SERVER,
notifier_options.notification_method);
@@ -50,16 +55,20 @@ void InvalidationNotifier::RemoveObserver(SyncNotifierObserver* observer) {
void InvalidationNotifier::SetUniqueId(const std::string& unique_id) {
DCHECK(non_thread_safe_.CalledOnValidThread());
invalidation_client_id_ = unique_id;
+ VLOG(1) << "Setting unique ID to " << unique_id;
+ CHECK(!invalidation_client_id_.empty());
}
void InvalidationNotifier::SetState(const std::string& state) {
DCHECK(non_thread_safe_.CalledOnValidThread());
invalidation_state_ = state;
+ VLOG(1) << "Setting new state";
}
void InvalidationNotifier::UpdateCredentials(
const std::string& email, const std::string& token) {
DCHECK(non_thread_safe_.CalledOnValidThread());
+ CHECK(!invalidation_client_id_.empty());
VLOG(1) << "Updating credentials for " << email;
buzz::XmppClientSettings xmpp_client_settings =
notifier::MakeXmppClientSettings(notifier_options_,
@@ -85,6 +94,7 @@ void InvalidationNotifier::UpdateCredentials(
void InvalidationNotifier::UpdateEnabledTypes(
const syncable::ModelTypeSet& enabled_types) {
DCHECK(non_thread_safe_.CalledOnValidThread());
+ CHECK(!invalidation_client_id_.empty());
invalidation_client_.RegisterTypes(enabled_types);
}
@@ -101,9 +111,13 @@ void InvalidationNotifier::OnConnect(
if (state_ >= STARTED) {
invalidation_client_.ChangeBaseTask(base_task);
} else {
- VLOG(1) << "First time connecting: starting invalidation client";
+ VLOG(1) << "First time connecting: starting invalidation client with id "
+ << invalidation_client_id_ << " and client info "
+ << client_info_;
invalidation_client_.Start(
invalidation_client_id_, client_info_, invalidation_state_,
+ initial_max_invalidation_versions_,
+ invalidation_version_tracker_,
this, this, base_task);
invalidation_state_.clear();
state_ = STARTED;
diff --git a/chrome/browser/sync/notifier/invalidation_notifier.h b/chrome/browser/sync/notifier/invalidation_notifier.h
index f39bbbe..7b6a71b 100644
--- a/chrome/browser/sync/notifier/invalidation_notifier.h
+++ b/chrome/browser/sync/notifier/invalidation_notifier.h
@@ -21,9 +21,11 @@
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "chrome/browser/sync/notifier/chrome_invalidation_client.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/state_writer.h"
#include "chrome/browser/sync/notifier/sync_notifier.h"
#include "chrome/browser/sync/syncable/model_type.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "jingle/notifier/base/notifier_options.h"
#include "jingle/notifier/communicator/login.h"
@@ -36,8 +38,12 @@ class InvalidationNotifier
public ChromeInvalidationClient::Listener,
public StateWriter {
public:
+ // |invalidation_version_tracker| must be initialized.
InvalidationNotifier(
const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info);
virtual ~InvalidationNotifier();
@@ -85,6 +91,13 @@ class InvalidationNotifier
const notifier::NotifierOptions notifier_options_;
// Passed to |invalidation_client_|.
+ const InvalidationVersionMap initial_max_invalidation_versions_;
+
+ // Passed to |invalidation_client_|.
+ const browser_sync::WeakHandle<InvalidationVersionTracker>
+ invalidation_version_tracker_;
+
+ // Passed to |invalidation_client_|.
const std::string client_info_;
// Our observers (which must live on the same thread).
diff --git a/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc b/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
index f9c6354..1c1e304 100644
--- a/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
+++ b/chrome/browser/sync/notifier/invalidation_notifier_unittest.cc
@@ -6,9 +6,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/mock_sync_notifier_observer.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "chrome/test/base/test_url_request_context_getter.h"
#include "content/browser/browser_thread.h"
#include "jingle/notifier/base/fake_base_task.h"
@@ -35,8 +37,13 @@ class InvalidationNotifierTest : public testing::Test {
// Note: URLRequestContextGetters are ref-counted.
notifier_options.request_context_getter =
new TestURLRequestContextGetter();
- invalidation_notifier_.reset(new InvalidationNotifier(notifier_options,
- "fake_client_info"));
+ invalidation_notifier_.reset(
+ new InvalidationNotifier(
+ notifier_options,
+ InvalidationVersionMap(),
+ browser_sync::MakeWeakHandle(
+ base::WeakPtr<InvalidationVersionTracker>()),
+ "fake_client_info"));
invalidation_notifier_->AddObserver(&mock_observer_);
}
@@ -68,6 +75,7 @@ TEST_F(InvalidationNotifierTest, Basic) {
EXPECT_CALL(mock_observer_, OnNotificationStateChange(false));
invalidation_notifier_->SetState("fake_state");
+ invalidation_notifier_->SetUniqueId("fake_id");
invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
invalidation_notifier_->OnConnect(fake_base_task_.AsWeakPtr());
diff --git a/chrome/browser/sync/notifier/invalidation_version_tracker.h b/chrome/browser/sync/notifier/invalidation_version_tracker.h
new file mode 100644
index 0000000..fe7d545
--- /dev/null
+++ b/chrome/browser/sync/notifier/invalidation_version_tracker.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2011 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.
+//
+// An InvalidationVersionTracker is an interface that handles getting
+// and setting (persisting) max invalidation versions.
+
+#ifndef CHROME_BROWSER_SYNC_NOTIFIER_INVALIDATION_VERSION_TRACKER_H_
+#define CHROME_BROWSER_SYNC_NOTIFIER_INVALIDATION_VERSION_TRACKER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "chrome/browser/sync/syncable/model_type.h"
+
+namespace sync_notifier {
+
+typedef std::map<syncable::ModelType, int64> InvalidationVersionMap;
+
+class InvalidationVersionTracker {
+ public:
+ InvalidationVersionTracker() {}
+
+ virtual InvalidationVersionMap GetAllMaxVersions() const = 0;
+
+ // |max_version| should be strictly greater than any existing max
+ // version for |model_type|.
+ virtual void SetMaxVersion(syncable::ModelType model_type,
+ int64 max_version) = 0;
+
+ protected:
+ virtual ~InvalidationVersionTracker() {}
+};
+
+} // namespace sync_notifier
+
+#endif // CHROME_BROWSER_SYNC_NOTIFIER_INVALIDATION_VERSION_TRACKER_H_
+
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
index e6040a3..8534b12 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.cc
@@ -26,8 +26,12 @@ class NonBlockingInvalidationNotifier::Core
void RemoveObserver(SyncNotifierObserver* observer);
// Helpers called on I/O thread.
- void Initialize(const notifier::NotifierOptions& notifier_options,
- const std::string& client_info);
+ void Initialize(
+ const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
+ const std::string& client_info);
void Teardown();
void SetUniqueId(const std::string& unique_id);
void SetState(const std::string& state);
@@ -61,6 +65,9 @@ NonBlockingInvalidationNotifier::Core::~Core() {
void NonBlockingInvalidationNotifier::Core::Initialize(
const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info) {
DCHECK(notifier_options.request_context_getter);
DCHECK_EQ(notifier::NOTIFICATION_SERVER,
@@ -69,7 +76,11 @@ void NonBlockingInvalidationNotifier::Core::Initialize(
GetIOMessageLoopProxy();
DCHECK(io_message_loop_proxy_->BelongsToCurrentThread());
invalidation_notifier_.reset(
- new InvalidationNotifier(notifier_options, client_info));
+ new InvalidationNotifier(
+ notifier_options,
+ initial_max_invalidation_versions,
+ invalidation_version_tracker,
+ client_info));
invalidation_notifier_->AddObserver(this);
}
@@ -137,6 +148,9 @@ void NonBlockingInvalidationNotifier::Core::StoreState(
NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier(
const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info)
: core_(new Core),
parent_message_loop_proxy_(
@@ -148,7 +162,10 @@ NonBlockingInvalidationNotifier::NonBlockingInvalidationNotifier(
NewRunnableMethod(
core_.get(),
&NonBlockingInvalidationNotifier::Core::Initialize,
- notifier_options, client_info))) {
+ notifier_options,
+ initial_max_invalidation_versions,
+ invalidation_version_tracker,
+ client_info))) {
NOTREACHED();
}
}
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
index 7e65158..351d67f 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier.h
@@ -14,7 +14,9 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/sync_notifier.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "jingle/notifier/base/notifier_options.h"
namespace base {
@@ -25,8 +27,12 @@ namespace sync_notifier {
class NonBlockingInvalidationNotifier : public SyncNotifier {
public:
+ // |invalidation_version_tracker| must be initialized.
NonBlockingInvalidationNotifier(
const notifier::NotifierOptions& notifier_options,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info);
virtual ~NonBlockingInvalidationNotifier();
diff --git a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
index 3ab7a73..dab0be5 100644
--- a/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
+++ b/chrome/browser/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
@@ -7,9 +7,11 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/mock_sync_notifier_observer.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/syncable/model_type_payload_map.h"
+#include "chrome/browser/sync/util/weak_handle.h"
#include "chrome/test/base/test_url_request_context_getter.h"
#include "content/browser/browser_thread.h"
#include "jingle/notifier/base/fake_base_task.h"
@@ -37,8 +39,12 @@ class NonBlockingInvalidationNotifierTest : public testing::Test {
notifier::NotifierOptions notifier_options;
notifier_options.request_context_getter = request_context_getter_;
invalidation_notifier_.reset(
- new NonBlockingInvalidationNotifier(notifier_options,
- "fake_client_info"));
+ new NonBlockingInvalidationNotifier(
+ notifier_options,
+ InvalidationVersionMap(),
+ browser_sync::WeakHandle<InvalidationVersionTracker>(
+ base::WeakPtr<sync_notifier::InvalidationVersionTracker>()),
+ "fake_client_info"));
invalidation_notifier_->AddObserver(&mock_observer_);
}
@@ -63,6 +69,7 @@ TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
types.insert(syncable::BOOKMARKS);
types.insert(syncable::AUTOFILL);
+ invalidation_notifier_->SetUniqueId("fake_id");
invalidation_notifier_->SetState("fake_state");
invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
invalidation_notifier_->UpdateEnabledTypes(types);
diff --git a/chrome/browser/sync/notifier/sync_notifier.h b/chrome/browser/sync/notifier/sync_notifier.h
index db1f703..f20000a 100644
--- a/chrome/browser/sync/notifier/sync_notifier.h
+++ b/chrome/browser/sync/notifier/sync_notifier.h
@@ -25,12 +25,12 @@ class SyncNotifier {
virtual void RemoveObserver(SyncNotifierObserver* observer) = 0;
// SetUniqueId must be called once, before any call to
- // UpdateCredentials. |unique_id| should be a globally unique
- // string.
+ // UpdateCredentials. |unique_id| should be a non-empty globally
+ // unique string.
virtual void SetUniqueId(const std::string& unique_id) = 0;
// SetState must be called once, before any call to
- // UpdateCredentials.
+ // UpdateCredentials. |state| may be empty.
virtual void SetState(const std::string& state) = 0;
// The observers won't be notified of any notifications until
diff --git a/chrome/browser/sync/notifier/sync_notifier_factory.cc b/chrome/browser/sync/notifier/sync_notifier_factory.cc
index 2b87844..452e1f1 100644
--- a/chrome/browser/sync/notifier/sync_notifier_factory.cc
+++ b/chrome/browser/sync/notifier/sync_notifier_factory.cc
@@ -49,6 +49,9 @@ net::HostPortPair StringToHostPortPair(const std::string& host_port_str,
SyncNotifier* CreateDefaultSyncNotifier(
const CommandLine& command_line,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
+ const InvalidationVersionMap& initial_max_invalidation_versions,
+ const browser_sync::WeakHandle<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const std::string& client_info) {
// Contains options specific to how sync clients send and listen to
// jingle notifications.
@@ -105,7 +108,9 @@ SyncNotifier* CreateDefaultSyncNotifier(
return new P2PNotifier(talk_mediator, NOTIFY_ALL);
}
- return new NonBlockingInvalidationNotifier(notifier_options, client_info);
+ return new NonBlockingInvalidationNotifier(
+ notifier_options, initial_max_invalidation_versions,
+ invalidation_version_tracker, client_info);
}
} // namespace
@@ -113,9 +118,16 @@ SyncNotifierFactory::SyncNotifierFactory(
const std::string& client_info,
const scoped_refptr<net::URLRequestContextGetter>&
request_context_getter,
+ const base::WeakPtr<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const CommandLine& command_line)
: client_info_(client_info),
request_context_getter_(request_context_getter),
+ initial_max_invalidation_versions_(
+ invalidation_version_tracker.get() ?
+ invalidation_version_tracker->GetAllMaxVersions() :
+ InvalidationVersionMap()),
+ invalidation_version_tracker_(invalidation_version_tracker),
command_line_(command_line) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
@@ -127,6 +139,8 @@ SyncNotifierFactory::~SyncNotifierFactory() {
SyncNotifier* SyncNotifierFactory::CreateSyncNotifier() {
return CreateDefaultSyncNotifier(command_line_,
request_context_getter_,
+ initial_max_invalidation_versions_,
+ invalidation_version_tracker_,
client_info_);
}
} // namespace sync_notifier
diff --git a/chrome/browser/sync/notifier/sync_notifier_factory.h b/chrome/browser/sync/notifier/sync_notifier_factory.h
index 6e89afe..2c0069ce 100644
--- a/chrome/browser/sync/notifier/sync_notifier_factory.h
+++ b/chrome/browser/sync/notifier/sync_notifier_factory.h
@@ -8,6 +8,9 @@
#include <string>
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
+#include "chrome/browser/sync/util/weak_handle.h"
class CommandLine;
@@ -24,11 +27,14 @@ class SyncNotifier;
class SyncNotifierFactory {
public:
// |client_info| is a string identifying the client, e.g. a user
- // agent string.
+ // agent string. |invalidation_version_tracker| may be NULL (for
+ // tests).
SyncNotifierFactory(
const std::string& client_info,
const scoped_refptr<net::URLRequestContextGetter>&
request_context_getter,
+ const base::WeakPtr<InvalidationVersionTracker>&
+ invalidation_version_tracker,
const CommandLine& command_line);
~SyncNotifierFactory();
@@ -39,7 +45,10 @@ class SyncNotifierFactory {
private:
const std::string client_info_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ const scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ const InvalidationVersionMap initial_max_invalidation_versions_;
+ const browser_sync::WeakHandle<InvalidationVersionTracker>
+ invalidation_version_tracker_;
const CommandLine& command_line_;
};
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 2ace4ac..08f65ad 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -315,7 +315,8 @@ void ProfileSyncService::InitializeBackend(bool delete_stale_data) {
void ProfileSyncService::CreateBackend() {
backend_.reset(
- new SyncBackendHost(profile_->GetDebugName(), profile_, &sync_prefs_));
+ new SyncBackendHost(profile_->GetDebugName(),
+ profile_, sync_prefs_.AsWeakPtr()));
}
bool ProfileSyncService::IsEncryptedDatatypeEnabled() const {
diff --git a/chrome/browser/sync/sync_prefs.cc b/chrome/browser/sync/sync_prefs.cc
index 45c75d8..4a3dcd4 100644
--- a/chrome/browser/sync/sync_prefs.cc
+++ b/chrome/browser/sync/sync_prefs.cc
@@ -5,6 +5,8 @@
#include "chrome/browser/sync/sync_prefs.h"
#include "base/logging.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/common/chrome_notification_types.h"
@@ -49,6 +51,9 @@ void SyncPrefs::ClearPreferences() {
// TODO(nick): The current behavior does not clear
// e.g. prefs::kSyncBookmarks. Is that really what we want?
+
+ pref_service_->ClearPref(prefs::kSyncMaxInvalidationVersions);
+
pref_service_->ScheduleSavePersistentPrefs();
}
@@ -193,6 +198,74 @@ void SyncPrefs::SetEncryptionBootstrapToken(const std::string& token) {
pref_service_->ScheduleSavePersistentPrefs();
}
+sync_notifier::InvalidationVersionMap SyncPrefs::GetAllMaxVersions() const {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ if (!pref_service_) {
+ return sync_notifier::InvalidationVersionMap();
+ }
+ // Complicated gross code to convert from a string -> string
+ // DictionaryValue to a ModelType -> int64 map.
+ const base::DictionaryValue* max_versions_dict =
+ pref_service_->GetDictionary(prefs::kSyncMaxInvalidationVersions);
+ CHECK(max_versions_dict);
+ sync_notifier::InvalidationVersionMap max_versions;
+ for (base::DictionaryValue::key_iterator it =
+ max_versions_dict->begin_keys();
+ it != max_versions_dict->end_keys(); ++it) {
+ int model_type_int = 0;
+ if (!base::StringToInt(*it, &model_type_int)) {
+ LOG(WARNING) << "Invalid model type key: " << *it;
+ continue;
+ }
+ if ((model_type_int < syncable::FIRST_REAL_MODEL_TYPE) ||
+ (model_type_int >= syncable::MODEL_TYPE_COUNT)) {
+ LOG(WARNING) << "Out-of-range model type key: " << model_type_int;
+ continue;
+ }
+ const syncable::ModelType model_type =
+ syncable::ModelTypeFromInt(model_type_int);
+ std::string max_version_str;
+ CHECK(max_versions_dict->GetString(*it, &max_version_str));
+ int64 max_version = 0;
+ if (!base::StringToInt64(max_version_str, &max_version)) {
+ LOG(WARNING) << "Invalid max invalidation version for "
+ << syncable::ModelTypeToString(model_type) << ": "
+ << max_version_str;
+ continue;
+ }
+ max_versions[model_type] = max_version;
+ }
+ return max_versions;
+}
+
+void SyncPrefs::SetMaxVersion(syncable::ModelType model_type,
+ int64 max_version) {
+ DCHECK(non_thread_safe_.CalledOnValidThread());
+ DCHECK(syncable::IsRealDataType(model_type));
+ CHECK(pref_service_);
+ sync_notifier::InvalidationVersionMap max_versions =
+ GetAllMaxVersions();
+ sync_notifier::InvalidationVersionMap::iterator it =
+ max_versions.find(model_type);
+ if ((it != max_versions.end()) && (max_version <= it->second)) {
+ NOTREACHED();
+ return;
+ }
+ max_versions[model_type] = max_version;
+
+ // Gross code to convert from a ModelType -> int64 map to a string
+ // -> string DictionaryValue.
+ base::DictionaryValue max_versions_dict;
+ for (sync_notifier::InvalidationVersionMap::const_iterator it =
+ max_versions.begin();
+ it != max_versions.end(); ++it) {
+ max_versions_dict.SetString(
+ base::IntToString(it->first),
+ base::Int64ToString(it->second));
+ }
+ pref_service_->Set(prefs::kSyncMaxInvalidationVersions, max_versions_dict);
+}
+
void SyncPrefs::AcknowledgeSyncedTypes(
const syncable::ModelTypeSet& types) {
DCHECK(non_thread_safe_.CalledOnValidThread());
@@ -362,6 +435,9 @@ void SyncPrefs::RegisterPreferences() {
pref_service_->RegisterListPref(prefs::kSyncAcknowledgedSyncTypes,
syncable::ModelTypeBitSetToValue(model_set),
PrefService::UNSYNCABLE_PREF);
+
+ pref_service_->RegisterDictionaryPref(prefs::kSyncMaxInvalidationVersions,
+ PrefService::UNSYNCABLE_PREF);
}
void SyncPrefs::RegisterDataTypePreferredPref(syncable::ModelType type,
diff --git a/chrome/browser/sync/sync_prefs.h b/chrome/browser/sync/sync_prefs.h
index f8f4cda..052304a 100644
--- a/chrome/browser/sync/sync_prefs.h
+++ b/chrome/browser/sync/sync_prefs.h
@@ -8,10 +8,12 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "base/time.h"
#include "chrome/browser/prefs/pref_member.h"
+#include "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "content/common/notification_observer.h"
@@ -30,7 +32,8 @@ class SyncPrefObserver {
};
// SyncPrefs is a helper class that manages getting, setting, and
-// persisting global sync preferences.
+// persisting global sync preferences. It is not thread-safe, and
+// lives on the UI thread.
//
// TODO(akalin): Some classes still read the prefs directly. Consider
// passing down a pointer to SyncPrefs to them. A list of files:
@@ -41,7 +44,9 @@ class SyncPrefObserver {
// sync_setup_wizard.cc
// sync_setup_wizard_unittest.cc
// two_client_preferences_sync_test.cc
-class SyncPrefs : public NotificationObserver {
+class SyncPrefs : public base::SupportsWeakPtr<SyncPrefs>,
+ public sync_notifier::InvalidationVersionTracker,
+ public NotificationObserver {
public:
// |pref_service| may be NULL (for unit tests), but in that case no
// setter methods should be called. Does not take ownership of
@@ -91,6 +96,12 @@ class SyncPrefs : public NotificationObserver {
std::string GetEncryptionBootstrapToken() const;
void SetEncryptionBootstrapToken(const std::string& token);
+ // InvalidationVersionTracker implementation.
+ virtual sync_notifier::InvalidationVersionMap
+ GetAllMaxVersions() const OVERRIDE;
+ virtual void SetMaxVersion(syncable::ModelType model_type,
+ int64 max_version) OVERRIDE;
+
// Merges the given set of types with the set of acknowledged types.
void AcknowledgeSyncedTypes(const syncable::ModelTypeSet& types);
diff --git a/chrome/browser/sync/sync_prefs_unittest.cc b/chrome/browser/sync/sync_prefs_unittest.cc
index e8ae6a2..5bf2e06 100644
--- a/chrome/browser/sync/sync_prefs_unittest.cc
+++ b/chrome/browser/sync/sync_prefs_unittest.cc
@@ -115,6 +115,29 @@ TEST_F(SyncPrefsTest, PreferredTypesNotKeepEverythingSynced) {
}
}
+TEST_F(SyncPrefsTest, MaxInvalidationVersions) {
+ SyncPrefs sync_prefs(&pref_service_);
+
+ sync_notifier::InvalidationVersionMap expected_max_versions;
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+
+ expected_max_versions[syncable::BOOKMARKS] = 2;
+ sync_prefs.SetMaxVersion(syncable::BOOKMARKS, 2);
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+
+ expected_max_versions[syncable::PREFERENCES] = 5;
+ sync_prefs.SetMaxVersion(syncable::PREFERENCES, 5);
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+
+ expected_max_versions[syncable::APP_NOTIFICATIONS] = 3;
+ sync_prefs.SetMaxVersion(syncable::APP_NOTIFICATIONS, 3);
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+
+ expected_max_versions[syncable::APP_NOTIFICATIONS] = 4;
+ sync_prefs.SetMaxVersion(syncable::APP_NOTIFICATIONS, 4);
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+}
+
class MockSyncPrefObserver : public SyncPrefObserver {
public:
MOCK_METHOD1(OnSyncManagedPrefChange, void(bool));
@@ -163,6 +186,7 @@ TEST_F(SyncPrefsTest, ClearPreferences) {
EXPECT_FALSE(sync_prefs.HasSyncSetupCompleted());
EXPECT_EQ(base::Time(), sync_prefs.GetLastSyncedTime());
EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
+ EXPECT_TRUE(sync_prefs.GetAllMaxVersions().empty());
sync_prefs.SetSyncSetupCompleted();
sync_prefs.SetLastSyncedTime(base::Time::Now());
@@ -171,12 +195,19 @@ TEST_F(SyncPrefsTest, ClearPreferences) {
EXPECT_TRUE(sync_prefs.HasSyncSetupCompleted());
EXPECT_NE(base::Time(), sync_prefs.GetLastSyncedTime());
EXPECT_EQ("token", sync_prefs.GetEncryptionBootstrapToken());
+ {
+ sync_notifier::InvalidationVersionMap expected_max_versions;
+ expected_max_versions[syncable::APP_NOTIFICATIONS] = 3;
+ sync_prefs.SetMaxVersion(syncable::APP_NOTIFICATIONS, 3);
+ EXPECT_EQ(expected_max_versions, sync_prefs.GetAllMaxVersions());
+ }
sync_prefs.ClearPreferences();
EXPECT_FALSE(sync_prefs.HasSyncSetupCompleted());
EXPECT_EQ(base::Time(), sync_prefs.GetLastSyncedTime());
EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
+ EXPECT_TRUE(sync_prefs.GetAllMaxVersions().empty());
}
TEST_F(SyncPrefsTest, NullPrefService) {
@@ -190,6 +221,7 @@ TEST_F(SyncPrefsTest, NullPrefService) {
EXPECT_TRUE(sync_prefs.GetPreferredDataTypes(non_passive_types).empty());
EXPECT_FALSE(sync_prefs.IsManaged());
EXPECT_TRUE(sync_prefs.GetEncryptionBootstrapToken().empty());
+ EXPECT_TRUE(sync_prefs.GetAllMaxVersions().empty());
}
} // namespace
diff --git a/chrome/browser/sync/test_profile_sync_service.cc b/chrome/browser/sync/test_profile_sync_service.cc
index 69aa920..586cb0d 100644
--- a/chrome/browser/sync/test_profile_sync_service.cc
+++ b/chrome/browser/sync/test_profile_sync_service.cc
@@ -48,7 +48,7 @@ namespace browser_sync {
SyncBackendHostForProfileSyncTest::SyncBackendHostForProfileSyncTest(
Profile* profile,
- SyncPrefs* sync_prefs,
+ const base::WeakPtr<SyncPrefs>& sync_prefs,
bool set_initial_sync_ended_on_init,
bool synchronous_init,
bool fail_initial_download)
@@ -238,7 +238,7 @@ void TestProfileSyncService::fail_initial_download() {
void TestProfileSyncService::CreateBackend() {
backend_.reset(new browser_sync::SyncBackendHostForProfileSyncTest(
profile(),
- &sync_prefs_,
+ sync_prefs_.AsWeakPtr(),
set_initial_sync_ended_on_init_,
synchronous_backend_initialization_,
fail_initial_download_));
diff --git a/chrome/browser/sync/test_profile_sync_service.h b/chrome/browser/sync/test_profile_sync_service.h
index 6c6cd80..406c9cc 100644
--- a/chrome/browser/sync/test_profile_sync_service.h
+++ b/chrome/browser/sync/test_profile_sync_service.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
#include "chrome/browser/sync/glue/data_type_manager_impl.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/test/engine/test_id_factory.h"
@@ -31,7 +32,7 @@ class SyncBackendHostForProfileSyncTest : public SyncBackendHost {
// completed setting itself up and called us back.
SyncBackendHostForProfileSyncTest(
Profile* profile,
- SyncPrefs* sync_prefs,
+ const base::WeakPtr<SyncPrefs>& sync_prefs,
bool set_initial_sync_ended_on_init,
bool synchronous_init,
bool fail_initial_download);
diff --git a/chrome/browser/sync/tools/sync_listen_notifications.cc b/chrome/browser/sync/tools/sync_listen_notifications.cc
index 1f99c87..b7e3674 100644
--- a/chrome/browser/sync/tools/sync_listen_notifications.cc
+++ b/chrome/browser/sync/tools/sync_listen_notifications.cc
@@ -8,10 +8,13 @@
#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 "chrome/browser/sync/notifier/invalidation_version_tracker.h"
#include "chrome/browser/sync/notifier/sync_notifier.h"
#include "chrome/browser/sync/notifier/sync_notifier_factory.h"
#include "chrome/browser/sync/notifier/sync_notifier_observer.h"
@@ -32,7 +35,7 @@ class NotificationPrinter : public sync_notifier::SyncNotifierObserver {
virtual ~NotificationPrinter() {}
virtual void OnIncomingNotification(
- const syncable::ModelTypePayloadMap& type_payloads) {
+ const syncable::ModelTypePayloadMap& type_payloads) OVERRIDE {
for (syncable::ModelTypePayloadMap::const_iterator it =
type_payloads.begin(); it != type_payloads.end(); ++it) {
LOG(INFO) << "Notification: type = "
@@ -41,11 +44,12 @@ class NotificationPrinter : public sync_notifier::SyncNotifierObserver {
}
}
- virtual void OnNotificationStateChange(bool notifications_enabled) {
+ virtual void OnNotificationStateChange(
+ bool notifications_enabled) OVERRIDE {
LOG(INFO) << "Notifications enabled: " << notifications_enabled;
}
- virtual void StoreState(const std::string& state) {
+ virtual void StoreState(const std::string& state) OVERRIDE {
std::string base64_state;
CHECK(base::Base64Encode(state, &base64_state));
LOG(INFO) << "Got state to store: " << base64_state;
@@ -55,6 +59,27 @@ class NotificationPrinter : public sync_notifier::SyncNotifierObserver {
DISALLOW_COPY_AND_ASSIGN(NotificationPrinter);
};
+class NullInvalidationVersionTracker
+ : public base::SupportsWeakPtr<NullInvalidationVersionTracker>,
+ public sync_notifier::InvalidationVersionTracker {
+ public:
+ NullInvalidationVersionTracker() {}
+ virtual ~NullInvalidationVersionTracker() {}
+
+ virtual sync_notifier::InvalidationVersionMap
+ GetAllMaxVersions() const OVERRIDE {
+ return sync_notifier::InvalidationVersionMap();
+ }
+
+ virtual void SetMaxVersion(
+ syncable::ModelType model_type,
+ int64 max_invalidation_version) OVERRIDE {
+ VLOG(1) << "Setting max invalidation version for "
+ << syncable::ModelTypeToString(model_type) << " to "
+ << max_invalidation_version;
+ }
+};
+
} // namespace
int main(int argc, char* argv[]) {
@@ -95,19 +120,27 @@ int main(int argc, char* argv[]) {
const char kClientInfo[] = "sync_listen_notifications";
scoped_refptr<TestURLRequestContextGetter> request_context_getter(
new TestURLRequestContextGetter());
+ NullInvalidationVersionTracker null_invalidation_version_tracker;
sync_notifier::SyncNotifierFactory sync_notifier_factory(
- kClientInfo, request_context_getter, command_line);
+ kClientInfo, request_context_getter,
+ null_invalidation_version_tracker.AsWeakPtr(), command_line);
scoped_ptr<sync_notifier::SyncNotifier> sync_notifier(
sync_notifier_factory.CreateSyncNotifier());
NotificationPrinter notification_printer;
sync_notifier->AddObserver(&notification_printer);
+ const char kUniqueId[] = "fake_unique_id";
+ sync_notifier->SetUniqueId(kUniqueId);
+ sync_notifier->SetState("");
sync_notifier->UpdateCredentials(email, token);
{
// Listen for notifications for all known types.
syncable::ModelTypeSet types;
+ // TODO(akalin): There is a server bug where unrecognized data
+ // types mean no invalidations are sent. Change
+ // EXTENSION_SETTINGS back to MODEL_TYPE_COUNT when this is fixed.
for (int i = syncable::FIRST_REAL_MODEL_TYPE;
- i < syncable::MODEL_TYPE_COUNT; ++i) {
+ i < syncable::EXTENSION_SETTINGS; ++i) {
types.insert(syncable::ModelTypeFromInt(i));
}
sync_notifier->UpdateEnabledTypes(types);
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 51e1218..5a9eaa9 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -783,6 +783,7 @@
'browser/sync/notifier/invalidation_notifier.cc',
'browser/sync/notifier/invalidation_util.cc',
'browser/sync/notifier/invalidation_util.h',
+ 'browser/sync/notifier/invalidation_version_tracker.h',
'browser/sync/notifier/non_blocking_invalidation_notifier.h',
'browser/sync/notifier/non_blocking_invalidation_notifier.cc',
'browser/sync/notifier/p2p_notifier.h',
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index d7bed63..4d108ec 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -1380,6 +1380,10 @@ const char kSyncSuppressStart[] = "sync.suppress_start";
// if a new sync type has rolled out so we can notify the user.
const char kSyncAcknowledgedSyncTypes[] = "sync.acknowledged_types";
+// Dictionary from sync model type (as an int) to max invalidation
+// version (int64 represented as a string).
+const char kSyncMaxInvalidationVersions[] = "sync.max_invalidation_versions";
+
// A string that can be used to restore sync encryption infrastructure on
// startup so that the user doesn't need to provide credentials on each start.
const char kSyncEncryptionBootstrapToken[] =
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index 56a1b7f..3ff6669 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -505,6 +505,7 @@ extern const char kSyncUsingOAuth[];
extern const char kSyncUsingSecondaryPassphrase[];
extern const char kSyncEncryptionBootstrapToken[];
extern const char kSyncAcknowledgedSyncTypes[];
+extern const char kSyncMaxInvalidationVersions[];
extern const char kSyncPromoStartupCount[];
extern const char kSyncPromoViewCount[];