diff options
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(¬ification_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[]; |