summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Maudsley <richard.maudsley@isode.com>2014-07-31 09:12:51 (GMT)
committerSwift Review <review@swift.im>2014-08-10 10:29:59 (GMT)
commitcdc8e88963e2f12cf0a6398a4dd6bb787b456b46 (patch)
tree4f3593b4551e96cfa94a5c606c2388bf43f1a936
parentb3c5aaea2fe185378d340ad1cdfe7ef502c1ab24 (diff)
downloadswift-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.cpp2
-rw-r--r--Swiften/Client/ClientBlockListManager.cpp20
-rw-r--r--Swiften/Client/ClientBlockListManager.h6
-rw-r--r--Swiften/Client/UnitTest/ClientBlockListManagerTest.cpp2
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);