summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-27 02:02:00 +0000
committerdcheng@chromium.org <dcheng@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-27 02:02:00 +0000
commitd914f0238aa455cdb25f0782839555ec20d4be02 (patch)
tree4f60c5d8cc098eb34aa90ff015bd121e1668f4dc
parentdf52d2b635484f73cad2357e2e422d0bcf1de68f (diff)
downloadchromium_src-d914f0238aa455cdb25f0782839555ec20d4be02.zip
chromium_src-d914f0238aa455cdb25f0782839555ec20d4be02.tar.gz
chromium_src-d914f0238aa455cdb25f0782839555ec20d4be02.tar.bz2
Refactor sync-specific parts out of SyncNotifier/SyncNotifierObserver
Sort of. SendNotification() is still there. Perhaps we want to split the interfaces completely. BUG=124149 TEST=tests should still pass, no observable behavior change NOTRY=true Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=147801 Committed: http://src.chromium.org/viewvc/chrome?view=rev&revision=148496 Review URL: https://chromiumcodereview.appspot.com/10702074 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148697 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/sync/glue/DEPS2
-rw-r--r--chrome/browser/sync/glue/bridged_sync_notifier.cc22
-rw-r--r--chrome/browser/sync/glue/bridged_sync_notifier.h11
-rw-r--r--chrome/browser/sync/glue/bridged_sync_notifier_unittest.cc37
-rw-r--r--chrome/browser/sync/glue/chrome_sync_notification_bridge.cc40
-rw-r--r--chrome/browser/sync/glue/chrome_sync_notification_bridge.h5
-rw-r--r--chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc26
-rw-r--r--sync/internal_api/sync_manager_impl.cc12
-rw-r--r--sync/internal_api/sync_manager_impl.h2
-rw-r--r--sync/internal_api/syncapi_unittest.cc58
-rw-r--r--sync/notifier/chrome_invalidation_client.h7
-rw-r--r--sync/notifier/invalidation_notifier.cc47
-rw-r--r--sync/notifier/invalidation_notifier.h12
-rw-r--r--sync/notifier/invalidation_notifier_unittest.cc28
-rw-r--r--sync/notifier/invalidation_util.cc26
-rw-r--r--sync/notifier/invalidation_util.h3
-rw-r--r--sync/notifier/mock_sync_notifier_observer.h2
-rw-r--r--sync/notifier/non_blocking_invalidation_notifier.cc67
-rw-r--r--sync/notifier/non_blocking_invalidation_notifier.h12
-rw-r--r--sync/notifier/non_blocking_invalidation_notifier_unittest.cc24
-rw-r--r--sync/notifier/object_id_payload_map.cc40
-rw-r--r--sync/notifier/object_id_payload_map.h29
-rw-r--r--sync/notifier/p2p_notifier.cc46
-rw-r--r--sync/notifier/p2p_notifier.h13
-rw-r--r--sync/notifier/p2p_notifier_unittest.cc47
-rw-r--r--sync/notifier/sync_notifier.h10
-rw-r--r--sync/notifier/sync_notifier_factory_unittest.cc10
-rw-r--r--sync/notifier/sync_notifier_helper.cc95
-rw-r--r--sync/notifier/sync_notifier_helper.h55
-rw-r--r--sync/notifier/sync_notifier_helper_unittest.cc156
-rw-r--r--sync/notifier/sync_notifier_observer.h6
-rw-r--r--sync/sync.gyp15
-rw-r--r--sync/tools/sync_listen_notifications.cc10
33 files changed, 632 insertions, 343 deletions
diff --git a/chrome/browser/sync/glue/DEPS b/chrome/browser/sync/glue/DEPS
index 71e2b90..e61591f 100644
--- a/chrome/browser/sync/glue/DEPS
+++ b/chrome/browser/sync/glue/DEPS
@@ -10,8 +10,10 @@ include_rules = [
# Should these live in their own "includes" (e.g) directory(ies)?
# Bug 19878.
+ "+sync/notifier/invalidation_util.h",
"+sync/notifier/mock_sync_notifier_observer.h",
"+sync/notifier/sync_notifier.h",
+ "+sync/notifier/sync_notifier_helper.h",
"+sync/notifier/sync_notifier_factory.h",
"+sync/notifier/sync_notifier_observer.h",
diff --git a/chrome/browser/sync/glue/bridged_sync_notifier.cc b/chrome/browser/sync/glue/bridged_sync_notifier.cc
index a9de057..5e3f669 100644
--- a/chrome/browser/sync/glue/bridged_sync_notifier.cc
+++ b/chrome/browser/sync/glue/bridged_sync_notifier.cc
@@ -18,18 +18,12 @@ BridgedSyncNotifier::BridgedSyncNotifier(
BridgedSyncNotifier::~BridgedSyncNotifier() {
}
-void BridgedSyncNotifier::AddObserver(
- syncer::SyncNotifierObserver* observer) {
+void BridgedSyncNotifier::UpdateRegisteredIds(
+ syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids) {
if (delegate_.get())
- delegate_->AddObserver(observer);
- bridge_->AddObserver(observer);
-}
-
-void BridgedSyncNotifier::RemoveObserver(
- syncer::SyncNotifierObserver* observer) {
- bridge_->RemoveObserver(observer);
- if (delegate_.get())
- delegate_->RemoveObserver(observer);
+ delegate_->UpdateRegisteredIds(handler, ids);
+ bridge_->UpdateRegisteredIds(handler, ids);
}
void BridgedSyncNotifier::SetUniqueId(const std::string& unique_id) {
@@ -48,12 +42,6 @@ void BridgedSyncNotifier::UpdateCredentials(
delegate_->UpdateCredentials(email, token);
}
-void BridgedSyncNotifier::UpdateEnabledTypes(
- syncer::ModelTypeSet enabled_types) {
- if (delegate_.get())
- delegate_->UpdateEnabledTypes(enabled_types);
-}
-
void BridgedSyncNotifier::SendNotification(
syncer::ModelTypeSet changed_types) {
if (delegate_.get())
diff --git a/chrome/browser/sync/glue/bridged_sync_notifier.h b/chrome/browser/sync/glue/bridged_sync_notifier.h
index b856080ae..f48d0f9 100644
--- a/chrome/browser/sync/glue/bridged_sync_notifier.h
+++ b/chrome/browser/sync/glue/bridged_sync_notifier.h
@@ -28,18 +28,13 @@ class BridgedSyncNotifier : public syncer::SyncNotifier {
virtual ~BridgedSyncNotifier();
// SyncNotifier implementation. Passes through all calls to the delegate.
- // AddObserver/RemoveObserver will also register/deregister |observer| with
- // the bridge.
- virtual void AddObserver(
- syncer::SyncNotifierObserver* observer) OVERRIDE;
- virtual void RemoveObserver(
- syncer::SyncNotifierObserver* observer) OVERRIDE;
+ // UpdateRegisteredIds calls will also be forwarded to the bridge.
+ virtual void UpdateRegisteredIds(syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids) OVERRIDE;
virtual void SetUniqueId(const std::string& unique_id) OVERRIDE;
virtual void SetStateDeprecated(const std::string& state) OVERRIDE;
virtual void UpdateCredentials(
const std::string& email, const std::string& token) OVERRIDE;
- virtual void UpdateEnabledTypes(
- syncer::ModelTypeSet enabled_types) OVERRIDE;
virtual void SendNotification(
syncer::ModelTypeSet changed_types) OVERRIDE;
diff --git a/chrome/browser/sync/glue/bridged_sync_notifier_unittest.cc b/chrome/browser/sync/glue/bridged_sync_notifier_unittest.cc
index e12de05..7347eac 100644
--- a/chrome/browser/sync/glue/bridged_sync_notifier_unittest.cc
+++ b/chrome/browser/sync/glue/bridged_sync_notifier_unittest.cc
@@ -35,8 +35,8 @@ class MockChromeSyncNotificationBridge : public ChromeSyncNotificationBridge {
: ChromeSyncNotificationBridge(profile, sync_task_runner) {}
virtual ~MockChromeSyncNotificationBridge() {}
- MOCK_METHOD1(AddObserver, void(syncer::SyncNotifierObserver*));
- MOCK_METHOD1(RemoveObserver, void(syncer::SyncNotifierObserver*));
+ MOCK_METHOD2(UpdateRegisteredIds, void(syncer::SyncNotifierObserver*,
+ const syncer::ObjectIdSet&));
};
class MockSyncNotifier : public syncer::SyncNotifier {
@@ -44,18 +44,17 @@ class MockSyncNotifier : public syncer::SyncNotifier {
MockSyncNotifier() {}
virtual ~MockSyncNotifier() {}
- MOCK_METHOD1(AddObserver, void(syncer::SyncNotifierObserver*));
- MOCK_METHOD1(RemoveObserver, void(syncer::SyncNotifierObserver*));
+ MOCK_METHOD2(UpdateRegisteredIds,
+ void(syncer::SyncNotifierObserver*, const syncer::ObjectIdSet&));
MOCK_METHOD1(SetUniqueId, void(const std::string&));
MOCK_METHOD1(SetStateDeprecated, void(const std::string&));
MOCK_METHOD2(UpdateCredentials, void(const std::string&, const std::string&));
- MOCK_METHOD1(UpdateEnabledTypes, void(syncer::ModelTypeSet));
MOCK_METHOD1(SendNotification, void(syncer::ModelTypeSet));
};
// All tests just verify that each call is passed through to the delegate, with
-// the exception of AddObserver/RemoveObserver, which also verify the observer
-// is registered with the bridge.
+// the exception of UpdateRegisteredIds, which also verifies the call is
+// forwarded to the bridge.
class BridgedSyncNotifierTest : public testing::Test {
public:
BridgedSyncNotifierTest()
@@ -74,18 +73,13 @@ class BridgedSyncNotifierTest : public testing::Test {
BridgedSyncNotifier bridged_notifier_;
};
-TEST_F(BridgedSyncNotifierTest, AddObserver) {
+TEST_F(BridgedSyncNotifierTest, UpdateRegisteredIds) {
syncer::MockSyncNotifierObserver observer;
- EXPECT_CALL(mock_bridge_, AddObserver(&observer));
- EXPECT_CALL(*mock_delegate_, AddObserver(&observer));
- bridged_notifier_.AddObserver(&observer);
-}
-
-TEST_F(BridgedSyncNotifierTest, RemoveObserver) {
- syncer::MockSyncNotifierObserver observer;
- EXPECT_CALL(mock_bridge_, RemoveObserver(&observer));
- EXPECT_CALL(*mock_delegate_, RemoveObserver(&observer));
- bridged_notifier_.RemoveObserver(&observer);
+ EXPECT_CALL(mock_bridge_, UpdateRegisteredIds(
+ &observer, syncer::ObjectIdSet()));
+ EXPECT_CALL(*mock_delegate_, UpdateRegisteredIds(
+ &observer, syncer::ObjectIdSet()));
+ bridged_notifier_.UpdateRegisteredIds(&observer, syncer::ObjectIdSet());
}
TEST_F(BridgedSyncNotifierTest, SetUniqueId) {
@@ -107,13 +101,6 @@ TEST_F(BridgedSyncNotifierTest, UpdateCredentials) {
bridged_notifier_.UpdateCredentials(email, token);
}
-TEST_F(BridgedSyncNotifierTest, UpdateEnabledTypes) {
- syncer::ModelTypeSet enabled_types(syncer::BOOKMARKS, syncer::PREFERENCES);
- EXPECT_CALL(*mock_delegate_,
- UpdateEnabledTypes(HasModelTypes(enabled_types)));
- bridged_notifier_.UpdateEnabledTypes(enabled_types);
-}
-
TEST_F(BridgedSyncNotifierTest, SendNotification) {
syncer::ModelTypeSet changed_types(syncer::SESSIONS, syncer::EXTENSIONS);
EXPECT_CALL(*mock_delegate_, SendNotification(HasModelTypes(changed_types)));
diff --git a/chrome/browser/sync/glue/chrome_sync_notification_bridge.cc b/chrome/browser/sync/glue/chrome_sync_notification_bridge.cc
index 76b62bf..31db8e2 100644
--- a/chrome/browser/sync/glue/chrome_sync_notification_bridge.cc
+++ b/chrome/browser/sync/glue/chrome_sync_notification_bridge.cc
@@ -6,10 +6,10 @@
#include "base/bind.h"
#include "base/location.h"
-#include "base/observer_list.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
+#include "sync/notifier/sync_notifier_helper.h"
#include "sync/notifier/sync_notifier_observer.h"
using content::BrowserThread;
@@ -26,8 +26,8 @@ class ChromeSyncNotificationBridge::Core
// All member functions below must be called on the sync task runner.
void UpdateEnabledTypes(syncer::ModelTypeSet enabled_types);
- void AddObserver(syncer::SyncNotifierObserver* observer);
- void RemoveObserver(syncer::SyncNotifierObserver* observer);
+ void UpdateRegisteredIds(syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids);
void EmitNotification(
const syncer::ModelTypePayloadMap& payload_map,
@@ -43,7 +43,7 @@ class ChromeSyncNotificationBridge::Core
// Used only on |sync_task_runner_|.
syncer::ModelTypeSet enabled_types_;
- ObserverList<syncer::SyncNotifierObserver> observers_;
+ syncer::SyncNotifierHelper helper_;
};
ChromeSyncNotificationBridge::Core::Core(
@@ -64,16 +64,11 @@ void ChromeSyncNotificationBridge::Core::UpdateEnabledTypes(
enabled_types_ = types;
}
-void ChromeSyncNotificationBridge::Core::AddObserver(
- syncer::SyncNotifierObserver* observer) {
+void ChromeSyncNotificationBridge::Core::UpdateRegisteredIds(
+ syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids) {
DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- observers_.AddObserver(observer);
-}
-
-void ChromeSyncNotificationBridge::Core::RemoveObserver(
- syncer::SyncNotifierObserver* observer) {
- DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- observers_.RemoveObserver(observer);
+ helper_.UpdateRegisteredIds(handler, ids);
}
void ChromeSyncNotificationBridge::Core::EmitNotification(
@@ -85,9 +80,9 @@ void ChromeSyncNotificationBridge::Core::EmitNotification(
syncer::ModelTypePayloadMapFromEnumSet(enabled_types_, std::string()) :
payload_map;
- FOR_EACH_OBSERVER(
- syncer::SyncNotifierObserver, observers_,
- OnIncomingNotification(effective_payload_map, notification_source));
+ helper_.DispatchInvalidationsToHandlers(
+ ModelTypePayloadMapToObjectIdPayloadMap(effective_payload_map),
+ notification_source);
}
ChromeSyncNotificationBridge::ChromeSyncNotificationBridge(
@@ -111,16 +106,11 @@ void ChromeSyncNotificationBridge::UpdateEnabledTypes(
core_->UpdateEnabledTypes(types);
}
-void ChromeSyncNotificationBridge::AddObserver(
- syncer::SyncNotifierObserver* observer) {
- DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- core_->AddObserver(observer);
-}
-
-void ChromeSyncNotificationBridge::RemoveObserver(
- syncer::SyncNotifierObserver* observer) {
+void ChromeSyncNotificationBridge::UpdateRegisteredIds(
+ syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids) {
DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- core_->RemoveObserver(observer);
+ core_->UpdateRegisteredIds(handler, ids);
}
void ChromeSyncNotificationBridge::Observe(
diff --git a/chrome/browser/sync/glue/chrome_sync_notification_bridge.h b/chrome/browser/sync/glue/chrome_sync_notification_bridge.h
index bda23b4..a878ff7 100644
--- a/chrome/browser/sync/glue/chrome_sync_notification_bridge.h
+++ b/chrome/browser/sync/glue/chrome_sync_notification_bridge.h
@@ -11,6 +11,7 @@
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "sync/internal_api/public/base/model_type.h"
+#include "sync/notifier/invalidation_util.h"
class Profile;
@@ -38,8 +39,8 @@ class ChromeSyncNotificationBridge : public content::NotificationObserver {
// Must be called on the sync task runner.
void UpdateEnabledTypes(syncer::ModelTypeSet enabled_types);
// Marked virtual for tests.
- virtual void AddObserver(syncer::SyncNotifierObserver* observer);
- virtual void RemoveObserver(syncer::SyncNotifierObserver* observer);
+ virtual void UpdateRegisteredIds(syncer::SyncNotifierObserver* handler,
+ const syncer::ObjectIdSet& ids);
// NotificationObserver implementation. Called on UI thread.
virtual void Observe(int type,
diff --git a/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc b/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
index 1b097eb..acf0898 100644
--- a/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
+++ b/chrome/browser/sync/glue/chrome_sync_notification_bridge_unittest.cc
@@ -44,7 +44,7 @@ class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver {
FakeSyncNotifierObserver(
const scoped_refptr<base::SequencedTaskRunner>& sync_task_runner,
ChromeSyncNotificationBridge* bridge,
- const syncer::ModelTypePayloadMap& expected_payloads,
+ const syncer::ObjectIdPayloadMap& expected_payloads,
syncer::IncomingNotificationSource expected_source)
: sync_task_runner_(sync_task_runner),
bridge_(bridge),
@@ -53,17 +53,23 @@ class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver {
expected_payloads_(expected_payloads),
expected_source_(expected_source) {
DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- bridge_->AddObserver(this);
+ // TODO(dcheng): We might want a function to go from ObjectIdPayloadMap ->
+ // ObjectIdSet to avoid this rather long incantation...
+ const syncer::ObjectIdSet& ids = syncer::ModelTypeSetToObjectIdSet(
+ syncer::ModelTypePayloadMapToEnumSet(
+ syncer::ObjectIdPayloadMapToModelTypePayloadMap(
+ expected_payloads)));
+ bridge_->UpdateRegisteredIds(this, ids);
}
virtual ~FakeSyncNotifierObserver() {
DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
- bridge_->RemoveObserver(this);
+ bridge_->UpdateRegisteredIds(this, syncer::ObjectIdSet());
}
// SyncNotifierObserver implementation.
virtual void OnIncomingNotification(
- const syncer::ModelTypePayloadMap& type_payloads,
+ const syncer::ObjectIdPayloadMap& id_payloads,
syncer::IncomingNotificationSource source) OVERRIDE {
DCHECK(sync_task_runner_->RunsTasksOnCurrentThread());
notification_count_++;
@@ -71,7 +77,7 @@ class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver {
LOG(ERROR) << "Received notification with wrong source";
received_improper_notification_ = true;
}
- if (expected_payloads_ != type_payloads) {
+ if (expected_payloads_ != id_payloads) {
LOG(ERROR) << "Received wrong payload";
received_improper_notification_ = true;
}
@@ -94,7 +100,7 @@ class FakeSyncNotifierObserver : public syncer::SyncNotifierObserver {
ChromeSyncNotificationBridge* const bridge_;
bool received_improper_notification_;
size_t notification_count_;
- const syncer::ModelTypePayloadMap expected_payloads_;
+ const syncer::ObjectIdPayloadMap expected_payloads_;
const syncer::IncomingNotificationSource expected_source_;
};
@@ -136,14 +142,16 @@ class ChromeSyncNotificationBridgeTest : public testing::Test {
}
void CreateObserverWithExpectations(
- syncer::ModelTypePayloadMap expected_payloads,
+ const syncer::ModelTypePayloadMap& expected_payloads,
syncer::IncomingNotificationSource expected_source) {
+ const syncer::ObjectIdPayloadMap& expected_id_payloads =
+ syncer::ModelTypePayloadMapToObjectIdPayloadMap(expected_payloads);
ASSERT_TRUE(sync_thread_.message_loop_proxy()->PostTask(
FROM_HERE,
base::Bind(
&ChromeSyncNotificationBridgeTest::CreateObserverOnSyncThread,
base::Unretained(this),
- expected_payloads,
+ expected_id_payloads,
expected_source)));
BlockForSyncThread();
}
@@ -182,7 +190,7 @@ class ChromeSyncNotificationBridgeTest : public testing::Test {
}
void CreateObserverOnSyncThread(
- syncer::ModelTypePayloadMap expected_payloads,
+ const syncer::ObjectIdPayloadMap& expected_payloads,
syncer::IncomingNotificationSource expected_source) {
DCHECK(sync_thread_.message_loop_proxy()->RunsTasksOnCurrentThread());
sync_observer_ = new FakeSyncNotifierObserver(
diff --git a/sync/internal_api/sync_manager_impl.cc b/sync/internal_api/sync_manager_impl.cc
index 547dae8..98ba4a3 100644
--- a/sync/internal_api/sync_manager_impl.cc
+++ b/sync/internal_api/sync_manager_impl.cc
@@ -39,6 +39,7 @@
#include "sync/js/js_event_details.h"
#include "sync/js/js_event_handler.h"
#include "sync/js/js_reply_handler.h"
+#include "sync/notifier/invalidation_util.h"
#include "sync/notifier/notifications_disabled_reason.h"
#include "sync/notifier/sync_notifier.h"
#include "sync/protocol/encryption.pb.h"
@@ -481,8 +482,6 @@ bool SyncManagerImpl::Init(
if (!success)
return false;
- sync_notifier_->AddObserver(this);
-
return success;
}
@@ -725,7 +724,8 @@ void SyncManagerImpl::UpdateCredentials(
void SyncManagerImpl::UpdateEnabledTypes(
const ModelTypeSet& enabled_types) {
DCHECK(thread_checker_.CalledOnValidThread());
- sync_notifier_->UpdateEnabledTypes(enabled_types);
+ sync_notifier_->UpdateRegisteredIds(this,
+ ModelTypeSetToObjectIdSet(enabled_types));
}
void SyncManagerImpl::SetEncryptionPassphrase(
@@ -1195,7 +1195,7 @@ void SyncManagerImpl::ShutdownOnSyncThread() {
RemoveObserver(&debug_info_event_listener_);
if (sync_notifier_.get()) {
- sync_notifier_->RemoveObserver(this);
+ sync_notifier_->UpdateRegisteredIds(this, ObjectIdSet());
}
sync_notifier_.reset();
@@ -1781,9 +1781,11 @@ void SyncManagerImpl::OnNotificationsDisabled(
}
void SyncManagerImpl::OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) {
DCHECK(thread_checker_.CalledOnValidThread());
+ const ModelTypePayloadMap& type_payloads =
+ ObjectIdPayloadMapToModelTypePayloadMap(id_payloads);
if (source == LOCAL_NOTIFICATION) {
scheduler_->ScheduleNudgeWithPayloadsAsync(
TimeDelta::FromMilliseconds(kSyncRefreshDelayMsec),
diff --git a/sync/internal_api/sync_manager_impl.h b/sync/internal_api/sync_manager_impl.h
index b353c42..bcb2c97 100644
--- a/sync/internal_api/sync_manager_impl.h
+++ b/sync/internal_api/sync_manager_impl.h
@@ -167,7 +167,7 @@ class SyncManagerImpl : public SyncManager,
virtual void OnNotificationsDisabled(
NotificationsDisabledReason reason) OVERRIDE;
virtual void OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) OVERRIDE;
// Called only by our NetworkChangeNotifier.
diff --git a/sync/internal_api/syncapi_unittest.cc b/sync/internal_api/syncapi_unittest.cc
index 6c319fc..40a18f8 100644
--- a/sync/internal_api/syncapi_unittest.cc
+++ b/sync/internal_api/syncapi_unittest.cc
@@ -695,14 +695,12 @@ class SyncManagerObserverMock : public SyncManager::Observer {
class SyncNotifierMock : public SyncNotifier {
public:
- MOCK_METHOD1(AddObserver, void(SyncNotifierObserver*));
- MOCK_METHOD1(RemoveObserver, void(SyncNotifierObserver*));
+ MOCK_METHOD2(UpdateRegisteredIds, void(SyncNotifierObserver*,
+ const ObjectIdSet&));
MOCK_METHOD1(SetUniqueId, void(const std::string&));
MOCK_METHOD1(SetStateDeprecated, void(const std::string&));
MOCK_METHOD2(UpdateCredentials,
void(const std::string&, const std::string&));
- MOCK_METHOD1(UpdateEnabledTypes,
- void(ModelTypeSet));
MOCK_METHOD1(SendNotification, void(ModelTypeSet));
};
@@ -724,9 +722,7 @@ class SyncManagerTest : public testing::Test,
SyncManagerTest()
: sync_notifier_mock_(NULL),
- sync_manager_("Test sync manager"),
- sync_notifier_observer_(NULL),
- update_enabled_types_call_count_(0) {}
+ sync_manager_("Test sync manager") {}
virtual ~SyncManagerTest() {
EXPECT_FALSE(sync_notifier_mock_);
@@ -741,23 +737,15 @@ class SyncManagerTest : public testing::Test,
credentials.sync_token = "sometoken";
sync_notifier_mock_ = new StrictMock<SyncNotifierMock>();
- EXPECT_CALL(*sync_notifier_mock_, AddObserver(_)).
- WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierAddObserver));
EXPECT_CALL(*sync_notifier_mock_, SetUniqueId(_));
EXPECT_CALL(*sync_notifier_mock_, SetStateDeprecated(""));
EXPECT_CALL(*sync_notifier_mock_,
UpdateCredentials(credentials.email, credentials.sync_token));
- EXPECT_CALL(*sync_notifier_mock_, UpdateEnabledTypes(_)).
- WillRepeatedly(
- Invoke(this, &SyncManagerTest::SyncNotifierUpdateEnabledTypes));
- EXPECT_CALL(*sync_notifier_mock_, RemoveObserver(_)).
- WillOnce(Invoke(this, &SyncManagerTest::SyncNotifierRemoveObserver));
sync_manager_.AddObserver(&observer_);
EXPECT_CALL(observer_, OnInitializationComplete(_, _)).
WillOnce(SaveArg<0>(&js_backend_));
- EXPECT_FALSE(sync_notifier_observer_);
EXPECT_FALSE(js_backend_.IsInitialized());
std::vector<ModelSafeWorker*> workers;
@@ -781,11 +769,8 @@ class SyncManagerTest : public testing::Test,
&handler_,
NULL);
- EXPECT_TRUE(sync_notifier_observer_);
EXPECT_TRUE(js_backend_.IsInitialized());
- EXPECT_EQ(0, update_enabled_types_call_count_);
-
for (ModelSafeRoutingInfo::iterator i = routing_info.begin();
i != routing_info.end(); ++i) {
type_roots_[i->first] = MakeServerNodeForType(
@@ -796,9 +781,10 @@ class SyncManagerTest : public testing::Test,
void TearDown() {
sync_manager_.RemoveObserver(&observer_);
+ EXPECT_CALL(*sync_notifier_mock_,
+ UpdateRegisteredIds(_, ObjectIdSet()));
sync_manager_.ShutdownOnSyncThread();
sync_notifier_mock_ = NULL;
- EXPECT_FALSE(sync_notifier_observer_);
PumpLoop();
}
@@ -859,26 +845,6 @@ class SyncManagerTest : public testing::Test,
return type_roots_[type];
}
- void SyncNotifierAddObserver(
- SyncNotifierObserver* sync_notifier_observer) {
- EXPECT_EQ(NULL, sync_notifier_observer_);
- sync_notifier_observer_ = sync_notifier_observer;
- }
-
- void SyncNotifierRemoveObserver(
- SyncNotifierObserver* sync_notifier_observer) {
- EXPECT_EQ(sync_notifier_observer_, sync_notifier_observer);
- sync_notifier_observer_ = NULL;
- }
-
- void SyncNotifierUpdateEnabledTypes(ModelTypeSet types) {
- ModelSafeRoutingInfo routes;
- GetModelSafeRoutingInfo(&routes);
- const ModelTypeSet expected_types = GetRoutingInfoTypes(routes);
- EXPECT_TRUE(types.Equals(expected_types));
- ++update_enabled_types_call_count_;
- }
-
void PumpLoop() {
message_loop_.RunAllPending();
}
@@ -948,8 +914,9 @@ class SyncManagerTest : public testing::Test,
DCHECK(sync_manager_.thread_checker_.CalledOnValidThread());
ModelTypePayloadMap model_types_with_payloads =
ModelTypePayloadMapFromEnumSet(model_types, std::string());
- sync_manager_.OnIncomingNotification(model_types_with_payloads,
- REMOTE_NOTIFICATION);
+ sync_manager_.OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(model_types_with_payloads),
+ REMOTE_NOTIFICATION);
}
private:
@@ -960,27 +927,24 @@ class SyncManagerTest : public testing::Test,
// Sync Id's for the roots of the enabled datatypes.
std::map<ModelType, int64> type_roots_;
FakeExtensionsActivityMonitor extensions_activity_monitor_;
- StrictMock<SyncNotifierMock>* sync_notifier_mock_;
protected:
FakeEncryptor encryptor_;
TestUnrecoverableErrorHandler handler_;
+ StrictMock<SyncNotifierMock>* sync_notifier_mock_;
SyncManagerImpl sync_manager_;
WeakHandle<JsBackend> js_backend_;
StrictMock<SyncManagerObserverMock> observer_;
- SyncNotifierObserver* sync_notifier_observer_;
- int update_enabled_types_call_count_;
};
TEST_F(SyncManagerTest, UpdateEnabledTypes) {
- EXPECT_EQ(0, update_enabled_types_call_count_);
-
ModelSafeRoutingInfo routes;
GetModelSafeRoutingInfo(&routes);
const ModelTypeSet enabled_types = GetRoutingInfoTypes(routes);
+ EXPECT_CALL(*sync_notifier_mock_,
+ UpdateRegisteredIds(_, ModelTypeSetToObjectIdSet(enabled_types)));
sync_manager_.UpdateEnabledTypes(enabled_types);
- EXPECT_EQ(1, update_enabled_types_call_count_);
}
TEST_F(SyncManagerTest, ProcessJsMessage) {
diff --git a/sync/notifier/chrome_invalidation_client.h b/sync/notifier/chrome_invalidation_client.h
index ddd5bb0..2328f99a 100644
--- a/sync/notifier/chrome_invalidation_client.h
+++ b/sync/notifier/chrome_invalidation_client.h
@@ -8,7 +8,6 @@
#ifndef SYNC_NOTIFIER_CHROME_INVALIDATION_CLIENT_H_
#define SYNC_NOTIFIER_CHROME_INVALIDATION_CLIENT_H_
-#include <map>
#include <string>
#include "base/basictypes.h"
@@ -21,8 +20,8 @@
#include "sync/internal_api/public/util/weak_handle.h"
#include "sync/notifier/chrome_system_resources.h"
#include "sync/notifier/invalidation_state_tracker.h"
-#include "sync/notifier/invalidation_util.h"
#include "sync/notifier/notifications_disabled_reason.h"
+#include "sync/notifier/object_id_payload_map.h"
#include "sync/notifier/state_writer.h"
namespace buzz {
@@ -37,10 +36,6 @@ namespace syncer {
class RegistrationManager;
-typedef std::map<invalidation::ObjectId,
- std::string,
- ObjectIdLessThan> ObjectIdPayloadMap;
-
// ChromeInvalidationClient is not thread-safe and lives on the sync
// thread.
class ChromeInvalidationClient
diff --git a/sync/notifier/invalidation_notifier.cc b/sync/notifier/invalidation_notifier.cc
index 0c629c6..3a72f32 100644
--- a/sync/notifier/invalidation_notifier.cc
+++ b/sync/notifier/invalidation_notifier.cc
@@ -34,14 +34,10 @@ InvalidationNotifier::~InvalidationNotifier() {
DCHECK(CalledOnValidThread());
}
-void InvalidationNotifier::AddObserver(SyncNotifierObserver* observer) {
+void InvalidationNotifier::UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) {
DCHECK(CalledOnValidThread());
- observers_.AddObserver(observer);
-}
-
-void InvalidationNotifier::RemoveObserver(SyncNotifierObserver* observer) {
- DCHECK(CalledOnValidThread());
- observers_.RemoveObserver(observer);
+ invalidation_client_.RegisterIds(helper_.UpdateRegisteredIds(handler, ids));
}
void InvalidationNotifier::SetUniqueId(const std::string& unique_id) {
@@ -85,22 +81,6 @@ void InvalidationNotifier::UpdateCredentials(
invalidation_client_.UpdateCredentials(email, token);
}
-void InvalidationNotifier::UpdateEnabledTypes(ModelTypeSet enabled_types) {
- DCHECK(CalledOnValidThread());
- CHECK(!invalidation_client_id_.empty());
- ObjectIdSet ids;
- for (ModelTypeSet::Iterator it = enabled_types.First(); it.Good();
- it.Inc()) {
- invalidation::ObjectId id;
- if (!RealModelTypeToObjectId(it.Get(), &id)) {
- DLOG(WARNING) << "Invalid model type " << it.Get();
- continue;
- }
- ids.insert(id);
- }
- invalidation_client_.RegisterIds(ids);
-}
-
void InvalidationNotifier::SendNotification(ModelTypeSet changed_types) {
DCHECK(CalledOnValidThread());
// Do nothing.
@@ -108,33 +88,18 @@ void InvalidationNotifier::SendNotification(ModelTypeSet changed_types) {
void InvalidationNotifier::OnInvalidate(const ObjectIdPayloadMap& id_payloads) {
DCHECK(CalledOnValidThread());
- // TODO(dcheng): This should probably be a utility function somewhere...
- ModelTypePayloadMap type_payloads;
- for (ObjectIdPayloadMap::const_iterator it = id_payloads.begin();
- it != id_payloads.end(); ++it) {
- ModelType model_type;
- if (!ObjectIdToRealModelType(it->first, &model_type)) {
- DLOG(WARNING) << "Invalid object ID: " << ObjectIdToString(it->first);
- continue;
- }
- type_payloads[model_type] = it->second;
- }
- FOR_EACH_OBSERVER(
- SyncNotifierObserver, observers_,
- OnIncomingNotification(type_payloads, REMOTE_NOTIFICATION));
+ helper_.DispatchInvalidationsToHandlers(id_payloads, REMOTE_NOTIFICATION);
}
void InvalidationNotifier::OnNotificationsEnabled() {
DCHECK(CalledOnValidThread());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnNotificationsEnabled());
+ helper_.EmitOnNotificationsEnabled();
}
void InvalidationNotifier::OnNotificationsDisabled(
NotificationsDisabledReason reason) {
DCHECK(CalledOnValidThread());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnNotificationsDisabled(reason));
+ helper_.EmitOnNotificationsDisabled(reason);
}
} // namespace syncer
diff --git a/sync/notifier/invalidation_notifier.h b/sync/notifier/invalidation_notifier.h
index c287efb..8d74552 100644
--- a/sync/notifier/invalidation_notifier.h
+++ b/sync/notifier/invalidation_notifier.h
@@ -17,13 +17,13 @@
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
-#include "base/observer_list.h"
#include "base/threading/non_thread_safe.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/util/weak_handle.h"
#include "sync/notifier/chrome_invalidation_client.h"
#include "sync/notifier/invalidation_state_tracker.h"
#include "sync/notifier/sync_notifier.h"
+#include "sync/notifier/sync_notifier_helper.h"
namespace notifier {
class PushClient;
@@ -49,13 +49,12 @@ class InvalidationNotifier
virtual ~InvalidationNotifier();
// SyncNotifier implementation.
- virtual void AddObserver(SyncNotifierObserver* observer) OVERRIDE;
- virtual void RemoveObserver(SyncNotifierObserver* observer) OVERRIDE;
+ virtual void UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) OVERRIDE;
virtual void SetUniqueId(const std::string& unique_id) OVERRIDE;
virtual void SetStateDeprecated(const std::string& state) OVERRIDE;
virtual void UpdateCredentials(
const std::string& email, const std::string& token) OVERRIDE;
- virtual void UpdateEnabledTypes(ModelTypeSet enabled_types) OVERRIDE;
virtual void SendNotification(ModelTypeSet changed_types) OVERRIDE;
// ChromeInvalidationClient::Listener implementation.
@@ -76,6 +75,8 @@ class InvalidationNotifier
};
State state_;
+ SyncNotifierHelper helper_;
+
// Passed to |invalidation_client_|.
const InvalidationVersionMap initial_max_invalidation_versions_;
@@ -86,9 +87,6 @@ class InvalidationNotifier
// Passed to |invalidation_client_|.
const std::string client_info_;
- // Our observers (which must live on the same thread).
- ObserverList<SyncNotifierObserver> observers_;
-
// The client ID to pass to |chrome_invalidation_client_|.
std::string invalidation_client_id_;
diff --git a/sync/notifier/invalidation_notifier_unittest.cc b/sync/notifier/invalidation_notifier_unittest.cc
index b0b64c7..4a07678 100644
--- a/sync/notifier/invalidation_notifier_unittest.cc
+++ b/sync/notifier/invalidation_notifier_unittest.cc
@@ -50,11 +50,10 @@ class InvalidationNotifierTest : public testing::Test {
initial_invalidation_state,
MakeWeakHandle(mock_tracker_.AsWeakPtr()),
"fake_client_info"));
- invalidation_notifier_->AddObserver(&mock_observer_);
}
void ResetNotifier() {
- invalidation_notifier_->RemoveObserver(&mock_observer_);
+ invalidation_notifier_->UpdateRegisteredIds(&mock_observer_, ObjectIdSet());
// Stopping the invalidation notifier stops its scheduler, which deletes any
// pending tasks without running them. Some tasks "run and delete" another
// task, so they must be run in order to avoid leaking the inner task.
@@ -75,15 +74,16 @@ TEST_F(InvalidationNotifierTest, Basic) {
CreateAndObserveNotifier("fake_state");
InSequence dummy;
- ModelTypePayloadMap type_payloads;
- type_payloads[PREFERENCES] = "payload";
- type_payloads[BOOKMARKS] = "payload";
- type_payloads[AUTOFILL] = "payload";
+ ModelTypeSet models(PREFERENCES, BOOKMARKS, AUTOFILL);
+ invalidation_notifier_->UpdateRegisteredIds(
+ &mock_observer_, ModelTypeSetToObjectIdSet(models));
+ const ModelTypePayloadMap& type_payloads =
+ ModelTypePayloadMapFromEnumSet(models, "payload");
EXPECT_CALL(mock_observer_, OnNotificationsEnabled());
- EXPECT_CALL(mock_observer_,
- OnIncomingNotification(type_payloads,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(type_payloads),
+ REMOTE_NOTIFICATION));
EXPECT_CALL(mock_observer_,
OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
EXPECT_CALL(mock_observer_,
@@ -99,14 +99,8 @@ TEST_F(InvalidationNotifierTest, Basic) {
invalidation_notifier_->OnNotificationsEnabled();
- ObjectIdPayloadMap id_payloads;
- for (ModelTypePayloadMap::const_iterator it = type_payloads.begin();
- it != type_payloads.end(); ++it) {
- invalidation::ObjectId id;
- ASSERT_TRUE(RealModelTypeToObjectId(it->first, &id));
- id_payloads[id] = "payload";
- }
- invalidation_notifier_->OnInvalidate(id_payloads);
+ invalidation_notifier_->OnInvalidate(
+ ModelTypePayloadMapToObjectIdPayloadMap(type_payloads));
invalidation_notifier_->OnNotificationsDisabled(
TRANSIENT_NOTIFICATION_ERROR);
diff --git a/sync/notifier/invalidation_util.cc b/sync/notifier/invalidation_util.cc
index 0065b50..5b18d66 100644
--- a/sync/notifier/invalidation_util.cc
+++ b/sync/notifier/invalidation_util.cc
@@ -33,6 +33,32 @@ bool ObjectIdToRealModelType(const invalidation::ObjectId& object_id,
return NotificationTypeToRealModelType(object_id.name(), model_type);
}
+ObjectIdSet ModelTypeSetToObjectIdSet(const ModelTypeSet& model_types) {
+ ObjectIdSet ids;
+ for (ModelTypeSet::Iterator it = model_types.First(); it.Good(); it.Inc()) {
+ invalidation::ObjectId model_type_as_id;
+ if (!RealModelTypeToObjectId(it.Get(), &model_type_as_id)) {
+ DLOG(WARNING) << "Invalid model type " << it.Get();
+ continue;
+ }
+ ids.insert(model_type_as_id);
+ }
+ return ids;
+}
+
+ModelTypeSet ObjectIdSetToModelTypeSet(const ObjectIdSet& ids) {
+ ModelTypeSet model_types;
+ for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+ ModelType model_type;
+ if (!ObjectIdToRealModelType(*it, &model_type)) {
+ DLOG(WARNING) << "Invalid object ID " << ObjectIdToString(*it);
+ continue;
+ }
+ model_types.Put(model_type);
+ }
+ return model_types;
+}
+
std::string ObjectIdToString(
const invalidation::ObjectId& object_id) {
std::stringstream ss;
diff --git a/sync/notifier/invalidation_util.h b/sync/notifier/invalidation_util.h
index 1a706ef..bc43523 100644
--- a/sync/notifier/invalidation_util.h
+++ b/sync/notifier/invalidation_util.h
@@ -34,6 +34,9 @@ bool RealModelTypeToObjectId(ModelType model_type,
bool ObjectIdToRealModelType(const invalidation::ObjectId& object_id,
ModelType* model_type);
+ObjectIdSet ModelTypeSetToObjectIdSet(const ModelTypeSet& models);
+ModelTypeSet ObjectIdSetToModelTypeSet(const ObjectIdSet& ids);
+
std::string ObjectIdToString(const invalidation::ObjectId& object_id);
std::string InvalidationToString(
diff --git a/sync/notifier/mock_sync_notifier_observer.h b/sync/notifier/mock_sync_notifier_observer.h
index b3baeb9..fc88c52 100644
--- a/sync/notifier/mock_sync_notifier_observer.h
+++ b/sync/notifier/mock_sync_notifier_observer.h
@@ -20,7 +20,7 @@ class MockSyncNotifierObserver : public SyncNotifierObserver {
MOCK_METHOD0(OnNotificationsEnabled, void());
MOCK_METHOD1(OnNotificationsDisabled, void(NotificationsDisabledReason));
MOCK_METHOD2(OnIncomingNotification,
- void(const ModelTypePayloadMap&, IncomingNotificationSource));
+ void(const ObjectIdPayloadMap&, IncomingNotificationSource));
};
} // namespace syncer
diff --git a/sync/notifier/non_blocking_invalidation_notifier.cc b/sync/notifier/non_blocking_invalidation_notifier.cc
index 6ec7849..ac0f76a 100644
--- a/sync/notifier/non_blocking_invalidation_notifier.cc
+++ b/sync/notifier/non_blocking_invalidation_notifier.cc
@@ -33,10 +33,10 @@ class NonBlockingInvalidationNotifier::Core
const WeakHandle<InvalidationStateTracker>& invalidation_state_tracker,
const std::string& client_info);
void Teardown();
+ void UpdateRegisteredIds(const ObjectIdSet& ids);
void SetUniqueId(const std::string& unique_id);
void SetStateDeprecated(const std::string& state);
void UpdateCredentials(const std::string& email, const std::string& token);
- void UpdateEnabledTypes(ModelTypeSet enabled_types);
// SyncNotifierObserver implementation (all called on I/O thread by
// InvalidationNotifier).
@@ -44,7 +44,7 @@ class NonBlockingInvalidationNotifier::Core
virtual void OnNotificationsDisabled(
NotificationsDisabledReason reason) OVERRIDE;
virtual void OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) OVERRIDE;
private:
@@ -89,17 +89,22 @@ void NonBlockingInvalidationNotifier::Core::Initialize(
initial_invalidation_state,
invalidation_state_tracker,
client_info));
- invalidation_notifier_->AddObserver(this);
}
void NonBlockingInvalidationNotifier::Core::Teardown() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
- invalidation_notifier_->RemoveObserver(this);
+ invalidation_notifier_->UpdateRegisteredIds(this, ObjectIdSet());
invalidation_notifier_.reset();
network_task_runner_ = NULL;
}
+void NonBlockingInvalidationNotifier::Core::UpdateRegisteredIds(
+ const ObjectIdSet& ids) {
+ DCHECK(network_task_runner_->BelongsToCurrentThread());
+ invalidation_notifier_->UpdateRegisteredIds(this, ids);
+}
+
void NonBlockingInvalidationNotifier::Core::SetUniqueId(
const std::string& unique_id) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
@@ -118,12 +123,6 @@ void NonBlockingInvalidationNotifier::Core::UpdateCredentials(
invalidation_notifier_->UpdateCredentials(email, token);
}
-void NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes(
- ModelTypeSet enabled_types) {
- DCHECK(network_task_runner_->BelongsToCurrentThread());
- invalidation_notifier_->UpdateEnabledTypes(enabled_types);
-}
-
void NonBlockingInvalidationNotifier::Core::OnNotificationsEnabled() {
DCHECK(network_task_runner_->BelongsToCurrentThread());
delegate_observer_.Call(FROM_HERE,
@@ -138,12 +137,11 @@ void NonBlockingInvalidationNotifier::Core::OnNotificationsDisabled(
}
void NonBlockingInvalidationNotifier::Core::OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
- IncomingNotificationSource source) {
+ const ObjectIdPayloadMap& id_payloads, IncomingNotificationSource source) {
DCHECK(network_task_runner_->BelongsToCurrentThread());
delegate_observer_.Call(FROM_HERE,
&SyncNotifierObserver::OnIncomingNotification,
- type_payloads,
+ id_payloads,
source);
}
@@ -185,16 +183,19 @@ NonBlockingInvalidationNotifier::~NonBlockingInvalidationNotifier() {
}
}
-void NonBlockingInvalidationNotifier::AddObserver(
- SyncNotifierObserver* observer) {
+void NonBlockingInvalidationNotifier::UpdateRegisteredIds(
+ SyncNotifierObserver* handler, const ObjectIdSet& ids) {
DCHECK(parent_task_runner_->BelongsToCurrentThread());
- observers_.AddObserver(observer);
-}
-
-void NonBlockingInvalidationNotifier::RemoveObserver(
- SyncNotifierObserver* observer) {
- DCHECK(parent_task_runner_->BelongsToCurrentThread());
- observers_.RemoveObserver(observer);
+ const ObjectIdSet& all_registered_ids =
+ helper_.UpdateRegisteredIds(handler, ids);
+ if (!network_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &NonBlockingInvalidationNotifier::Core::UpdateRegisteredIds,
+ core_.get(),
+ all_registered_ids))) {
+ NOTREACHED();
+ }
}
void NonBlockingInvalidationNotifier::SetUniqueId(
@@ -231,17 +232,6 @@ void NonBlockingInvalidationNotifier::UpdateCredentials(
}
}
-void NonBlockingInvalidationNotifier::UpdateEnabledTypes(
- ModelTypeSet enabled_types) {
- DCHECK(parent_task_runner_->BelongsToCurrentThread());
- if (!network_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&NonBlockingInvalidationNotifier::Core::UpdateEnabledTypes,
- core_.get(), enabled_types))) {
- NOTREACHED();
- }
-}
-
void NonBlockingInvalidationNotifier::SendNotification(
ModelTypeSet changed_types) {
DCHECK(parent_task_runner_->BelongsToCurrentThread());
@@ -251,23 +241,20 @@ void NonBlockingInvalidationNotifier::SendNotification(
void NonBlockingInvalidationNotifier::OnNotificationsEnabled() {
DCHECK(parent_task_runner_->BelongsToCurrentThread());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnNotificationsEnabled());
+ helper_.EmitOnNotificationsEnabled();
}
void NonBlockingInvalidationNotifier::OnNotificationsDisabled(
NotificationsDisabledReason reason) {
DCHECK(parent_task_runner_->BelongsToCurrentThread());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnNotificationsDisabled(reason));
+ helper_.EmitOnNotificationsDisabled(reason);
}
void NonBlockingInvalidationNotifier::OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) {
DCHECK(parent_task_runner_->BelongsToCurrentThread());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observers_,
- OnIncomingNotification(type_payloads, source));
+ helper_.DispatchInvalidationsToHandlers(id_payloads, source);
}
} // namespace syncer
diff --git a/sync/notifier/non_blocking_invalidation_notifier.h b/sync/notifier/non_blocking_invalidation_notifier.h
index 4756a81..f76b37b 100644
--- a/sync/notifier/non_blocking_invalidation_notifier.h
+++ b/sync/notifier/non_blocking_invalidation_notifier.h
@@ -14,11 +14,11 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
#include "jingle/notifier/base/notifier_options.h"
#include "sync/internal_api/public/util/weak_handle.h"
#include "sync/notifier/invalidation_state_tracker.h"
#include "sync/notifier/sync_notifier.h"
+#include "sync/notifier/sync_notifier_helper.h"
#include "sync/notifier/sync_notifier_observer.h"
namespace base {
@@ -44,13 +44,12 @@ class NonBlockingInvalidationNotifier
virtual ~NonBlockingInvalidationNotifier();
// SyncNotifier implementation.
- virtual void AddObserver(SyncNotifierObserver* observer) OVERRIDE;
- virtual void RemoveObserver(SyncNotifierObserver* observer) OVERRIDE;
+ virtual void UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) OVERRIDE;
virtual void SetUniqueId(const std::string& unique_id) OVERRIDE;
virtual void SetStateDeprecated(const std::string& state) OVERRIDE;
virtual void UpdateCredentials(
const std::string& email, const std::string& token) OVERRIDE;
- virtual void UpdateEnabledTypes(ModelTypeSet enabled_types) OVERRIDE;
virtual void SendNotification(ModelTypeSet changed_types) OVERRIDE;
// SyncNotifierObserver implementation.
@@ -58,7 +57,7 @@ class NonBlockingInvalidationNotifier
virtual void OnNotificationsDisabled(
NotificationsDisabledReason reason) OVERRIDE;
virtual void OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) OVERRIDE;
private:
@@ -66,8 +65,7 @@ class NonBlockingInvalidationNotifier
base::WeakPtrFactory<NonBlockingInvalidationNotifier> weak_ptr_factory_;
- // Our observers (which must live on the parent thread).
- ObserverList<SyncNotifierObserver> observers_;
+ SyncNotifierHelper helper_;
// The real guts of NonBlockingInvalidationNotifier, which allows
// this class to live completely on the parent thread.
diff --git a/sync/notifier/non_blocking_invalidation_notifier_unittest.cc b/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
index 7a30f58..36f4532 100644
--- a/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
+++ b/sync/notifier/non_blocking_invalidation_notifier_unittest.cc
@@ -8,6 +8,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/threading/thread.h"
+#include "google/cacheinvalidation/v2/types.pb.h"
#include "jingle/notifier/base/fake_base_task.h"
#include "net/url_request/url_request_test_util.h"
#include "sync/internal_api/public/base/model_type.h"
@@ -45,11 +46,10 @@ class NonBlockingInvalidationNotifierTest : public testing::Test {
std::string(), // initial_invalidation_state
MakeWeakHandle(base::WeakPtr<InvalidationStateTracker>()),
"fake_client_info"));
- invalidation_notifier_->AddObserver(&mock_observer_);
}
virtual void TearDown() {
- invalidation_notifier_->RemoveObserver(&mock_observer_);
+ invalidation_notifier_->UpdateRegisteredIds(&mock_observer_, ObjectIdSet());
invalidation_notifier_.reset();
request_context_getter_ = NULL;
io_thread_.Stop();
@@ -67,15 +67,16 @@ class NonBlockingInvalidationNotifierTest : public testing::Test {
TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
InSequence dummy;
- ModelTypePayloadMap type_payloads;
- type_payloads[PREFERENCES] = "payload";
- type_payloads[BOOKMARKS] = "";
- type_payloads[AUTOFILL] = "";
+ ModelTypeSet models(PREFERENCES, BOOKMARKS, AUTOFILL);
+ invalidation_notifier_->UpdateRegisteredIds(
+ &mock_observer_, ModelTypeSetToObjectIdSet(models));
+ const ModelTypePayloadMap& type_payloads =
+ ModelTypePayloadMapFromEnumSet(models, "payload");
EXPECT_CALL(mock_observer_, OnNotificationsEnabled());
- EXPECT_CALL(mock_observer_,
- OnIncomingNotification(type_payloads,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(type_payloads),
+ REMOTE_NOTIFICATION));
EXPECT_CALL(mock_observer_,
OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
EXPECT_CALL(mock_observer_,
@@ -86,8 +87,9 @@ TEST_F(NonBlockingInvalidationNotifierTest, Basic) {
invalidation_notifier_->UpdateCredentials("foo@bar.com", "fake_token");
invalidation_notifier_->OnNotificationsEnabled();
- invalidation_notifier_->OnIncomingNotification(type_payloads,
- REMOTE_NOTIFICATION);
+ invalidation_notifier_->OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(type_payloads),
+ REMOTE_NOTIFICATION);
invalidation_notifier_->OnNotificationsDisabled(
TRANSIENT_NOTIFICATION_ERROR);
invalidation_notifier_->OnNotificationsDisabled(
diff --git a/sync/notifier/object_id_payload_map.cc b/sync/notifier/object_id_payload_map.cc
new file mode 100644
index 0000000..179f8be
--- /dev/null
+++ b/sync/notifier/object_id_payload_map.cc
@@ -0,0 +1,40 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/notifier/object_id_payload_map.h"
+
+namespace syncer {
+
+ModelTypePayloadMap ObjectIdPayloadMapToModelTypePayloadMap(
+ const ObjectIdPayloadMap& id_payloads) {
+ ModelTypePayloadMap types_with_payloads;
+ for (ObjectIdPayloadMap::const_iterator it = id_payloads.begin();
+ it != id_payloads.end(); ++it) {
+ ModelType model_type;
+ if (!ObjectIdToRealModelType(it->first, &model_type)) {
+ DLOG(WARNING) << "Invalid object ID: "
+ << ObjectIdToString(it->first);
+ continue;
+ }
+ types_with_payloads[model_type] = it->second;
+ }
+ return types_with_payloads;
+}
+
+ObjectIdPayloadMap ModelTypePayloadMapToObjectIdPayloadMap(
+ const ModelTypePayloadMap& type_payloads) {
+ ObjectIdPayloadMap id_payloads;
+ for (ModelTypePayloadMap::const_iterator it = type_payloads.begin();
+ it != type_payloads.end(); ++it) {
+ invalidation::ObjectId id;
+ if (!RealModelTypeToObjectId(it->first, &id)) {
+ DLOG(WARNING) << "Invalid model type " << it->first;
+ continue;
+ }
+ id_payloads[id] = it->second;
+ }
+ return id_payloads;
+}
+
+} // namespace syncer
diff --git a/sync/notifier/object_id_payload_map.h b/sync/notifier/object_id_payload_map.h
new file mode 100644
index 0000000..9205326
--- /dev/null
+++ b/sync/notifier/object_id_payload_map.h
@@ -0,0 +1,29 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_NOTIFIER_OBJECT_ID_PAYLOAD_MAP_H_
+#define SYNC_NOTIFIER_OBJECT_ID_PAYLOAD_MAP_H_
+
+#include <map>
+#include <string>
+
+#include "google/cacheinvalidation/include/types.h"
+#include "sync/internal_api/public/base/model_type_payload_map.h"
+#include "sync/notifier/invalidation_util.h"
+
+namespace syncer {
+
+typedef std::map<invalidation::ObjectId,
+ std::string,
+ ObjectIdLessThan> ObjectIdPayloadMap;
+
+// Converts between ObjectIdPayloadMaps and ModelTypePayloadMaps.
+ModelTypePayloadMap ObjectIdPayloadMapToModelTypePayloadMap(
+ const ObjectIdPayloadMap& id_payloads);
+ObjectIdPayloadMap ModelTypePayloadMapToObjectIdPayloadMap(
+ const ModelTypePayloadMap& type_payloads);
+
+} // namespace syncer
+
+#endif // HOME_DCHENG_SRC_CHROMIUM_SRC_SYNC_NOTIFIER_OBJECT_ID_PAYLOAD_MAP_H_
diff --git a/sync/notifier/p2p_notifier.cc b/sync/notifier/p2p_notifier.cc
index bb16f5e..5d5aeff 100644
--- a/sync/notifier/p2p_notifier.cc
+++ b/sync/notifier/p2p_notifier.cc
@@ -12,6 +12,7 @@
#include "base/values.h"
#include "jingle/notifier/listener/push_client.h"
#include "sync/internal_api/public/base/model_type_payload_map.h"
+#include "sync/notifier/invalidation_util.h"
#include "sync/notifier/sync_notifier_observer.h"
namespace syncer {
@@ -156,14 +157,16 @@ P2PNotifier::~P2PNotifier() {
push_client_->RemoveObserver(this);
}
-void P2PNotifier::AddObserver(SyncNotifierObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observer_list_.AddObserver(observer);
-}
-
-void P2PNotifier::RemoveObserver(SyncNotifierObserver* observer) {
- DCHECK(thread_checker_.CalledOnValidThread());
- observer_list_.RemoveObserver(observer);
+void P2PNotifier::UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) {
+ const ModelTypeSet enabled_types = ObjectIdSetToModelTypeSet(
+ helper_.UpdateRegisteredIds(handler, ids));
+ const ModelTypeSet new_enabled_types =
+ Difference(enabled_types, enabled_types_);
+ const P2PNotificationData notification_data(
+ unique_id_, NOTIFY_SELF, new_enabled_types);
+ SendNotificationData(notification_data);
+ enabled_types_ = enabled_types;
}
void P2PNotifier::SetUniqueId(const std::string& unique_id) {
@@ -193,16 +196,6 @@ void P2PNotifier::UpdateCredentials(
logged_in_ = true;
}
-void P2PNotifier::UpdateEnabledTypes(ModelTypeSet enabled_types) {
- DCHECK(thread_checker_.CalledOnValidThread());
- const ModelTypeSet new_enabled_types =
- Difference(enabled_types, enabled_types_);
- enabled_types_ = enabled_types;
- const P2PNotificationData notification_data(
- unique_id_, NOTIFY_SELF, new_enabled_types);
- SendNotificationData(notification_data);
-}
-
void P2PNotifier::SendNotification(ModelTypeSet changed_types) {
DCHECK(thread_checker_.CalledOnValidThread());
const P2PNotificationData notification_data(
@@ -214,9 +207,7 @@ void P2PNotifier::OnNotificationsEnabled() {
DCHECK(thread_checker_.CalledOnValidThread());
bool just_turned_on = (notifications_enabled_ == false);
notifications_enabled_ = true;
- FOR_EACH_OBSERVER(
- SyncNotifierObserver, observer_list_,
- OnNotificationsEnabled());
+ helper_.EmitOnNotificationsEnabled();
if (just_turned_on) {
const P2PNotificationData notification_data(
unique_id_, NOTIFY_SELF, enabled_types_);
@@ -227,9 +218,7 @@ void P2PNotifier::OnNotificationsEnabled() {
void P2PNotifier::OnNotificationsDisabled(
notifier::NotificationsDisabledReason reason) {
DCHECK(thread_checker_.CalledOnValidThread());
- FOR_EACH_OBSERVER(
- SyncNotifierObserver, observer_list_,
- OnNotificationsDisabled(FromNotifierReason(reason)));
+ helper_.EmitOnNotificationsDisabled(FromNotifierReason(reason));
}
void P2PNotifier::OnIncomingNotification(
@@ -266,10 +255,11 @@ void P2PNotifier::OnIncomingNotification(
DVLOG(1) << "No enabled and changed types -- not emitting notification";
return;
}
- const ModelTypePayloadMap& type_payloads =
- ModelTypePayloadMapFromEnumSet(types_to_notify, std::string());
- FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_,
- OnIncomingNotification(type_payloads, REMOTE_NOTIFICATION));
+ const ModelTypePayloadMap& type_payloads = ModelTypePayloadMapFromEnumSet(
+ notification_data.GetChangedTypes(), std::string());
+ helper_.DispatchInvalidationsToHandlers(
+ ModelTypePayloadMapToObjectIdPayloadMap(type_payloads),
+ REMOTE_NOTIFICATION);
}
void P2PNotifier::SendNotificationDataForTest(
diff --git a/sync/notifier/p2p_notifier.h b/sync/notifier/p2p_notifier.h
index a360f25..d2de89d 100644
--- a/sync/notifier/p2p_notifier.h
+++ b/sync/notifier/p2p_notifier.h
@@ -20,6 +20,7 @@
#include "sync/internal_api/public/base/model_type.h"
#include "sync/notifier/notifications_disabled_reason.h"
#include "sync/notifier/sync_notifier.h"
+#include "sync/notifier/sync_notifier_helper.h"
namespace notifier {
class PushClient;
@@ -81,9 +82,8 @@ class P2PNotificationData {
ModelTypeSet changed_types_;
};
-class P2PNotifier
- : public SyncNotifier,
- public notifier::PushClientObserver {
+class P2PNotifier : public SyncNotifier,
+ public notifier::PushClientObserver {
public:
// The |send_notification_target| parameter was added to allow us to send
// self-notifications in some cases, but not others. The value should be
@@ -96,13 +96,12 @@ class P2PNotifier
virtual ~P2PNotifier();
// SyncNotifier implementation
- virtual void AddObserver(SyncNotifierObserver* observer) OVERRIDE;
- virtual void RemoveObserver(SyncNotifierObserver* observer) OVERRIDE;
+ virtual void UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) OVERRIDE;
virtual void SetUniqueId(const std::string& unique_id) OVERRIDE;
virtual void SetStateDeprecated(const std::string& state) OVERRIDE;
virtual void UpdateCredentials(
const std::string& email, const std::string& token) OVERRIDE;
- virtual void UpdateEnabledTypes(ModelTypeSet enabled_types) OVERRIDE;
virtual void SendNotification(ModelTypeSet changed_types) OVERRIDE;
// PushClientObserver implementation.
@@ -120,7 +119,7 @@ class P2PNotifier
base::ThreadChecker thread_checker_;
- ObserverList<SyncNotifierObserver> observer_list_;
+ SyncNotifierHelper helper_;
// The push client.
scoped_ptr<notifier::PushClient> push_client_;
diff --git a/sync/notifier/p2p_notifier_unittest.cc b/sync/notifier/p2p_notifier_unittest.cc
index 055fd1b..28a73c9 100644
--- a/sync/notifier/p2p_notifier_unittest.cc
+++ b/sync/notifier/p2p_notifier_unittest.cc
@@ -8,6 +8,7 @@
#include "jingle/notifier/listener/fake_push_client.h"
#include "sync/internal_api/public/base/model_type.h"
+#include "sync/internal_api/public/base/model_type_payload_map.h"
#include "sync/notifier/mock_sync_notifier_observer.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,15 +28,14 @@ class P2PNotifierTest : public testing::Test {
scoped_ptr<notifier::PushClient>(fake_push_client_),
NOTIFY_OTHERS),
next_sent_notification_to_reflect_(0) {
- p2p_notifier_.AddObserver(&mock_observer_);
}
virtual ~P2PNotifierTest() {
- p2p_notifier_.RemoveObserver(&mock_observer_);
+ p2p_notifier_.UpdateRegisteredIds(&mock_observer_, ObjectIdSet());
}
ModelTypePayloadMap MakePayloadMap(ModelTypeSet types) {
- return ModelTypePayloadMapFromEnumSet(types, "");
+ return ModelTypePayloadMapFromEnumSet(types, std::string());
}
// Simulate receiving all the notifications we sent out since last
@@ -142,10 +142,13 @@ TEST_F(P2PNotifierTest, P2PNotificationDataNonDefault) {
TEST_F(P2PNotifierTest, NotificationsBasic) {
ModelTypeSet enabled_types(BOOKMARKS, PREFERENCES);
+ p2p_notifier_.UpdateRegisteredIds(&mock_observer_,
+ ModelTypeSetToObjectIdSet(enabled_types));
+
EXPECT_CALL(mock_observer_, OnNotificationsEnabled());
- EXPECT_CALL(mock_observer_,
- OnIncomingNotification(MakePayloadMap(enabled_types),
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(MakePayloadMap(enabled_types)),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SetUniqueId("sender");
@@ -163,8 +166,6 @@ TEST_F(P2PNotifierTest, NotificationsBasic) {
EXPECT_EQ(kEmail, fake_push_client_->email());
EXPECT_EQ(kToken, fake_push_client_->token());
- p2p_notifier_.UpdateEnabledTypes(enabled_types);
-
ReflectSentNotifications();
fake_push_client_->EnableNotifications();
@@ -186,17 +187,21 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
ModelTypeSet changed_types(THEMES, APPS);
ModelTypeSet expected_types(THEMES);
+ p2p_notifier_.UpdateRegisteredIds(&mock_observer_,
+ ModelTypeSetToObjectIdSet(enabled_types));
+
const ModelTypePayloadMap& expected_payload_map =
MakePayloadMap(expected_types);
EXPECT_CALL(mock_observer_, OnNotificationsEnabled());
EXPECT_CALL(mock_observer_,
- OnIncomingNotification(MakePayloadMap(enabled_types),
- REMOTE_NOTIFICATION));
+ OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(
+ MakePayloadMap(enabled_types)),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SetUniqueId("sender");
p2p_notifier_.UpdateCredentials("foo@bar.com", "fake_token");
- p2p_notifier_.UpdateEnabledTypes(enabled_types);
ReflectSentNotifications();
fake_push_client_->EnableNotifications();
@@ -211,8 +216,9 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(expected_payload_map,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(expected_payload_map),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SendNotificationDataForTest(
P2PNotificationData("sender", NOTIFY_SELF, changed_types));
@@ -240,8 +246,9 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(expected_payload_map,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(expected_payload_map),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SendNotificationDataForTest(
P2PNotificationData("sender2", NOTIFY_OTHERS, changed_types));
@@ -256,8 +263,9 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(expected_payload_map,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(expected_payload_map),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SendNotificationDataForTest(
P2PNotificationData("sender", NOTIFY_ALL, changed_types));
@@ -265,8 +273,9 @@ TEST_F(P2PNotifierTest, SendNotificationData) {
// Should be propagated.
Mock::VerifyAndClearExpectations(&mock_observer_);
- EXPECT_CALL(mock_observer_, OnIncomingNotification(expected_payload_map,
- REMOTE_NOTIFICATION));
+ EXPECT_CALL(mock_observer_, OnIncomingNotification(
+ ModelTypePayloadMapToObjectIdPayloadMap(expected_payload_map),
+ REMOTE_NOTIFICATION));
p2p_notifier_.SendNotificationDataForTest(
P2PNotificationData("sender2", NOTIFY_ALL, changed_types));
diff --git a/sync/notifier/sync_notifier.h b/sync/notifier/sync_notifier.h
index 0c775f4..369ced1 100644
--- a/sync/notifier/sync_notifier.h
+++ b/sync/notifier/sync_notifier.h
@@ -12,6 +12,7 @@
#include <string>
#include "sync/internal_api/public/base/model_type.h"
+#include "sync/notifier/invalidation_util.h"
namespace syncer {
class SyncNotifierObserver;
@@ -21,8 +22,11 @@ class SyncNotifier {
SyncNotifier() {}
virtual ~SyncNotifier() {}
- virtual void AddObserver(SyncNotifierObserver* observer) = 0;
- virtual void RemoveObserver(SyncNotifierObserver* observer) = 0;
+ // Updates the set of ObjectIds associated with a given |handler|. Passing an
+ // empty ObjectIdSet will unregister |handler|. If two different handlers
+ // attempt to register for the same object ID, the first registration wins.
+ virtual void UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids) = 0;
// SetUniqueId must be called once, before any call to
// UpdateCredentials. |unique_id| should be a non-empty globally
@@ -40,8 +44,6 @@ class SyncNotifier {
virtual void UpdateCredentials(
const std::string& email, const std::string& token) = 0;
- virtual void UpdateEnabledTypes(ModelTypeSet enabled_types) = 0;
-
// This is here only to support the old p2p notification implementation,
// which is still used by sync integration tests.
// TODO(akalin): Remove this once we move the integration tests off p2p
diff --git a/sync/notifier/sync_notifier_factory_unittest.cc b/sync/notifier/sync_notifier_factory_unittest.cc
index 52fd505..8036c1a 100644
--- a/sync/notifier/sync_notifier_factory_unittest.cc
+++ b/sync/notifier/sync_notifier_factory_unittest.cc
@@ -60,8 +60,9 @@ TEST_F(SyncNotifierFactoryTest, Basic) {
ASSERT_FALSE(notifier.get());
#else
ASSERT_TRUE(notifier.get());
- notifier->AddObserver(&mock_observer_);
- notifier->RemoveObserver(&mock_observer_);
+ ObjectIdSet ids = ModelTypeSetToObjectIdSet(ModelTypeSet(syncer::BOOKMARKS));
+ notifier->UpdateRegisteredIds(&mock_observer_, ids);
+ notifier->UpdateRegisteredIds(&mock_observer_, ObjectIdSet());
#endif
}
@@ -77,8 +78,9 @@ TEST_F(SyncNotifierFactoryTest, Basic_P2P) {
ASSERT_FALSE(notifier.get());
#else
ASSERT_TRUE(notifier.get());
- notifier->AddObserver(&mock_observer_);
- notifier->RemoveObserver(&mock_observer_);
+ ObjectIdSet ids = ModelTypeSetToObjectIdSet(ModelTypeSet(syncer::BOOKMARKS));
+ notifier->UpdateRegisteredIds(&mock_observer_, ids);
+ notifier->UpdateRegisteredIds(&mock_observer_, ObjectIdSet());
#endif
}
diff --git a/sync/notifier/sync_notifier_helper.cc b/sync/notifier/sync_notifier_helper.cc
new file mode 100644
index 0000000..af3b2ea
--- /dev/null
+++ b/sync/notifier/sync_notifier_helper.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "sync/notifier/sync_notifier_helper.h"
+
+#include "base/logging.h"
+
+namespace syncer {
+
+SyncNotifierHelper::SyncNotifierHelper() {}
+SyncNotifierHelper::~SyncNotifierHelper() {}
+
+ObjectIdSet SyncNotifierHelper::UpdateRegisteredIds(
+ SyncNotifierObserver* handler, const ObjectIdSet& ids) {
+ if (ids.empty()) {
+ handlers_.RemoveObserver(handler);
+ } else if (!handlers_.HasObserver(handler)) {
+ handlers_.AddObserver(handler);
+ }
+
+ ObjectIdSet registered_ids(ids);
+ // Remove all existing entries for |handler| and fill |registered_ids| with
+ // the rest.
+ for (ObjectIdHandlerMap::iterator it = id_to_handler_map_.begin();
+ it != id_to_handler_map_.end(); ) {
+ if (it->second == handler) {
+ ObjectIdHandlerMap::iterator erase_it = it;
+ ++it;
+ id_to_handler_map_.erase(erase_it);
+ } else {
+ registered_ids.insert(it->first);
+ ++it;
+ }
+ }
+
+ // Now add the entries for |handler|. We keep track of the last insertion
+ // point so we only traverse the map once to insert all the new entries.
+ ObjectIdHandlerMap::iterator insert_it = id_to_handler_map_.begin();
+ for (ObjectIdSet::const_iterator it = ids.begin(); it != ids.end(); ++it) {
+ insert_it = id_to_handler_map_.insert(insert_it,
+ std::make_pair(*it, handler));
+ CHECK_EQ(handler, insert_it->second) << "Duplicate registration for "
+ << ObjectIdToString(insert_it->first);
+ }
+ if (logging::DEBUG_MODE) {
+ // The mapping shouldn't contain any handlers that aren't in |handlers_|.
+ for (ObjectIdHandlerMap::const_iterator it = id_to_handler_map_.begin();
+ it != id_to_handler_map_.end(); ++it) {
+ CHECK(handlers_.HasObserver(it->second));
+ }
+ }
+ return registered_ids;
+}
+
+void SyncNotifierHelper::DispatchInvalidationsToHandlers(
+ const ObjectIdPayloadMap& id_payloads,
+ IncomingNotificationSource source) {
+ typedef std::map<SyncNotifierObserver*, ObjectIdPayloadMap> DispatchMap;
+ DispatchMap dispatch_map;
+ for (ObjectIdPayloadMap::const_iterator it = id_payloads.begin();
+ it != id_payloads.end(); ++it) {
+ ObjectIdHandlerMap::const_iterator find_it =
+ id_to_handler_map_.find(it->first);
+ // If we get an invalidation with a source type that we can't map to an
+ // observer, just drop it--the observer was unregistered while the
+ // invalidation was in flight.
+ if (find_it == id_to_handler_map_.end())
+ continue;
+ dispatch_map[find_it->second].insert(*it);
+ }
+
+ if (handlers_.might_have_observers()) {
+ ObserverListBase<SyncNotifierObserver>::Iterator it(handlers_);
+ SyncNotifierObserver* handler = NULL;
+ while ((handler = it.GetNext()) != NULL) {
+ DispatchMap::const_iterator dispatch_it = dispatch_map.find(handler);
+ if (dispatch_it != dispatch_map.end()) {
+ handler->OnIncomingNotification(dispatch_it->second, source);
+ }
+ }
+ }
+}
+
+void SyncNotifierHelper::EmitOnNotificationsEnabled() {
+ FOR_EACH_OBSERVER(SyncNotifierObserver, handlers_, OnNotificationsEnabled());
+}
+
+void SyncNotifierHelper::EmitOnNotificationsDisabled(
+ NotificationsDisabledReason reason) {
+ FOR_EACH_OBSERVER(SyncNotifierObserver, handlers_,
+ OnNotificationsDisabled(reason));
+}
+
+} // namespace syncer
diff --git a/sync/notifier/sync_notifier_helper.h b/sync/notifier/sync_notifier_helper.h
new file mode 100644
index 0000000..28ff187
--- /dev/null
+++ b/sync/notifier/sync_notifier_helper.h
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef SYNC_NOTIFIER_SYNC_NOTIFIER_HELPER_H_
+#define SYNC_NOTIFIER_SYNC_NOTIFIER_HELPER_H_
+
+#include <map>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "sync/notifier/invalidation_util.h"
+#include "sync/notifier/object_id_payload_map.h"
+#include "sync/notifier/sync_notifier_observer.h"
+
+namespace syncer {
+
+// A helper class for classes that want to implement the SyncNotifier interface.
+// It helps keep track of registered handlers and which object ID registrations
+// are associated with which handlers, so implementors can just reuse the logic
+// here to dispatch invalidations and other interesting notifications.
+class SyncNotifierHelper {
+ public:
+ SyncNotifierHelper();
+ ~SyncNotifierHelper();
+
+ // Updates the set of ObjectIds associated with a given |handler|. Passing an
+ // empty ObjectIdSet will unregister |handler|. The return value is an
+ // ObjectIdSet containing values for all existing handlers.
+ ObjectIdSet UpdateRegisteredIds(SyncNotifierObserver* handler,
+ const ObjectIdSet& ids);
+
+ // Helper that sorts incoming invalidations into a bucket for each handler
+ // and then dispatches the batched invalidations to the corresponding handler.
+ void DispatchInvalidationsToHandlers(const ObjectIdPayloadMap& id_payloads,
+ IncomingNotificationSource source);
+
+ // Calls the given handler method for each handler that has registered IDs.
+ void EmitOnNotificationsEnabled();
+ void EmitOnNotificationsDisabled(NotificationsDisabledReason reason);
+
+ private:
+ typedef std::map<invalidation::ObjectId,
+ SyncNotifierObserver*,
+ ObjectIdLessThan> ObjectIdHandlerMap;
+
+ ObserverList<SyncNotifierObserver> handlers_;
+ ObjectIdHandlerMap id_to_handler_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(SyncNotifierHelper);
+};
+
+} // namespace syncer
+
+#endif // SYNC_NOTIFIER_SYNC_NOTIFIER_HELPER_H_
diff --git a/sync/notifier/sync_notifier_helper_unittest.cc b/sync/notifier/sync_notifier_helper_unittest.cc
new file mode 100644
index 0000000..ba2d768
--- /dev/null
+++ b/sync/notifier/sync_notifier_helper_unittest.cc
@@ -0,0 +1,156 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "google/cacheinvalidation/v2/types.pb.h"
+#include "sync/notifier/sync_notifier_helper.h"
+#include "sync/notifier/mock_sync_notifier_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using testing::StrictMock;
+
+namespace syncer {
+
+class SyncNotifierHelperTest : public testing::Test {
+ protected:
+ SyncNotifierHelperTest()
+ : kObjectId1(ipc::invalidation::ObjectSource::TEST, "a"),
+ kObjectId2(ipc::invalidation::ObjectSource::TEST, "b"),
+ kObjectId3(ipc::invalidation::ObjectSource::TEST, "c") {
+ }
+
+ invalidation::ObjectId kObjectId1;
+ invalidation::ObjectId kObjectId2;
+ invalidation::ObjectId kObjectId3;
+};
+
+// Basic check that registrations are correctly updated for one handler.
+TEST_F(SyncNotifierHelperTest, Basic) {
+ SyncNotifierHelper helper;
+ StrictMock<MockSyncNotifierObserver> observer;
+ ObjectIdSet ids;
+ ids.insert(kObjectId1);
+ ids.insert(kObjectId2);
+ helper.UpdateRegisteredIds(&observer, ids);
+
+ ObjectIdPayloadMap dispatched_payloads;
+ dispatched_payloads[kObjectId1] = "1";
+ dispatched_payloads[kObjectId2] = "2";
+ dispatched_payloads[kObjectId3] = "3";
+
+ // A object ID with no registration should be ignored.
+ ObjectIdPayloadMap expected_payload1;
+ expected_payload1[kObjectId1] = "1";
+ expected_payload1[kObjectId2] = "2";
+ EXPECT_CALL(observer, OnIncomingNotification(expected_payload1,
+ REMOTE_NOTIFICATION));
+ helper.DispatchInvalidationsToHandlers(dispatched_payloads,
+ REMOTE_NOTIFICATION);
+
+ // Removed object IDs should not be notified, newly-added ones should.
+ ids.erase(kObjectId1);
+ ids.insert(kObjectId3);
+ helper.UpdateRegisteredIds(&observer, ids);
+
+ ObjectIdPayloadMap expected_payload2;
+ expected_payload2[kObjectId2] = "2";
+ expected_payload2[kObjectId3] = "3";
+ EXPECT_CALL(observer, OnIncomingNotification(expected_payload2,
+ REMOTE_NOTIFICATION));
+ helper.DispatchInvalidationsToHandlers(dispatched_payloads,
+ REMOTE_NOTIFICATION);
+}
+
+// Tests that we correctly bucket and dispatch invalidations on multiple objects
+// to the corresponding handlers.
+TEST_F(SyncNotifierHelperTest, MultipleHandlers) {
+ SyncNotifierHelper helper;
+ StrictMock<MockSyncNotifierObserver> observer;
+ ObjectIdSet ids;
+ ids.insert(kObjectId1);
+ ids.insert(kObjectId2);
+ helper.UpdateRegisteredIds(&observer, ids);
+ StrictMock<MockSyncNotifierObserver> observer2;
+ ObjectIdSet ids2;
+ ids2.insert(kObjectId3);
+ helper.UpdateRegisteredIds(&observer2, ids2);
+
+ ObjectIdPayloadMap expected_payload1;
+ expected_payload1[kObjectId1] = "1";
+ expected_payload1[kObjectId2] = "2";
+ EXPECT_CALL(observer, OnIncomingNotification(expected_payload1,
+ REMOTE_NOTIFICATION));
+ ObjectIdPayloadMap expected_payload2;
+ expected_payload2[kObjectId3] = "3";
+ EXPECT_CALL(observer2, OnIncomingNotification(expected_payload2,
+ REMOTE_NOTIFICATION));
+
+ ObjectIdPayloadMap dispatched_payloads;
+ dispatched_payloads[kObjectId1] = "1";
+ dispatched_payloads[kObjectId2] = "2";
+ dispatched_payloads[kObjectId3] = "3";
+ helper.DispatchInvalidationsToHandlers(dispatched_payloads,
+ REMOTE_NOTIFICATION);
+
+ // Also verify that the callbacks for OnNotificationsEnabled/Disabled work.
+ EXPECT_CALL(observer, OnNotificationsEnabled());
+ EXPECT_CALL(observer2, OnNotificationsEnabled());
+ EXPECT_CALL(observer,
+ OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
+ EXPECT_CALL(observer2,
+ OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
+ helper.EmitOnNotificationsEnabled();
+ helper.EmitOnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR);
+}
+
+// Multiple registrations by different handlers on the same object ID should
+// cause a CHECK.
+TEST_F(SyncNotifierHelperTest, MultipleRegistration) {
+ SyncNotifierHelper helper;
+ StrictMock<MockSyncNotifierObserver> observer;
+ ObjectIdSet ids;
+ ids.insert(kObjectId1);
+ ids.insert(kObjectId2);
+ helper.UpdateRegisteredIds(&observer, ids);
+
+ StrictMock<MockSyncNotifierObserver> observer2;
+ EXPECT_DEATH({ helper.UpdateRegisteredIds(&observer2, ids); },
+ "Duplicate registration for .*");
+}
+
+// Make sure that passing an empty set to UpdateRegisteredIds clears the
+// corresponding entries for the handler.
+TEST_F(SyncNotifierHelperTest, EmptySetUnregisters) {
+ SyncNotifierHelper helper;
+ StrictMock<MockSyncNotifierObserver> observer;
+ ObjectIdSet ids;
+ ids.insert(kObjectId1);
+ ids.insert(kObjectId2);
+ helper.UpdateRegisteredIds(&observer, ids);
+ // Control observer.
+ StrictMock<MockSyncNotifierObserver> observer2;
+ ObjectIdSet ids2;
+ ids2.insert(kObjectId3);
+ helper.UpdateRegisteredIds(&observer2, ids2);
+ // Unregister the first observer. It should not receive any further callbacks.
+ helper.UpdateRegisteredIds(&observer, ObjectIdSet());
+
+ ObjectIdPayloadMap expected_payload2;
+ expected_payload2[kObjectId3] = "3";
+ EXPECT_CALL(observer2, OnIncomingNotification(expected_payload2,
+ REMOTE_NOTIFICATION));
+ EXPECT_CALL(observer2, OnNotificationsEnabled());
+ EXPECT_CALL(observer2,
+ OnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR));
+
+ ObjectIdPayloadMap dispatched_payloads;
+ dispatched_payloads[kObjectId1] = "1";
+ dispatched_payloads[kObjectId2] = "2";
+ dispatched_payloads[kObjectId3] = "3";
+ helper.DispatchInvalidationsToHandlers(dispatched_payloads,
+ REMOTE_NOTIFICATION);
+ helper.EmitOnNotificationsEnabled();
+ helper.EmitOnNotificationsDisabled(TRANSIENT_NOTIFICATION_ERROR);
+}
+
+} // namespace syncer
diff --git a/sync/notifier/sync_notifier_observer.h b/sync/notifier/sync_notifier_observer.h
index eaea91f..b79f838 100644
--- a/sync/notifier/sync_notifier_observer.h
+++ b/sync/notifier/sync_notifier_observer.h
@@ -5,7 +5,7 @@
#ifndef SYNC_NOTIFIER_SYNC_NOTIFIER_OBSERVER_H_
#define SYNC_NOTIFIER_SYNC_NOTIFIER_OBSERVER_H_
-#include "sync/internal_api/public/base/model_type_payload_map.h"
+#include "sync/notifier/object_id_payload_map.h"
#include "sync/notifier/notifications_disabled_reason.h"
namespace syncer {
@@ -27,10 +27,10 @@ class SyncNotifierObserver {
virtual void OnNotificationsDisabled(
NotificationsDisabledReason reason) = 0;
- // Called when a notification is received. The per-type payloads
+ // Called when a notification is received. The per-id payloads
// are in |type_payloads| and the source is in |source|.
virtual void OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) = 0;
protected:
diff --git a/sync/sync.gyp b/sync/sync.gyp
index b517825..ea2f7b3 100644
--- a/sync/sync.gyp
+++ b/sync/sync.gyp
@@ -250,11 +250,15 @@
'sources': [
'notifier/invalidation_util.cc',
'notifier/invalidation_util.h',
- 'notifier/notifications_disabled_reason.h',
'notifier/notifications_disabled_reason.cc',
+ 'notifier/notifications_disabled_reason.h',
+ 'notifier/object_id_payload_map.cc',
+ 'notifier/object_id_payload_map.h',
'notifier/sync_notifier.h',
- 'notifier/sync_notifier_factory.h',
'notifier/sync_notifier_factory.cc',
+ 'notifier/sync_notifier_factory.h',
+ 'notifier/sync_notifier_helper.cc',
+ 'notifier/sync_notifier_helper.h',
'notifier/sync_notifier_observer.h',
],
'conditions': [
@@ -264,13 +268,13 @@
'notifier/chrome_invalidation_client.h',
'notifier/chrome_system_resources.cc',
'notifier/chrome_system_resources.h',
- 'notifier/invalidation_notifier.h',
'notifier/invalidation_notifier.cc',
+ 'notifier/invalidation_notifier.h',
'notifier/invalidation_state_tracker.h',
- 'notifier/non_blocking_invalidation_notifier.h',
'notifier/non_blocking_invalidation_notifier.cc',
- 'notifier/p2p_notifier.h',
+ 'notifier/non_blocking_invalidation_notifier.h',
'notifier/p2p_notifier.cc',
+ 'notifier/p2p_notifier.h',
'notifier/push_client_channel.cc',
'notifier/push_client_channel.h',
'notifier/registration_manager.cc',
@@ -649,6 +653,7 @@
'notifier/p2p_notifier_unittest.cc',
'notifier/push_client_channel_unittest.cc',
'notifier/registration_manager_unittest.cc',
+ 'notifier/sync_notifier_helper_unittest.cc',
],
}],
],
diff --git a/sync/tools/sync_listen_notifications.cc b/sync/tools/sync_listen_notifications.cc
index 25ebcbd..22b22d6 100644
--- a/sync/tools/sync_listen_notifications.cc
+++ b/sync/tools/sync_listen_notifications.cc
@@ -63,8 +63,10 @@ class NotificationPrinter : public SyncNotifierObserver {
}
virtual void OnIncomingNotification(
- const ModelTypePayloadMap& type_payloads,
+ const ObjectIdPayloadMap& id_payloads,
IncomingNotificationSource source) OVERRIDE {
+ const ModelTypePayloadMap& type_payloads =
+ ObjectIdPayloadMapToModelTypePayloadMap(id_payloads);
for (ModelTypePayloadMap::const_iterator it =
type_payloads.begin(); it != type_payloads.end(); ++it) {
LOG(INFO) << (source == REMOTE_NOTIFICATION ? "Remote" : "Local")
@@ -233,17 +235,17 @@ int SyncListenNotificationsMain(int argc, char* argv[]) {
scoped_ptr<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->UpdateCredentials(email, token);
// Listen for notifications for all known types.
- sync_notifier->UpdateEnabledTypes(ModelTypeSet::All());
+ sync_notifier->UpdateRegisteredIds(
+ &notification_printer, ModelTypeSetToObjectIdSet(ModelTypeSet::All()));
ui_loop.Run();
- sync_notifier->RemoveObserver(&notification_printer);
+ sync_notifier->UpdateRegisteredIds(&notification_printer, ObjectIdSet());
io_thread.Stop();
return 0;
}