summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/Controllers/Chat/ChatController.cpp20
-rw-r--r--Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp31
-rw-r--r--Swift/Controllers/UnitTest/MockChatWindow.h12
3 files changed, 56 insertions, 7 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp
index 503a050..e2751f7 100644
--- a/Swift/Controllers/Chat/ChatController.cpp
+++ b/Swift/Controllers/Chat/ChatController.cpp
@@ -460,22 +460,34 @@ std::string ChatController::getStatusChangeString(boost::shared_ptr<Presence> pr
if (!presence->getStatus().empty()) {
response += " (" + presence->getStatus() + ")";
}
return response + ".";
}
void ChatController::handlePresenceChange(boost::shared_ptr<Presence> newPresence) {
bool relevantPresence = false;
- if (toJID_.equals(newPresence->getFrom(), JID::WithoutResource)) {
- // Presence matches ChatController JID.
- newPresence = presenceOracle_->getAccountPresence(toJID_);
- relevantPresence = true;
+ if (isInMUC_) {
+ // For MUC participants we only have a single presence to choose one and
+ // even for multi-session nicknames multiple resources are not distinguishable
+ // to other participants.
+ if (toJID_.equals(newPresence->getFrom(), JID::WithResource)) {
+ relevantPresence = true;
+ }
+ }
+ else {
+ // For standard chats we retrieve the account presence from the PresenceOracle,
+ // as there can be multiple presences to choose from.
+ if (toJID_.equals(newPresence->getFrom(), JID::WithoutResource)) {
+ // Presence matches ChatController JID.
+ newPresence = presenceOracle_->getAccountPresence(toJID_);
+ relevantPresence = true;
+ }
}
if (!relevantPresence) {
return;
}
if (!newPresence) {
newPresence = boost::make_shared<Presence>();
newPresence->setType(Presence::Unavailable);
diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
index 281783e..5f89f62 100644
--- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
+++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp
@@ -67,18 +67,19 @@ class ChatsManagerTest : public CppUnit::TestFixture {
CPPUNIT_TEST(testUnbindRebind);
CPPUNIT_TEST(testNoDuplicateUnbind);
CPPUNIT_TEST(testThreeMUCWindows);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnRemoveFromRoster);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnAddToRoster);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth);
CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom);
CPPUNIT_TEST(testChatControllerFullJIDBindingOnMessageAndNotReceipt);
CPPUNIT_TEST(testChatControllerFullJIDBindingOnTypingAndNotActive);
+ CPPUNIT_TEST(testChatControllerPMPresenceHandling);
CPPUNIT_TEST_SUITE_END();
public:
void setUp() {
mocks_ = new MockRepository();
jid_ = JID("test@test.com/resource");
stanzaChannel_ = new DummyStanzaChannel();
iqChannel_ = new DummyIQChannel();
iqRouter_ = new IQRouter(iqChannel_);
@@ -636,18 +637,48 @@ public:
// Send third message.
window->onSendMessageRequest("ping.", false);
// The chat session is now bound to the full JID of the second resource due to its recent composing message.
CPPUNIT_ASSERT_EQUAL(senderResource[1], stanzaChannel_->getStanzaAtIndex<Message>(3)->getTo());
CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(3)->getPayload<DeliveryReceiptRequest>());
}
+ void testChatControllerPMPresenceHandling() {
+ JID participantA = JID("test@rooms.test.com/participantA");
+ JID participantB = JID("test@rooms.test.com/participantB");
+
+ mucRegistry_->addMUC("test@rooms.test.com");
+
+ MockChatWindow* window = new MockChatWindow();
+ mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(participantA, uiEventStream_).Return(window);
+
+ uiEventStream_->send(boost::shared_ptr<UIEvent>(new RequestChatUIEvent(JID(participantA))));
+
+ Presence::ref presence = Presence::create();
+ presence->setFrom(participantA);
+ presence->setShow(StatusShow::Online);
+ stanzaChannel_->onPresenceReceived(presence);
+ CPPUNIT_ASSERT_EQUAL(std::string("participantA has become available."), MockChatWindow::bodyFromMessage(window->lastAddedPresence_));
+
+ presence = Presence::create();
+ presence->setFrom(participantB);
+ presence->setShow(StatusShow::Away);
+ stanzaChannel_->onPresenceReceived(presence);
+
+ presence = Presence::create();
+ presence->setFrom(participantA);
+ presence->setShow(StatusShow::None);
+ presence->setType(Presence::Unavailable);
+ stanzaChannel_->onPresenceReceived(presence);
+ CPPUNIT_ASSERT_EQUAL(std::string("participantA has gone offline."), MockChatWindow::bodyFromMessage(window->lastReplacedMessage_));
+ }
+
void testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::Subscription from, RosterItemPayload::Subscription to) {
JID messageJID("testling@test.com/resource1");
xmppRoster_->addContact(messageJID, "foo", std::vector<std::string>(), from);
MockChatWindow* window = new MockChatWindow();//mocks_->InterfaceMock<ChatWindow>();
mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(messageJID, uiEventStream_).Return(window);
settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true);
boost::shared_ptr<Message> message = makeDeliveryReceiptTestMessage(messageJID, "1");
diff --git a/Swift/Controllers/UnitTest/MockChatWindow.h b/Swift/Controllers/UnitTest/MockChatWindow.h
index c906bfd..ddb7e3e 100644
--- a/Swift/Controllers/UnitTest/MockChatWindow.h
+++ b/Swift/Controllers/UnitTest/MockChatWindow.h
@@ -23,24 +23,28 @@ namespace Swift {
return "id";
}
virtual std::string addAction(const ChatMessage& /*message*/, const std::string& /*senderName*/, bool /*senderIsSelf*/, boost::shared_ptr<SecurityLabel> /*label*/, const std::string& /*avatarPath*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {return "id";}
virtual std::string addSystemMessage(const ChatMessage& /*message*/, Direction /*direction*/) {
return "id";
}
- virtual void addPresenceMessage(const ChatMessage& /*message*/, Direction /*direction*/) {}
+ virtual void addPresenceMessage(const ChatMessage& message, Direction /*direction*/) {
+ lastAddedPresence_ = message;
+ }
virtual void addErrorMessage(const ChatMessage& /*message*/) {}
virtual void replaceMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
virtual void replaceWithAction(const ChatMessage& /*message*/, const std::string& /*id*/, const boost::posix_time::ptime& /*time*/, const HighlightAction& /*highlight*/) {}
- virtual void replaceLastMessage(const ChatMessage& /*message*/, const TimestampBehaviour /*timestampBehaviour*/) {}
+ virtual void replaceLastMessage(const ChatMessage& message, const TimestampBehaviour /*timestampBehaviour*/) {
+ lastReplacedMessage_ = message;
+ }
virtual void replaceSystemMessage(const ChatMessage& /*message*/, const std::string& /*id*/, const TimestampBehaviour /*timestampBehaviour*/) {}
// File transfer related stuff
virtual std::string addFileTransfer(const std::string& /*senderName*/, bool /*senderIsSelf*/,const std::string& /*filename*/, const boost::uintmax_t /*sizeInBytes*/, const std::string& /*description*/) { return 0; }
virtual void setFileTransferProgress(std::string /*id*/, const int /*alreadyTransferedBytes*/) { }
virtual void setFileTransferStatus(std::string /*id*/, const FileTransferState /*state*/, const std::string& /*msg*/) { }
virtual void setMessageReceiptState(const std::string &/* id */, ReceiptState /* state */) { }
@@ -76,28 +80,30 @@ namespace Swift {
virtual void setAffiliations(MUCOccupant::Affiliation, const std::vector<JID>&) {}
virtual void setAvailableRoomActions(const std::vector<RoomAction> &) {}
virtual void setBlockingState(BlockingState) {}
virtual void setCanInitiateImpromptuChats(bool /*supportsImpromptu*/) {}
virtual void showBookmarkWindow(const MUCBookmark& /*bookmark*/) {}
virtual void setBookmarkState(RoomBookmarkState) {}
- std::string bodyFromMessage(const ChatMessage& message) {
+ static std::string bodyFromMessage(const ChatMessage& message) {
boost::shared_ptr<ChatTextMessagePart> text;
foreach (boost::shared_ptr<ChatMessagePart> part, message.getParts()) {
if ((text = boost::dynamic_pointer_cast<ChatTextMessagePart>(part))) {
return text->text;
}
}
return "";
}
std::string name_;
std::string lastMessageBody_;
+ ChatMessage lastAddedPresence_;
+ ChatMessage lastReplacedMessage_;
std::vector<SecurityLabelsCatalog::Item> labels_;
bool labelsEnabled_;
SecurityLabelsCatalog::Item label_;
Roster* roster_;
};
}