diff options
| author | Richard Maudsley <richard.maudsley@isode.com> | 2014-07-31 09:12:51 (GMT) |
|---|---|---|
| committer | Swift Review <review@swift.im> | 2014-08-10 10:29:59 (GMT) |
| commit | cdc8e88963e2f12cf0a6398a4dd6bb787b456b46 (patch) | |
| tree | 4f3593b4551e96cfa94a5c606c2388bf43f1a936 | |
| parent | b3c5aaea2fe185378d340ad1cdfe7ef502c1ab24 (diff) | |
| download | swift-contrib-cdc8e88963e2f12cf0a6398a4dd6bb787b456b46.zip swift-contrib-cdc8e88963e2f12cf0a6398a4dd6bb787b456b46.tar.bz2 | |
Fix blocklist not being requested on reconnect.
Test-Information:
Connect client and confirm that blocklist is requested only once. Reconnect client and confirm that blocklist is requested again.
Change-Id: Iebf38c9f3c1ff9749c239b6cf785feb7a539a9b1
| -rw-r--r-- | Swift/Controllers/Roster/RosterController.cpp | 2 | ||||
| -rw-r--r-- | Swiften/Client/ClientBlockListManager.cpp | 20 | ||||
| -rw-r--r-- | Swiften/Client/ClientBlockListManager.h | 6 | ||||
| -rw-r--r-- | Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp | 2 |
4 files changed, 19 insertions, 11 deletions
diff --git a/Swift/Controllers/Roster/RosterController.cpp b/Swift/Controllers/Roster/RosterController.cpp index e823a1c..43623d5 100644 --- a/Swift/Controllers/Roster/RosterController.cpp +++ b/Swift/Controllers/Roster/RosterController.cpp @@ -1,403 +1,403 @@ /* * Copyright (c) 2010-2013 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swift/Controllers/Roster/RosterController.h> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <Swiften/Base/foreach.h> #include <Swiften/Base/format.h> #include <Swiften/Base/Path.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/NickManager.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/Disco/EntityCapsManager.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/FileTransfer/FileTransferManager.h> #include <Swiften/JID/JID.h> #include <Swiften/Jingle/JingleSessionManager.h> #include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Presence/SubscriptionManager.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Roster/GetRosterRequest.h> #include <Swiften/Roster/SetRosterRequest.h> #include <Swiften/Roster/XMPPRoster.h> #include <Swiften/Roster/XMPPRosterItem.h> #include <Swift/Controllers/Intl.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/OfflineRosterFilter.h> #include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Roster/RosterVCardProvider.h> #include <Swift/Controllers/Roster/ItemOperations/AppearOffline.h> #include <Swift/Controllers/Roster/ItemOperations/SetAvatar.h> #include <Swift/Controllers/Roster/ItemOperations/SetAvailableFeatures.h> #include <Swift/Controllers/Roster/ItemOperations/SetBlockingState.h> #include <Swift/Controllers/Roster/ItemOperations/SetName.h> #include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> #include <Swift/Controllers/Roster/ItemOperations/SetVCard.h> #include <Swift/Controllers/SettingConstants.h> #include <Swift/Controllers/UIEvents/AddContactUIEvent.h> #include <Swift/Controllers/UIEvents/RemoveRosterItemUIEvent.h> #include <Swift/Controllers/UIEvents/RenameGroupUIEvent.h> #include <Swift/Controllers/UIEvents/RenameRosterItemUIEvent.h> #include <Swift/Controllers/UIEvents/SendFileUIEvent.h> #include <Swift/Controllers/UIInterfaces/MainWindow.h> #include <Swift/Controllers/UIInterfaces/MainWindowFactory.h> #include <Swift/Controllers/XMPPEvents/ErrorEvent.h> #include <Swift/Controllers/XMPPEvents/EventController.h> #include <Swift/Controllers/XMPPEvents/SubscriptionRequestEvent.h> namespace Swift { /** * The controller does not gain ownership of these parameters. */ RosterController::RosterController(const JID& jid, XMPPRoster* xmppRoster, AvatarManager* avatarManager, MainWindowFactory* mainWindowFactory, NickManager* nickManager, NickResolver* nickResolver, PresenceOracle* presenceOracle, SubscriptionManager* subscriptionManager, EventController* eventController, UIEventStream* uiEventStream, IQRouter* iqRouter, SettingsProvider* settings, EntityCapsProvider* entityCapsManager, FileTransferOverview* fileTransferOverview, ClientBlockListManager* clientBlockListManager, VCardManager* vcardManager) : myJID_(jid), xmppRoster_(xmppRoster), mainWindowFactory_(mainWindowFactory), mainWindow_(mainWindowFactory_->createMainWindow(uiEventStream)), roster_(new Roster()), offlineFilter_(new OfflineRosterFilter()), vcardManager_(vcardManager), avatarManager_(avatarManager), nickManager_(nickManager), nickResolver_(nickResolver), presenceOracle_(presenceOracle), uiEventStream_(uiEventStream), entityCapsManager_(entityCapsManager), ftOverview_(fileTransferOverview), clientBlockListManager_(clientBlockListManager) { assert(fileTransferOverview); iqRouter_ = iqRouter; subscriptionManager_ = subscriptionManager; eventController_ = eventController; settings_ = settings; expandiness_ = new RosterGroupExpandinessPersister(roster_, settings); mainWindow_->setRosterModel(roster_); rosterVCardProvider_ = new RosterVCardProvider(roster_, vcardManager, JID::WithoutResource); changeStatusConnection_ = mainWindow_->onChangeStatusRequest.connect(boost::bind(&RosterController::handleChangeStatusRequest, this, _1, _2)); signOutConnection_ = mainWindow_->onSignOutRequest.connect(boost::bind(boost::ref(onSignOutRequest))); xmppRoster_->onJIDAdded.connect(boost::bind(&RosterController::handleOnJIDAdded, this, _1)); xmppRoster_->onJIDUpdated.connect(boost::bind(&RosterController::handleOnJIDUpdated, this, _1, _2, _3)); xmppRoster_->onJIDRemoved.connect(boost::bind(&RosterController::handleOnJIDRemoved, this, _1)); xmppRoster_->onRosterCleared.connect(boost::bind(&RosterController::handleRosterCleared, this)); subscriptionManager_->onPresenceSubscriptionRequest.connect(boost::bind(&RosterController::handleSubscriptionRequest, this, _1, _2)); presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handleIncomingPresence, this, _1)); uiEventConnection_ = uiEventStream->onUIEvent.connect(boost::bind(&RosterController::handleUIEvent, this, _1)); vcardManager_->onOwnVCardChanged.connect(boost::bind(&RosterController::handleOwnVCardChanged, this, _1)); avatarManager_->onAvatarChanged.connect(boost::bind(&RosterController::handleAvatarChanged, this, _1)); presenceOracle_->onPresenceChange.connect(boost::bind(&RosterController::handlePresenceChanged, this, _1)); mainWindow_->setMyAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); nickManager_->onOwnNickChanged.connect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); mainWindow_->setMyJID(jid); mainWindow_->setMyNick(nickManager_->getOwnNick()); entityCapsManager_->onCapsChanged.connect(boost::bind(&RosterController::handleOnCapsChanged, this, _1)); settings_->onSettingChanged.connect(boost::bind(&RosterController::handleSettingChanged, this, _1)); handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); ownContact_ = boost::make_shared<ContactRosterItem>(myJID_.toBare(), myJID_.toBare(), nickManager_->getOwnNick(), (GroupRosterItem*)0); ownContact_->setVCard(vcardManager_->getVCard(myJID_.toBare())); ownContact_->setAvatarPath(pathToString(avatarManager_->getAvatarPath(myJID_.toBare()))); mainWindow_->setMyContactRosterItem(ownContact_); } RosterController::~RosterController() { settings_->onSettingChanged.disconnect(boost::bind(&RosterController::handleSettingChanged, this, _1)); nickManager_->onOwnNickChanged.disconnect(boost::bind(&MainWindow::setMyNick, mainWindow_, _1)); delete offlineFilter_; delete expandiness_; mainWindow_->setRosterModel(NULL); if (mainWindow_->canDelete()) { delete mainWindow_; } delete rosterVCardProvider_; delete roster_; } void RosterController::setEnabled(bool enabled) { if (!enabled) { roster_->applyOnItems(AppearOffline()); } } void RosterController::handleShowOfflineToggled(bool state) { if (state) { roster_->removeFilter(offlineFilter_); } else { roster_->addFilter(offlineFilter_); } } void RosterController::handleChangeStatusRequest(StatusShow::Type show, const std::string &statusText) { onChangeStatusRequest(show, statusText); } void RosterController::handleOnJIDAdded(const JID& jid) { std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); std::string name = nickResolver_->jidToNick(jid); if (!groups.empty()) { foreach(const std::string& group, groups) { roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); } } else { roster_->addContact(jid, jid, name, QT_TRANSLATE_NOOP("", "Contacts"), avatarManager_->getAvatarPath(jid)); } applyAllPresenceTo(jid); } void RosterController::applyAllPresenceTo(const JID& jid) { foreach (Presence::ref presence, presenceOracle_->getAllPresence(jid)) { roster_->applyOnItems(SetPresence(presence)); } } void RosterController::handleRosterCleared() { roster_->removeAll(); } void RosterController::handleOnJIDRemoved(const JID& jid) { roster_->removeContact(jid); } void RosterController::handleOnJIDUpdated(const JID& jid, const std::string& oldName, const std::vector<std::string>& passedOldGroups) { if (oldName != xmppRoster_->getNameForJID(jid)) { roster_->applyOnItems(SetName(nickResolver_->jidToNick(jid), jid)); } std::vector<std::string> groups = xmppRoster_->getGroupsForJID(jid); std::vector<std::string> oldGroups = passedOldGroups; std::string name = nickResolver_->jidToNick(jid); std::string contactsGroup = QT_TRANSLATE_NOOP("", "Contacts"); if (oldGroups.empty()) { oldGroups.push_back(contactsGroup); } if (groups.empty()) { groups.push_back(contactsGroup); } foreach(const std::string& group, groups) { if (std::find(oldGroups.begin(), oldGroups.end(), group) == oldGroups.end()) { roster_->addContact(jid, jid, name, group, avatarManager_->getAvatarPath(jid)); } } foreach(const std::string& group, oldGroups) { if (std::find(groups.begin(), groups.end(), group) == groups.end()) { roster_->removeContactFromGroup(jid, group); if (roster_->getGroup(group)->getChildren().size() == 0) { roster_->removeGroup(group); } } } applyAllPresenceTo(jid); } void RosterController::handleSettingChanged(const std::string& settingPath) { if (settingPath == SettingConstants::SHOW_OFFLINE.getKey()) { handleShowOfflineToggled(settings_->getSetting(SettingConstants::SHOW_OFFLINE)); } } void RosterController::handleBlockingStateChanged() { if (clientBlockListManager_->getBlockList()->getState() == BlockList::Available) { foreach(const JID& jid, clientBlockListManager_->getBlockList()->getItems()) { roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); } } } void RosterController::handleBlockingItemAdded(const JID& jid) { roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); } void RosterController::handleBlockingItemRemoved(const JID& jid) { roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsUnblocked)); } void RosterController::handleUIEvent(boost::shared_ptr<UIEvent> event) { if (boost::shared_ptr<AddContactUIEvent> addContactEvent = boost::dynamic_pointer_cast<AddContactUIEvent>(event)) { RosterItemPayload item; item.setName(addContactEvent->getName()); item.setJID(addContactEvent->getJID()); item.setGroups(std::vector<std::string>(addContactEvent->getGroups().begin(), addContactEvent->getGroups().end())); boost::shared_ptr<RosterPayload> roster(new RosterPayload()); roster->addItem(item); SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); request->send(); subscriptionManager_->requestSubscription(addContactEvent->getJID()); } else if (boost::shared_ptr<RemoveRosterItemUIEvent> removeEvent = boost::dynamic_pointer_cast<RemoveRosterItemUIEvent>(event)) { RosterItemPayload item(removeEvent->getJID(), "", RosterItemPayload::Remove); boost::shared_ptr<RosterPayload> roster(new RosterPayload()); roster->addItem(item); SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); request->send(); } else if (boost::shared_ptr<RenameRosterItemUIEvent> renameEvent = boost::dynamic_pointer_cast<RenameRosterItemUIEvent>(event)) { JID contact(renameEvent->getJID()); RosterItemPayload item(contact, renameEvent->getNewName(), xmppRoster_->getSubscriptionStateForJID(contact)); item.setGroups(xmppRoster_->getGroupsForJID(contact)); boost::shared_ptr<RosterPayload> roster(new RosterPayload()); roster->addItem(item); SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); request->onResponse.connect(boost::bind(&RosterController::handleRosterSetError, this, _1, roster)); request->send(); } else if (boost::shared_ptr<RenameGroupUIEvent> renameGroupEvent = boost::dynamic_pointer_cast<RenameGroupUIEvent>(event)) { std::vector<XMPPRosterItem> items = xmppRoster_->getItems(); std::string group = renameGroupEvent->getGroup(); // FIXME: We should handle contacts groups specially to avoid clashes if (group == QT_TRANSLATE_NOOP("", "Contacts")) { group = ""; } foreach(XMPPRosterItem& item, items) { std::vector<std::string> groups = item.getGroups(); if ( (group.empty() && groups.empty()) || std::find(groups.begin(), groups.end(), group) != groups.end()) { groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end()); if (std::find(groups.begin(), groups.end(), renameGroupEvent->getNewName()) == groups.end()) { groups.push_back(renameGroupEvent->getNewName()); } item.setGroups(groups); updateItem(item); } } } else if (boost::shared_ptr<SendFileUIEvent> sendFileEvent = boost::dynamic_pointer_cast<SendFileUIEvent>(event)) { //TODO add send file dialog to ChatView of receipient jid ftOverview_->sendFile(sendFileEvent->getJID(), sendFileEvent->getFilename()); } } void RosterController::setContactGroups(const JID& jid, const std::vector<std::string>& groups) { updateItem(XMPPRosterItem(jid, xmppRoster_->getNameForJID(jid), groups, xmppRoster_->getSubscriptionStateForJID(jid))); } void RosterController::updateItem(const XMPPRosterItem& item) { RosterItemPayload itemPayload(item.getJID(), item.getName(), item.getSubscription()); itemPayload.setGroups(item.getGroups()); RosterPayload::ref roster = boost::make_shared<RosterPayload>(); roster->addItem(itemPayload); SetRosterRequest::ref request = SetRosterRequest::create(roster, iqRouter_); request->onResponse.connect(boost::bind(&RosterController::handleRosterItemUpdated, this, _1, roster)); request->send(); } void RosterController::initBlockingCommand() { - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); + boost::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); blockingOnStateChangedConnection_ = blockList->onStateChanged.connect(boost::bind(&RosterController::handleBlockingStateChanged, this)); blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&RosterController::handleBlockingItemAdded, this, _1)); blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&RosterController::handleBlockingItemRemoved, this, _1)); roster_->setBlockingSupported(true); if (blockList->getState() == BlockList::Available) { foreach(const JID& jid, blockList->getItems()) { roster_->applyOnItems(SetBlockingState(jid, ContactRosterItem::IsBlocked)); } } } void RosterController::handleRosterItemUpdated(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload) { if (!!error) { handleRosterSetError(error, rosterPayload); } boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); std::vector<RosterItemPayload> items = rosterPayload->getItems(); if (blockList->getState() == BlockList::Available && items.size() > 0) { std::vector<JID> jids = blockList->getItems(); if (std::find(jids.begin(), jids.end(), items[0].getJID()) != jids.end()) { roster_->applyOnItems(SetBlockingState(items[0].getJID(), ContactRosterItem::IsBlocked)); } } } void RosterController::handleRosterSetError(ErrorPayload::ref error, boost::shared_ptr<RosterPayload> rosterPayload) { if (!error) { return; } std::string text = str(format(QT_TRANSLATE_NOOP("", "Server %1% rejected contact list change to item '%2%'")) % myJID_.getDomain() % rosterPayload->getItems()[0].getJID().toString()); if (!error->getText().empty()) { text += ": " + error->getText(); } boost::shared_ptr<ErrorEvent> errorEvent(new ErrorEvent(JID(myJID_.getDomain()), text)); eventController_->handleIncomingEvent(errorEvent); } void RosterController::handleIncomingPresence(Presence::ref newPresence) { if (newPresence->getType() == Presence::Error) { return; } roster_->applyOnItems(SetPresence(newPresence)); } void RosterController::handleSubscriptionRequest(const JID& jid, const std::string& message) { if (xmppRoster_->containsJID(jid) && (xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::To || xmppRoster_->getSubscriptionStateForJID(jid) == RosterItemPayload::Both)) { subscriptionManager_->confirmSubscription(jid); return; } SubscriptionRequestEvent* eventPointer = new SubscriptionRequestEvent(jid, message); eventPointer->onAccept.connect(boost::bind(&RosterController::handleSubscriptionRequestAccepted, this, eventPointer)); eventPointer->onDecline.connect(boost::bind(&RosterController::handleSubscriptionRequestDeclined, this, eventPointer)); boost::shared_ptr<StanzaEvent> event(eventPointer); eventController_->handleIncomingEvent(event); } void RosterController::handleSubscriptionRequestAccepted(SubscriptionRequestEvent* event) { subscriptionManager_->confirmSubscription(event->getJID()); if (!xmppRoster_->containsJID(event->getJID()) || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::None || xmppRoster_->getSubscriptionStateForJID(event->getJID()) == RosterItemPayload::From) { subscriptionManager_->requestSubscription(event->getJID()); } } void RosterController::handleSubscriptionRequestDeclined(SubscriptionRequestEvent* event) { subscriptionManager_->cancelSubscription(event->getJID()); } void RosterController::handleOwnVCardChanged(VCard::ref vcard) { ownContact_->setVCard(vcard); mainWindow_->setMyContactRosterItem(ownContact_); } void RosterController::handleAvatarChanged(const JID& jid) { boost::filesystem::path path = avatarManager_->getAvatarPath(jid); roster_->applyOnItems(SetAvatar(jid, path)); if (jid.equals(myJID_, JID::WithResource)) { mainWindow_->setMyAvatarPath(pathToString(path)); ownContact_->setAvatarPath(pathToString(path)); mainWindow_->setMyContactRosterItem(ownContact_); } } void RosterController::handlePresenceChanged(Presence::ref presence) { if (presence->getFrom().equals(myJID_, JID::WithResource)) { ownContact_->applyPresence(std::string(), presence); mainWindow_->setMyContactRosterItem(ownContact_); } } boost::optional<XMPPRosterItem> RosterController::getItem(const JID& jid) const { return xmppRoster_->getItem(jid); } std::set<std::string> RosterController::getGroups() const { return xmppRoster_->getGroups(); } void RosterController::handleOnCapsChanged(const JID& jid) { DiscoInfo::ref info = entityCapsManager_->getCaps(jid); if (info) { std::set<ContactRosterItem::Feature> features; if (FileTransferManager::isSupportedBy(info)) { features.insert(ContactRosterItem::FileTransferFeature); } if (info->hasFeature(DiscoInfo::WhiteboardFeature)) { features.insert(ContactRosterItem::WhiteboardFeature); } roster_->applyOnItems(SetAvailableFeatures(jid, features)); } } } diff --git a/Swiften/Client/ClientBlockListManager.cpp b/Swiften/Client/ClientBlockListManager.cpp index 6646a5c..d446315 100644 --- a/Swiften/Client/ClientBlockListManager.cpp +++ b/Swiften/Client/ClientBlockListManager.cpp @@ -1,130 +1,134 @@ /* * Copyright (c) 2011 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiften/Client/ClientBlockListManager.h> #include <boost/bind.hpp> #include <boost/smart_ptr/make_shared.hpp> #include <cassert> #include <Swiften/Client/BlockListImpl.h> using namespace Swift; namespace { class BlockResponder : public SetResponder<BlockPayload> { public: BlockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<BlockPayload>(iqRouter), blockList(blockList) { } virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<BlockPayload> payload) { if (getIQRouter()->isAccountJID(from)) { if (payload) { blockList->addItems(payload->getItems()); } sendResponse(from, id, boost::shared_ptr<BlockPayload>()); } else { sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); } return true; } private: boost::shared_ptr<BlockListImpl> blockList; }; class UnblockResponder : public SetResponder<UnblockPayload> { public: UnblockResponder(boost::shared_ptr<BlockListImpl> blockList, IQRouter* iqRouter) : SetResponder<UnblockPayload>(iqRouter), blockList(blockList) { } virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr<UnblockPayload> payload) { if (getIQRouter()->isAccountJID(from)) { if (payload) { if (payload->getItems().empty()) { blockList->removeAllItems(); } else { blockList->removeItems(payload->getItems()); } } sendResponse(from, id, boost::shared_ptr<UnblockPayload>()); } else { sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); } return true; } private: boost::shared_ptr<BlockListImpl> blockList; }; } ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iqRouter) { } ClientBlockListManager::~ClientBlockListManager() { if (blockList && blockList->getState() == BlockList::Available) { unblockResponder->stop(); blockResponder->stop(); } - if (getRequest) { - getRequest->onResponse.disconnect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); - } } boost::shared_ptr<BlockList> ClientBlockListManager::getBlockList() { if (!blockList) { blockList = boost::make_shared<BlockListImpl>(); - blockList->setState(BlockList::Requesting); - assert(!getRequest); - getRequest = boost::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), boost::make_shared<BlockListPayload>(), iqRouter); - getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); - getRequest->send(); + blockList->setState(BlockList::Init); + } + return blockList; +} + +boost::shared_ptr<BlockList> ClientBlockListManager::requestBlockList() { + if (!blockList) { + blockList = boost::make_shared<BlockListImpl>(); } + blockList->setState(BlockList::Requesting); + boost::shared_ptr<GenericRequest<BlockListPayload> > getRequest = boost::make_shared< GenericRequest<BlockListPayload> >(IQ::Get, JID(), boost::make_shared<BlockListPayload>(), iqRouter); + getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); + getRequest->send(); return blockList; } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDRequest(const JID& jid) { return createBlockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<BlockPayload>::ref ClientBlockListManager::createBlockJIDsRequest(const std::vector<JID>& jids) { boost::shared_ptr<BlockPayload> payload = boost::make_shared<BlockPayload>(jids); return boost::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDRequest(const JID& jid) { return createUnblockJIDsRequest(std::vector<JID>(1, jid)); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockJIDsRequest(const std::vector<JID>& jids) { boost::shared_ptr<UnblockPayload> payload = boost::make_shared<UnblockPayload>(jids); return boost::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, iqRouter); } GenericRequest<UnblockPayload>::ref ClientBlockListManager::createUnblockAllRequest() { return createUnblockJIDsRequest(std::vector<JID>()); } void ClientBlockListManager::handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref error) { if (error || !payload) { blockList->setState(BlockList::Error); } else { blockList->setItems(payload->getItems()); blockList->setState(BlockList::Available); blockResponder = boost::make_shared<BlockResponder>(blockList, iqRouter); blockResponder->start(); unblockResponder = boost::make_shared<UnblockResponder>(blockList, iqRouter); unblockResponder->start(); } } diff --git a/Swiften/Client/ClientBlockListManager.h b/Swiften/Client/ClientBlockListManager.h index e8d4ac6..e715737 100644 --- a/Swiften/Client/ClientBlockListManager.h +++ b/Swiften/Client/ClientBlockListManager.h @@ -1,52 +1,56 @@ /* * Copyright (c) 2011 Remko Tronçon * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <boost/shared_ptr.hpp> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/BlockPayload.h> #include <Swiften/Elements/BlockListPayload.h> #include <Swiften/Elements/UnblockPayload.h> #include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Queries/SetResponder.h> #include <Swiften/Queries/GenericRequest.h> #include <Swiften/Client/BlockList.h> #include <Swiften/Client/BlockListImpl.h> namespace Swift { class IQRouter; class ClientBlockListManager { public: ClientBlockListManager(IQRouter *iqRouter); ~ClientBlockListManager(); /** * Returns the blocklist. */ boost::shared_ptr<BlockList> getBlockList(); + /** + * Get the blocklist from the server. + */ + boost::shared_ptr<BlockList> requestBlockList(); + GenericRequest<BlockPayload>::ref createBlockJIDRequest(const JID& jid); GenericRequest<BlockPayload>::ref createBlockJIDsRequest(const std::vector<JID>& jids); GenericRequest<UnblockPayload>::ref createUnblockJIDRequest(const JID& jid); GenericRequest<UnblockPayload>::ref createUnblockJIDsRequest(const std::vector<JID>& jids); GenericRequest<UnblockPayload>::ref createUnblockAllRequest(); private: void handleBlockListReceived(boost::shared_ptr<BlockListPayload> payload, ErrorPayload::ref); private: IQRouter* iqRouter; - boost::shared_ptr<GenericRequest<BlockListPayload> > getRequest; boost::shared_ptr<SetResponder<BlockPayload> > blockResponder; boost::shared_ptr<SetResponder<UnblockPayload> > unblockResponder; boost::shared_ptr<BlockListImpl> blockList; }; } diff --git a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp index 9010042..dd6c95d 100644 --- a/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp +++ b/Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp @@ -1,190 +1,190 @@ /* * Copyright (c) 2013 Tobias Markmann * Licensed under the simplified BSD license. * See Documentation/Licenses/BSD-simplified.txt for more information. */ #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <algorithm> #include <Swiften/Base/foreach.h> #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Elements/IQ.h> using namespace Swift; class ClientBlockListManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ClientBlockListManagerTest); CPPUNIT_TEST(testFetchBlockList); CPPUNIT_TEST(testBlockCommand); CPPUNIT_TEST(testUnblockCommand); CPPUNIT_TEST(testUnblockAllCommand); CPPUNIT_TEST_SUITE_END(); public: void setUp() { ownJID_ = JID("kev@wonderland.lit"); stanzaChannel_ = new DummyStanzaChannel(); iqRouter_ = new IQRouter(stanzaChannel_); iqRouter_->setJID(ownJID_); clientBlockListManager_ = new ClientBlockListManager(iqRouter_); } void testFetchBlockList() { std::vector<JID> blockJids; blockJids.push_back(JID("romeo@montague.net")); blockJids.push_back(JID("iago@shakespeare.lit")); helperInitialBlockListFetch(blockJids); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); } void testBlockCommand() { // start with an already fetched block list helperInitialBlockListFetch(std::vector<JID>(1, JID("iago@shakespeare.lit"))); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); GenericRequest<BlockPayload>::ref blockRequest = clientBlockListManager_->createBlockJIDRequest(JID("romeo@montague.net")); blockRequest->send(); IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); CPPUNIT_ASSERT(request.get() != NULL); boost::shared_ptr<BlockPayload> blockPayload = request->getPayload<BlockPayload>(); CPPUNIT_ASSERT(blockPayload.get() != NULL); CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), blockPayload->getItems().at(0)); IQ::ref blockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); stanzaChannel_->sendIQ(blockRequestResponse); stanzaChannel_->onIQReceived(blockRequestResponse); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), clientBlockListManager_->getBlockList()->getItems().size()); // send block push boost::shared_ptr<BlockPayload> pushPayload = boost::make_shared<BlockPayload>(); pushPayload->addItem(JID("romeo@montague.net")); IQ::ref blockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); stanzaChannel_->sendIQ(blockPush); stanzaChannel_->onIQReceived(blockPush); std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); CPPUNIT_ASSERT(blockedJIDs.end() != std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); } void testUnblockCommand() { // start with an already fetched block list std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); initialBlockList.push_back(JID("romeo@montague.net")); helperInitialBlockListFetch(initialBlockList); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockJIDRequest(JID("romeo@montague.net")); unblockRequest->send(); IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); CPPUNIT_ASSERT(request.get() != NULL); boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); CPPUNIT_ASSERT(unblockPayload.get() != NULL); CPPUNIT_ASSERT_EQUAL(JID("romeo@montague.net"), unblockPayload->getItems().at(0)); IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); stanzaChannel_->sendIQ(unblockRequestResponse); stanzaChannel_->onIQReceived(unblockRequestResponse); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), clientBlockListManager_->getBlockList()->getItems().size()); // send block push boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); pushPayload->addItem(JID("romeo@montague.net")); IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); stanzaChannel_->sendIQ(unblockPush); stanzaChannel_->onIQReceived(unblockPush); std::vector<JID> blockedJIDs = clientBlockListManager_->getBlockList()->getItems(); CPPUNIT_ASSERT(blockedJIDs.end() == std::find(blockedJIDs.begin(), blockedJIDs.end(), JID("romeo@montague.net"))); } void testUnblockAllCommand() { // start with an already fetched block list std::vector<JID> initialBlockList = std::vector<JID>(1, JID("iago@shakespeare.lit")); initialBlockList.push_back(JID("romeo@montague.net")); initialBlockList.push_back(JID("benvolio@montague.net")); helperInitialBlockListFetch(initialBlockList); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); GenericRequest<UnblockPayload>::ref unblockRequest = clientBlockListManager_->createUnblockAllRequest(); unblockRequest->send(); IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(2); CPPUNIT_ASSERT(request.get() != NULL); boost::shared_ptr<UnblockPayload> unblockPayload = request->getPayload<UnblockPayload>(); CPPUNIT_ASSERT(unblockPayload.get() != NULL); CPPUNIT_ASSERT_EQUAL(true, unblockPayload->getItems().empty()); IQ::ref unblockRequestResponse = IQ::createResult(request->getFrom(), JID(), request->getID()); stanzaChannel_->sendIQ(unblockRequestResponse); stanzaChannel_->onIQReceived(unblockRequestResponse); CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), clientBlockListManager_->getBlockList()->getItems().size()); // send block push boost::shared_ptr<UnblockPayload> pushPayload = boost::make_shared<UnblockPayload>(); IQ::ref unblockPush = IQ::createRequest(IQ::Set, ownJID_, "push1", pushPayload); stanzaChannel_->sendIQ(unblockPush); stanzaChannel_->onIQReceived(unblockPush); CPPUNIT_ASSERT_EQUAL(true, clientBlockListManager_->getBlockList()->getItems().empty()); } void tearDown() { delete clientBlockListManager_; delete iqRouter_; delete stanzaChannel_; } private: void helperInitialBlockListFetch(const std::vector<JID>& blockedJids) { - boost::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); + boost::shared_ptr<BlockList> blockList = clientBlockListManager_->requestBlockList(); CPPUNIT_ASSERT(blockList); // check for IQ request IQ::ref request = stanzaChannel_->getStanzaAtIndex<IQ>(0); CPPUNIT_ASSERT(request.get() != NULL); boost::shared_ptr<BlockListPayload> requestPayload = request->getPayload<BlockListPayload>(); CPPUNIT_ASSERT(requestPayload.get() != NULL); CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, blockList->getState()); CPPUNIT_ASSERT_EQUAL(BlockList::Requesting, clientBlockListManager_->getBlockList()->getState()); // build IQ response boost::shared_ptr<BlockListPayload> responsePayload = boost::make_shared<BlockListPayload>(); foreach(const JID& jid, blockedJids) { responsePayload->addItem(jid); } IQ::ref response = IQ::createResult(ownJID_, JID(), request->getID(), responsePayload); stanzaChannel_->sendIQ(response); stanzaChannel_->onIQReceived(response); CPPUNIT_ASSERT_EQUAL(BlockList::Available, clientBlockListManager_->getBlockList()->getState()); CPPUNIT_ASSERT(responsePayload->getItems() == clientBlockListManager_->getBlockList()->getItems()); } private: JID ownJID_; IQRouter* iqRouter_; DummyStanzaChannel* stanzaChannel_; ClientBlockListManager* clientBlockListManager_; }; CPPUNIT_TEST_SUITE_REGISTRATION(ClientBlockListManagerTest); |
Swift