diff options
Diffstat (limited to 'sync')
-rw-r--r-- | sync/notifier/p2p_notifier.cc | 56 | ||||
-rw-r--r-- | sync/notifier/p2p_notifier.h | 37 | ||||
-rw-r--r-- | sync/notifier/p2p_notifier_unittest.cc | 148 | ||||
-rw-r--r-- | sync/notifier/sync_notifier_factory.cc | 5 |
4 files changed, 119 insertions, 127 deletions
diff --git a/sync/notifier/p2p_notifier.cc b/sync/notifier/p2p_notifier.cc index d54097b..3e9def1 100644 --- a/sync/notifier/p2p_notifier.cc +++ b/sync/notifier/p2p_notifier.cc @@ -9,8 +9,8 @@ #include "base/json/json_reader.h" #include "base/json/json_writer.h" #include "base/logging.h" +#include "base/message_loop_proxy.h" #include "base/values.h" -#include "jingle/notifier/listener/push_client.h" #include "sync/notifier/sync_notifier_observer.h" #include "sync/syncable/model_type_payload_map.h" @@ -140,62 +140,63 @@ bool P2PNotificationData::ResetFromString(const std::string& str) { return true; } -P2PNotifier::P2PNotifier(scoped_ptr<notifier::PushClient> push_client, +P2PNotifier::P2PNotifier(const notifier::NotifierOptions& notifier_options, P2PNotificationTarget send_notification_target) - : push_client_(push_client.Pass()), + : push_client_(notifier_options), logged_in_(false), notifications_enabled_(false), - send_notification_target_(send_notification_target) { + send_notification_target_(send_notification_target), + parent_message_loop_proxy_(base::MessageLoopProxy::current()) { DCHECK(send_notification_target_ == NOTIFY_OTHERS || send_notification_target_ == NOTIFY_ALL); - push_client_->AddObserver(this); + push_client_.AddObserver(this); } P2PNotifier::~P2PNotifier() { - DCHECK(non_thread_safe_.CalledOnValidThread()); - push_client_->RemoveObserver(this); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); + push_client_.RemoveObserver(this); } void P2PNotifier::AddObserver(SyncNotifierObserver* observer) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); observer_list_.AddObserver(observer); } void P2PNotifier::RemoveObserver(SyncNotifierObserver* observer) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); observer_list_.RemoveObserver(observer); } void P2PNotifier::SetUniqueId(const std::string& unique_id) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); unique_id_ = unique_id; } void P2PNotifier::SetState(const std::string& state) { - DCHECK(non_thread_safe_.CalledOnValidThread()); - // Do nothing. + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); } void P2PNotifier::UpdateCredentials( const std::string& email, const std::string& token) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); notifier::Subscription subscription; subscription.channel = kSyncP2PNotificationChannel; // There may be some subtle issues around case sensitivity of the // from field, but it doesn't matter too much since this is only // used in p2p mode (which is only used in testing). subscription.from = email; - push_client_->UpdateSubscriptions( + push_client_.UpdateSubscriptions( notifier::SubscriptionList(1, subscription)); + // If already logged in, the new credentials will take effect on the // next reconnection. - push_client_->UpdateCredentials(email, token); + push_client_.UpdateCredentials(email, token); logged_in_ = true; } void P2PNotifier::UpdateEnabledTypes( syncable::ModelTypeSet enabled_types) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); const syncable::ModelTypeSet new_enabled_types = Difference(enabled_types, enabled_types_); enabled_types_ = enabled_types; @@ -206,14 +207,14 @@ void P2PNotifier::UpdateEnabledTypes( void P2PNotifier::SendNotification( syncable::ModelTypeSet changed_types) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); const P2PNotificationData notification_data( unique_id_, send_notification_target_, changed_types); SendNotificationData(notification_data); } void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); bool disabled_to_enabled = notifications_enabled && !notifications_enabled_; notifications_enabled_ = notifications_enabled; FOR_EACH_OBSERVER(SyncNotifierObserver, observer_list_, @@ -227,7 +228,7 @@ void P2PNotifier::OnNotificationStateChange(bool notifications_enabled) { void P2PNotifier::OnIncomingNotification( const notifier::Notification& notification) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); DVLOG(1) << "Received notification " << notification.ToString(); if (!logged_in_) { DVLOG(1) << "Not logged in yet -- not emitting notification"; @@ -264,20 +265,31 @@ void P2PNotifier::OnIncomingNotification( OnIncomingNotification(type_payloads, REMOTE_NOTIFICATION)); } +void P2PNotifier::SimulateConnectForTest( + base::WeakPtr<buzz::XmppTaskParentInterface> base_task) { + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); + push_client_.SimulateConnectAndSubscribeForTest(base_task); +} + +void P2PNotifier::ReflectSentNotificationsForTest() { + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); + push_client_.ReflectSentNotificationsForTest(); +} + void P2PNotifier::SendNotificationDataForTest( const P2PNotificationData& notification_data) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); SendNotificationData(notification_data); } void P2PNotifier::SendNotificationData( const P2PNotificationData& notification_data) { - DCHECK(non_thread_safe_.CalledOnValidThread()); + DCHECK(parent_message_loop_proxy_->BelongsToCurrentThread()); notifier::Notification notification; notification.channel = kSyncP2PNotificationChannel; notification.data = notification_data.ToString(); DVLOG(1) << "Sending XMPP notification: " << notification.ToString(); - push_client_->SendNotification(notification); + push_client_.SendNotification(notification); } } // namespace sync_notifier diff --git a/sync/notifier/p2p_notifier.h b/sync/notifier/p2p_notifier.h index bc5ed6a..24b0ab3 100644 --- a/sync/notifier/p2p_notifier.h +++ b/sync/notifier/p2p_notifier.h @@ -15,14 +15,18 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "base/threading/non_thread_safe.h" -#include "jingle/notifier/listener/push_client_observer.h" +#include "jingle/notifier/base/notifier_options.h" +#include "jingle/notifier/listener/push_client.h" #include "sync/notifier/sync_notifier.h" #include "sync/syncable/model_type.h" -namespace notifier { -class PushClient; -} // namespace notifier +namespace base { +class MessageLoopProxy; +} + +namespace buzz { +class XmppTaskParentInterface; +} // namespace buzz namespace sync_notifier { @@ -82,14 +86,14 @@ class P2PNotificationData { class P2PNotifier : public SyncNotifier, - public notifier::PushClientObserver { + public notifier::PushClient::Observer { 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 // either NOTIFY_ALL to send notifications to all clients, or NOTIFY_OTHERS // to send notifications to all clients except for the one that triggered the // notification. See crbug.com/97780. - P2PNotifier(scoped_ptr<notifier::PushClient> push_client, + P2PNotifier(const notifier::NotifierOptions& notifier_options, P2PNotificationTarget send_notification_target); virtual ~P2PNotifier(); @@ -106,23 +110,30 @@ class P2PNotifier virtual void SendNotification( syncable::ModelTypeSet changed_types) OVERRIDE; - // PushClientObserver implementation. + // PushClient::Delegate implementation. virtual void OnNotificationStateChange(bool notifications_enabled) OVERRIDE; virtual void OnIncomingNotification( const notifier::Notification& notification) OVERRIDE; + // For testing. + + void SimulateConnectForTest( + base::WeakPtr<buzz::XmppTaskParentInterface> base_task); + + // Any notifications sent after this is called will be reflected, + // i.e. will be treated as an incoming notification also. + void ReflectSentNotificationsForTest(); + void SendNotificationDataForTest( const P2PNotificationData& notification_data); private: void SendNotificationData(const P2PNotificationData& notification_data); - base::NonThreadSafe non_thread_safe_; - ObserverList<SyncNotifierObserver> observer_list_; - // The push client. - scoped_ptr<notifier::PushClient> push_client_; + // The XMPP push client. + notifier::PushClient push_client_; // Our unique ID. std::string unique_id_; // Whether we have called UpdateCredentials() yet. @@ -134,8 +145,8 @@ class P2PNotifier P2PNotificationTarget send_notification_target_; syncable::ModelTypeSet enabled_types_; + scoped_refptr<base::MessageLoopProxy> parent_message_loop_proxy_; }; } // namespace sync_notifier - #endif // SYNC_NOTIFIER_P2P_NOTIFIER_H_ diff --git a/sync/notifier/p2p_notifier_unittest.cc b/sync/notifier/p2p_notifier_unittest.cc index fe1a623..ea85433 100644 --- a/sync/notifier/p2p_notifier_unittest.cc +++ b/sync/notifier/p2p_notifier_unittest.cc @@ -6,7 +6,13 @@ #include <cstddef> -#include "jingle/notifier/listener/fake_push_client.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop.h" +#include "jingle/notifier/base/fake_base_task.h" +#include "jingle/notifier/base/notifier_options.h" +#include "jingle/notifier/listener/push_client.h" +#include "net/url_request/url_request_test_util.h" #include "sync/notifier/mock_sync_notifier_observer.h" #include "sync/syncable/model_type.h" #include "testing/gtest/include/gtest/gtest.h" @@ -21,17 +27,23 @@ using ::testing::StrictMock; class P2PNotifierTest : public testing::Test { protected: - P2PNotifierTest() - : fake_push_client_(new notifier::FakePushClient()), - p2p_notifier_( - scoped_ptr<notifier::PushClient>(fake_push_client_), - NOTIFY_OTHERS), - next_sent_notification_to_reflect_(0) { - p2p_notifier_.AddObserver(&mock_observer_); + P2PNotifierTest() { + notifier_options_.request_context_getter = + new TestURLRequestContextGetter(message_loop_.message_loop_proxy()); } - virtual ~P2PNotifierTest() { - p2p_notifier_.RemoveObserver(&mock_observer_); + virtual ~P2PNotifierTest() {} + + virtual void SetUp() OVERRIDE { + p2p_notifier_.reset(new P2PNotifier(notifier_options_, NOTIFY_OTHERS)); + p2p_notifier_->AddObserver(&mock_observer_); + } + + virtual void TearDown() OVERRIDE { + message_loop_.RunAllPending(); + p2p_notifier_->RemoveObserver(&mock_observer_); + p2p_notifier_.reset(); + message_loop_.RunAllPending(); } syncable::ModelTypePayloadMap MakePayloadMap( @@ -39,28 +51,14 @@ class P2PNotifierTest : public testing::Test { return syncable::ModelTypePayloadMapFromEnumSet(types, ""); } - // Simulate receiving all the notifications we sent out since last - // time this was called. - void ReflectSentNotifications() { - const std::vector<notifier::Notification>& sent_notifications = - fake_push_client_->sent_notifications(); - for(size_t i = next_sent_notification_to_reflect_; - i < sent_notifications.size(); ++i) { - p2p_notifier_.OnIncomingNotification(sent_notifications[i]); - } - next_sent_notification_to_reflect_ = sent_notifications.size(); - } - - // Owned by |p2p_notifier_|. - notifier::FakePushClient* fake_push_client_; - P2PNotifier p2p_notifier_; + // The sockets created by the XMPP code expect an IO loop. + MessageLoopForIO message_loop_; + notifier::NotifierOptions notifier_options_; + scoped_ptr<P2PNotifier> p2p_notifier_; StrictMock<MockSyncNotifierObserver> mock_observer_; - - private: - size_t next_sent_notification_to_reflect_; + notifier::FakeBaseTask fake_base_task_; }; -// Make sure the P2PNotificationTarget <-> string conversions work. TEST_F(P2PNotifierTest, P2PNotificationTarget) { for (int i = FIRST_NOTIFICATION_TARGET; i <= LAST_NOTIFICATION_TARGET; ++i) { @@ -72,7 +70,6 @@ TEST_F(P2PNotifierTest, P2PNotificationTarget) { EXPECT_EQ(NOTIFY_SELF, P2PNotificationTargetFromString("unknown")); } -// Make sure notification targeting works correctly. TEST_F(P2PNotifierTest, P2PNotificationDataIsTargeted) { { const P2PNotificationData notification_data( @@ -97,8 +94,6 @@ TEST_F(P2PNotifierTest, P2PNotificationDataIsTargeted) { } } -// Make sure the P2PNotificationData <-> string conversions work for a -// default-constructed P2PNotificationData. TEST_F(P2PNotifierTest, P2PNotificationDataDefault) { const P2PNotificationData notification_data; EXPECT_TRUE(notification_data.IsTargeted("")); @@ -115,8 +110,6 @@ TEST_F(P2PNotifierTest, P2PNotificationDataDefault) { EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); } -// Make sure the P2PNotificationData <-> string conversions work for a -// non-default-constructed P2PNotificationData. TEST_F(P2PNotifierTest, P2PNotificationDataNonDefault) { const syncable::ModelTypeSet changed_types( syncable::BOOKMARKS, syncable::THEMES); @@ -137,10 +130,6 @@ TEST_F(P2PNotifierTest, P2PNotificationDataNonDefault) { EXPECT_TRUE(notification_data.Equals(notification_data_parsed)); } -// Set up the P2PNotifier, simulate a successful connection, and send -// a notification with the default target (NOTIFY_OTHERS). The -// observer should receive only a notification from the call to -// UpdateEnabledTypes(). TEST_F(P2PNotifierTest, NotificationsBasic) { syncable::ModelTypeSet enabled_types( syncable::BOOKMARKS, syncable::PREFERENCES); @@ -150,41 +139,23 @@ TEST_F(P2PNotifierTest, NotificationsBasic) { OnIncomingNotification(MakePayloadMap(enabled_types), REMOTE_NOTIFICATION)); - p2p_notifier_.SetUniqueId("sender"); + p2p_notifier_->ReflectSentNotificationsForTest(); - const char kEmail[] = "foo@bar.com"; - const char kToken[] = "token"; - p2p_notifier_.UpdateCredentials(kEmail, kToken); - { - notifier::Subscription expected_subscription; - expected_subscription.channel = kSyncP2PNotificationChannel; - expected_subscription.from = kEmail; - EXPECT_TRUE(notifier::SubscriptionListsEqual( - fake_push_client_->subscriptions(), - notifier::SubscriptionList(1, expected_subscription))); - } - EXPECT_EQ(kEmail, fake_push_client_->email()); - EXPECT_EQ(kToken, fake_push_client_->token()); - - p2p_notifier_.UpdateEnabledTypes(enabled_types); + p2p_notifier_->SetUniqueId("sender"); + p2p_notifier_->UpdateCredentials("foo@bar.com", "fake_token"); + p2p_notifier_->UpdateEnabledTypes(enabled_types); - ReflectSentNotifications(); - fake_push_client_->SimulateNotificationStateChange(true); + p2p_notifier_->SimulateConnectForTest(fake_base_task_.AsWeakPtr()); // Sent with target NOTIFY_OTHERS so should not be propagated to // |mock_observer_|. { syncable::ModelTypeSet changed_types( syncable::THEMES, syncable::APPS); - p2p_notifier_.SendNotification(changed_types); + p2p_notifier_->SendNotification(changed_types); } - - ReflectSentNotifications(); } -// Set up the P2PNotifier and send out notifications with various -// target settings. The notifications received by the observer should -// be consistent with the target settings. TEST_F(P2PNotifierTest, SendNotificationData) { syncable::ModelTypeSet enabled_types( syncable::BOOKMARKS, syncable::PREFERENCES); @@ -200,90 +171,91 @@ TEST_F(P2PNotifierTest, SendNotificationData) { OnIncomingNotification(MakePayloadMap(enabled_types), REMOTE_NOTIFICATION)); - p2p_notifier_.SetUniqueId("sender"); - p2p_notifier_.UpdateCredentials("foo@bar.com", "fake_token"); - p2p_notifier_.UpdateEnabledTypes(enabled_types); + p2p_notifier_->ReflectSentNotificationsForTest(); + + p2p_notifier_->SetUniqueId("sender"); + p2p_notifier_->UpdateCredentials("foo@bar.com", "fake_token"); + p2p_notifier_->UpdateEnabledTypes(enabled_types); - ReflectSentNotifications(); - fake_push_client_->SimulateNotificationStateChange(true); + p2p_notifier_->SimulateConnectForTest(fake_base_task_.AsWeakPtr()); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. Mock::VerifyAndClearExpectations(&mock_observer_); - p2p_notifier_.SendNotificationDataForTest(P2PNotificationData()); + p2p_notifier_->SendNotificationDataForTest(P2PNotificationData()); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be propagated. Mock::VerifyAndClearExpectations(&mock_observer_); EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map, REMOTE_NOTIFICATION)); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender", NOTIFY_SELF, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. Mock::VerifyAndClearExpectations(&mock_observer_); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender2", NOTIFY_SELF, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. Mock::VerifyAndClearExpectations(&mock_observer_); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender", NOTIFY_SELF, syncable::ModelTypeSet())); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender", NOTIFY_OTHERS, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be propagated. Mock::VerifyAndClearExpectations(&mock_observer_); EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map, REMOTE_NOTIFICATION)); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender2", NOTIFY_OTHERS, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. Mock::VerifyAndClearExpectations(&mock_observer_); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender2", NOTIFY_OTHERS, syncable::ModelTypeSet())); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be propagated. Mock::VerifyAndClearExpectations(&mock_observer_); EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map, REMOTE_NOTIFICATION)); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender", NOTIFY_ALL, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be propagated. Mock::VerifyAndClearExpectations(&mock_observer_); EXPECT_CALL(mock_observer_, OnIncomingNotification(changed_payload_map, REMOTE_NOTIFICATION)); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender2", NOTIFY_ALL, changed_types)); - ReflectSentNotifications(); + message_loop_.RunAllPending(); // Should be dropped. Mock::VerifyAndClearExpectations(&mock_observer_); - p2p_notifier_.SendNotificationDataForTest( + p2p_notifier_->SendNotificationDataForTest( P2PNotificationData("sender2", NOTIFY_ALL, syncable::ModelTypeSet())); - ReflectSentNotifications(); + message_loop_.RunAllPending(); } } // namespace diff --git a/sync/notifier/sync_notifier_factory.cc b/sync/notifier/sync_notifier_factory.cc index ed838b1..5c864f7 100644 --- a/sync/notifier/sync_notifier_factory.cc +++ b/sync/notifier/sync_notifier_factory.cc @@ -7,7 +7,6 @@ #include <string> #include "base/logging.h" -#include "jingle/notifier/listener/push_client.h" #include "sync/notifier/non_blocking_invalidation_notifier.h" #include "sync/notifier/p2p_notifier.h" #include "sync/notifier/sync_notifier.h" @@ -26,9 +25,7 @@ SyncNotifier* CreateDefaultSyncNotifier( // NOTIFY_OTHERS. There's no good reason to notify ourselves of our own // commits. We self-notify for now only because the integration tests rely // on this behaviour. See crbug.com/97780. - return new P2PNotifier( - notifier::PushClient::CreateDefault(notifier_options), - NOTIFY_ALL); + return new P2PNotifier(notifier_options, NOTIFY_ALL); } return new NonBlockingInvalidationNotifier( |