diff options
Diffstat (limited to 'Swiften/Chat')
-rw-r--r-- | Swiften/Chat/ChatStateMessageSender.cpp | 28 | ||||
-rw-r--r-- | Swiften/Chat/ChatStateMessageSender.h | 26 | ||||
-rw-r--r-- | Swiften/Chat/ChatStateNotifier.cpp | 61 | ||||
-rw-r--r-- | Swiften/Chat/ChatStateNotifier.h | 26 | ||||
-rw-r--r-- | Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp | 135 |
5 files changed, 139 insertions, 137 deletions
diff --git a/Swiften/Chat/ChatStateMessageSender.cpp b/Swiften/Chat/ChatStateMessageSender.cpp deleted file mode 100644 index e150d29..0000000 --- a/Swiften/Chat/ChatStateMessageSender.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#include "Swiften/Chat/ChatStateMessageSender.h" - -#include <boost/bind.hpp> - -#include "Swiften/Client/StanzaChannel.h" - -namespace Swift { - -ChatStateMessageSender::ChatStateMessageSender(ChatStateNotifier* notifier, StanzaChannel* stanzaChannel, const JID& contact) : contact_(contact) { - notifier_ = notifier; - stanzaChannel_ = stanzaChannel; - notifier_->onChatStateChanged.connect(boost::bind(&ChatStateMessageSender::handleChatStateChanged, this, _1)); -} - -void ChatStateMessageSender::handleChatStateChanged(ChatState::ChatStateType state) { - boost::shared_ptr<Message> message(new Message()); - message->setTo(contact_); - message->addPayload(boost::shared_ptr<Payload>(new ChatState(state))); - stanzaChannel_->sendMessage(message); -} - -} diff --git a/Swiften/Chat/ChatStateMessageSender.h b/Swiften/Chat/ChatStateMessageSender.h deleted file mode 100644 index d6ce40d..0000000 --- a/Swiften/Chat/ChatStateMessageSender.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2010 Kevin Smith - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. - */ - -#pragma once - -#include "Swiften/Chat/ChatStateNotifier.h" -#include "Swiften/Elements/ChatState.h" -#include "Swiften/JID/JID.h" - -namespace Swift { - class StanzaChannel; - class ChatStateMessageSender { - public: - ChatStateMessageSender(ChatStateNotifier* notifier, StanzaChannel* stanzaChannel, const JID& contact); - void setContact(const JID& contact) {contact_ = contact;}; - - private: - void handleChatStateChanged(ChatState::ChatStateType state); - ChatStateNotifier* notifier_; - StanzaChannel* stanzaChannel_; - JID contact_; - }; -} diff --git a/Swiften/Chat/ChatStateNotifier.cpp b/Swiften/Chat/ChatStateNotifier.cpp index 1aee9cf..cb7fa9a 100644 --- a/Swiften/Chat/ChatStateNotifier.cpp +++ b/Swiften/Chat/ChatStateNotifier.cpp @@ -6,32 +6,41 @@ #include "Swiften/Chat/ChatStateNotifier.h" -namespace Swift { +#include <boost/bind.hpp> -ChatStateNotifier::ChatStateNotifier() { - contactJIDHasChanged(); -} +#include "Swiften/Elements/Message.h" +#include "Swiften/Elements/ChatState.h" +#include "Swiften/Client/StanzaChannel.h" +#include "Swiften/Disco/EntityCapsProvider.h" -void ChatStateNotifier::setContactHas85Caps(bool hasCaps) { - contactHas85Caps_ = hasCaps; +namespace Swift { + +ChatStateNotifier::ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager) : stanzaChannel_(stanzaChannel), entityCapsManager_(entityCapsManager), contact_(contact) { + setContact(contact); + entityCapsManager_->onCapsChanged.connect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); } -void ChatStateNotifier::setContactIsOnline(bool online) { - contactIsOnline_ = online; +ChatStateNotifier::~ChatStateNotifier() { + entityCapsManager_->onCapsChanged.disconnect(boost::bind(&ChatStateNotifier::handleCapsChanged, this, _1)); } -void ChatStateNotifier::contactJIDHasChanged() { +void ChatStateNotifier::setContact(const JID& contact) { contactHasSentActive_ = false; - contactHas85Caps_ = false; userIsTyping_ = false; contactIsOnline_ = false; + contact_ = contact; + handleCapsChanged(contact_); +} + +void ChatStateNotifier::setContactIsOnline(bool online) { + contactIsOnline_ = online; } void ChatStateNotifier::setUserIsTyping() { bool should = contactShouldReceiveStates(); if (should && !userIsTyping_) { userIsTyping_ = true; - onChatStateChanged(ChatState::Composing); + changeState(ChatState::Composing); } } @@ -42,7 +51,7 @@ void ChatStateNotifier::userSentMessage() { void ChatStateNotifier::userCancelledNewMessage() { if (userIsTyping_) { userIsTyping_ = false; - onChatStateChanged(ChatState::Active); + changeState(ChatState::Active); } } @@ -52,10 +61,32 @@ void ChatStateNotifier::receivedMessageFromContact(bool hasActiveElement) { bool ChatStateNotifier::contactShouldReceiveStates() { /* So, yes, the XEP says to look at caps, but it also says that once you've - heard from the contact, the active state overrides this. - *HOWEVER* it says that the MUST NOT send csn if you haven't received - active is OPTIONAL behaviour for if you haven't got caps.*/ + heard from the contact, the active state overrides this. + *HOWEVER* it says that the MUST NOT send csn if you haven't received + active is OPTIONAL behaviour for if you haven't got caps.*/ return contactIsOnline_ && (contactHasSentActive_ || contactHas85Caps_); } +void ChatStateNotifier::changeState(ChatState::ChatStateType state) { + boost::shared_ptr<Message> message(new Message()); + message->setTo(contact_); + message->addPayload(boost::shared_ptr<Payload>(new ChatState(state))); + stanzaChannel_->sendMessage(message); +} + +void ChatStateNotifier::addChatStateRequest(Message::ref message) { + if (contactShouldReceiveStates()) { + message->addPayload(boost::shared_ptr<Payload>(new ChatState(ChatState::Active))); + } +} + + +void ChatStateNotifier::handleCapsChanged(const JID& jid) { + if (jid == contact_) { + DiscoInfo::ref caps = entityCapsManager_->getCaps(contact_); + bool hasCSN = caps && caps->hasFeature(ChatState::getFeatureNamespace()); + contactHas85Caps_ = hasCSN; + } +} + } diff --git a/Swiften/Chat/ChatStateNotifier.h b/Swiften/Chat/ChatStateNotifier.h index 3889b9c..1185ed0 100644 --- a/Swiften/Chat/ChatStateNotifier.h +++ b/Swiften/Chat/ChatStateNotifier.h @@ -9,23 +9,39 @@ #include "Swiften/Base/boost_bsignals.h" #include <boost/shared_ptr.hpp> +#include "Swiften/Elements/Message.h" #include "Swiften/Elements/ChatState.h" +#include "Swiften/JID/JID.h" namespace Swift { + class StanzaChannel; + class EntityCapsProvider; + class ChatStateNotifier { public: - ChatStateNotifier(); - void setContactHas85Caps(bool hasCaps); + ChatStateNotifier(StanzaChannel* stanzaChannel, const JID& contact, EntityCapsProvider* entityCapsManager); + ~ChatStateNotifier(); + + void setContact(const JID& contact); + + void addChatStateRequest(Message::ref message); + void setUserIsTyping(); - void setContactIsOnline(bool online); void userSentMessage(); void userCancelledNewMessage(); + void receivedMessageFromContact(bool hasActiveElement); + void setContactIsOnline(bool online); + + private: bool contactShouldReceiveStates(); - void contactJIDHasChanged(); + void changeState(ChatState::ChatStateType type); + void handleCapsChanged(const JID& contact); - boost::signal<void (ChatState::ChatStateType)> onChatStateChanged; private: + StanzaChannel* stanzaChannel_; + EntityCapsProvider* entityCapsManager_; + JID contact_; bool contactHas85Caps_; bool contactHasSentActive_; bool userIsTyping_; diff --git a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp index 045a245..8380330 100644 --- a/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp +++ b/Swiften/Chat/UnitTest/ChatStateNotifierTest.cpp @@ -9,41 +9,11 @@ #include <boost/bind.hpp> #include "Swiften/Chat/ChatStateNotifier.h" +#include "Swiften/Client/DummyStanzaChannel.h" +#include "Swiften/Disco/DummyEntityCapsProvider.h" using namespace Swift; - -class ChatStateMonitor { -public: - ChatStateMonitor(ChatStateNotifier* notifier) { - notifier_ = notifier; - composingCallCount = 0; - activeCallCount = 0; - notifier->onChatStateChanged.connect(boost::bind(&ChatStateMonitor::handleChatStateChanged, this, _1)); - }; - - int composingCallCount; - int activeCallCount; - ChatState::ChatStateType currentState; - -private: - void handleChatStateChanged(ChatState::ChatStateType newState) { - switch (newState) { - case ChatState::Composing: - composingCallCount++; - break; - case ChatState::Active: - activeCallCount++; - break; - default: - break; - } - currentState = newState; - }; - - ChatStateNotifier* notifier_; -}; - class ChatStateNotifierTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ChatStateNotifierTest); CPPUNIT_TEST(testStartTypingReply_CapsNotIncluded); @@ -57,101 +27,140 @@ class ChatStateNotifierTest : public CppUnit::TestFixture { CPPUNIT_TEST(testContactShouldReceiveStates_ActiveOverrideOff); CPPUNIT_TEST_SUITE_END(); -private: - ChatStateNotifier* notifier_; - ChatStateMonitor* monitor_; - public: void setUp() { - notifier_ = new ChatStateNotifier(); + stanzaChannel = new DummyStanzaChannel(); + stanzaChannel->setAvailable(true); + entityCapsProvider = new DummyEntityCapsProvider(); + notifier_ = new ChatStateNotifier(stanzaChannel, JID("foo@bar.com/baz"), entityCapsProvider); notifier_->setContactIsOnline(true); - monitor_ = new ChatStateMonitor(notifier_); } void tearDown() { delete notifier_; - delete monitor_; + delete stanzaChannel; } void testStartTypingReply_CapsNotIncluded() { - notifier_->setContactHas85Caps(false); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(0, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(0, getComposingCount()); } void testSendTwoMessages() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->setUserIsTyping(); notifier_->userSentMessage(); notifier_->setUserIsTyping(); notifier_->userSentMessage(); - CPPUNIT_ASSERT_EQUAL(2, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(2, getComposingCount()); } void testCancelledNewMessage() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->setUserIsTyping(); notifier_->userCancelledNewMessage(); - CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); - CPPUNIT_ASSERT_EQUAL(1, monitor_->activeCallCount); - CPPUNIT_ASSERT_EQUAL(ChatState::Active, monitor_->currentState); + CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); + CPPUNIT_ASSERT_EQUAL(1, getActiveCount()); + CPPUNIT_ASSERT_EQUAL(ChatState::Active, stanzaChannel->sentStanzas[stanzaChannel->sentStanzas.size()-1]->getPayload<ChatState>()->getChatState()); } void testContactShouldReceiveStates_CapsOnly() { - notifier_->setContactHas85Caps(true); - CPPUNIT_ASSERT_EQUAL(true, notifier_->contactShouldReceiveStates()); + setContactHas85Caps(); + boost::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + CPPUNIT_ASSERT(message->getPayload<ChatState>()); + CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); } void testContactShouldReceiveStates_CapsNorActive() { - CPPUNIT_ASSERT_EQUAL(false, notifier_->contactShouldReceiveStates()); + boost::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + CPPUNIT_ASSERT(!message->getPayload<ChatState>()); } void testContactShouldReceiveStates_ActiveOverrideOn() { - notifier_->setContactHas85Caps(false); notifier_->receivedMessageFromContact(true); - CPPUNIT_ASSERT_EQUAL(true, notifier_->contactShouldReceiveStates()); + boost::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + CPPUNIT_ASSERT(message->getPayload<ChatState>()); + CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); } void testContactShouldReceiveStates_ActiveOverrideOff() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->receivedMessageFromContact(false); /* I originally read the MUST NOT send after receiving without Active and * thought this should check for false, but I later found it was OPTIONAL * (MAY) behaviour only for if you didn't receive caps. */ - CPPUNIT_ASSERT_EQUAL(true, notifier_->contactShouldReceiveStates()); + boost::shared_ptr<Message> message(new Message()); + notifier_->addChatStateRequest(message); + CPPUNIT_ASSERT(message->getPayload<ChatState>()); + CPPUNIT_ASSERT_EQUAL(ChatState::Active, message->getPayload<ChatState>()->getChatState()); } void testStartTypingReply_CapsIncluded() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); } void testContinueTypingReply_CapsIncluded() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->setUserIsTyping(); notifier_->setUserIsTyping(); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); notifier_->userSentMessage(); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(2, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(2, getComposingCount()); } void testTypeReplies_WentOffline() { - notifier_->setContactHas85Caps(true); + setContactHas85Caps(); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); notifier_->setContactIsOnline(false); notifier_->userSentMessage(); notifier_->setUserIsTyping(); - CPPUNIT_ASSERT_EQUAL(1, monitor_->composingCallCount); + CPPUNIT_ASSERT_EQUAL(1, getComposingCount()); } - + + private: + void setContactHas85Caps() { + DiscoInfo::ref caps(new DiscoInfo()); + caps->addFeature(ChatState::getFeatureNamespace()); + entityCapsProvider->caps[JID("foo@bar.com/baz")] = caps; + entityCapsProvider->onCapsChanged(JID("foo@bar.com/baz")); + } + + int getComposingCount() const { + int result = 0; + foreach(boost::shared_ptr<Stanza> stanza, stanzaChannel->sentStanzas) { + if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Composing) { + result++; + } + } + return result; + } + + int getActiveCount() const { + int result = 0; + foreach(boost::shared_ptr<Stanza> stanza, stanzaChannel->sentStanzas) { + if (stanza->getPayload<ChatState>() && stanza->getPayload<ChatState>()->getChatState() == ChatState::Active) { + result++; + } + } + return result; + } + + private: + DummyStanzaChannel* stanzaChannel; + DummyEntityCapsProvider* entityCapsProvider; + ChatStateNotifier* notifier_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ChatStateNotifierTest); |