plasma-framework/private/remoteservice.cpp
David Faure 083d157684 Merge remote-tracking branch 'origin/KDE/4.8' into origin-frameworks
Conflicts:
	kdecore/network/k3datagramsocket.cpp
	kdeui/actions/kstandardaction.cpp
	kdeui/dialogs/kconfigdialogmanager.cpp
	kdeui/icons/kicondialog.cpp
	kdeui/itemviews/kviewstatesaver.h
	kfile/knewfilemenu.cpp
	kio/misc/kpac/downloader.cpp
	kio/tests/kdirlistertest.cpp
	kparts/browserextension.cpp
	nepomuk/core/nepomukmainmodel.cpp
	nepomuk/query/queryserviceclient.cpp
	nepomuk/test/ratingpaintertestwidget.cpp
	nepomuk/ui/kedittagsdialog.cpp
	nepomuk/ui/ktagcloudwidget.cpp
	nepomuk/ui/ktagdisplaywidget.cpp
	nepomuk/ui/nepomukmassupdatejob.cpp
	nepomuk/ui/tagwidget.cpp
	nepomuk/utils/daterangeselectionwidget.cpp
	nepomuk/utils/facetwidget.cpp
	nepomuk/utils/searchwidget.cpp
	plasma/containment.cpp
	plasma/datacontainer.cpp
	plasma/deprecated/animator.cpp
	plasma/extenders/extender.cpp
	plasma/plasma.h
	plasma/scripting/wallpaperscript.cpp
	tier1/solid/tests/networkingclient.cpp
(signal/slot normalization changes conflicted with KUrl->QUrl changes
and with other changes in frameworks)
2012-02-14 12:32:25 +01:00

311 lines
11 KiB
C++

/*
* Copyright © 2009 Rob Scheepmaker <r.scheepmaker@student.utwente.nl>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License version 2 as
* published by the Free Software Foundation
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "remoteservice_p.h"
#include "../remote/accessmanager.h"
#include "../remote/authorizationinterface.h"
#include "../remote/authorizationmanager.h"
#include "../remote/clientpinrequest.h"
#include "../service.h"
#include "authorizationmanager_p.h"
#include "joliemessagehelper_p.h"
#include "remoteservicejob_p.h"
#include "service_p.h"
#include <QtCore/QBuffer>
#include <QtCore/QObject>
#include <QtCore/QTimer>
#include <QtCore/QUuid>
#include <QtJolie/Client>
#include <QtJolie/Message>
#include <QtJolie/PendingReply>
#include <QtJolie/PendingCall>
#include <QtJolie/PendingCallWatcher>
#include <QtJolie/Value>
#include <kdebug.h>
#include <kurl.h>
namespace Plasma
{
RemoteService::RemoteService(QObject* parent)
: Service(parent),
m_client(0),
m_ready(false),
m_busy(false)
{
}
RemoteService::RemoteService(QObject* parent, KUrl location)
: Service(parent),
m_location(location),
m_client(0),
m_ready(false),
m_busy(false)
{
if (AuthorizationManager::self()->d->myCredentials.isValid()) {
setLocation(location);
} else {
connect(AuthorizationManager::self(), SIGNAL(readyForRemoteAccess()),
this, SLOT(slotReadyForRemoteAccess()));
}
}
RemoteService::~RemoteService()
{
delete m_client;
}
void RemoteService::slotReadyForRemoteAccess()
{
#ifndef NDEBUG
kDebug() << "AuthorizationManager is now ready for remote access!";
#endif
setLocation(m_location);
}
void RemoteService::setLocation(const KUrl &location)
{
#ifndef NDEBUG
kDebug() << "Setting RemoteService location to " << location.prettyUrl();
#endif
m_uuid = QUuid::createUuid().toString();
Credentials identity = AuthorizationManager::self()->d->myCredentials;
if (!identity.canSign()) {
#ifndef NDEBUG
kDebug() << "we can't sign? how did we get here?";
#endif
return;
}
if (m_client && (m_location != location)) {
delete m_client;
m_client = new Jolie::Client(location.host(), location.port());
}
if (!m_client) {
m_client = new Jolie::Client(location.host(), location.port());
}
m_location = location;
QByteArray identityByteArray;
QDataStream stream(&identityByteArray, QIODevice::WriteOnly);
stream << identity.toPublicCredentials();
Jolie::Message getOpDesc(location.path(KUrl::RemoveTrailingSlash).remove(0, 1).toUtf8(),
"startConnection");
Jolie::Value data;
data.children(JolieMessage::Field::IDENTITY) << Jolie::Value(identityByteArray);
data.children(JolieMessage::Field::UUID) << Jolie::Value(m_uuid.toAscii());
getOpDesc.setData(data);
Jolie::PendingCall pendingReply = m_client->asyncCall(getOpDesc);
Jolie::PendingCallWatcher *watcher = new Jolie::PendingCallWatcher(pendingReply, this);
connect(watcher, SIGNAL(finished(Jolie::PendingCallWatcher*)),
this, SLOT(callCompleted(Jolie::PendingCallWatcher*)));
}
QString RemoteService::location() const
{
return m_location.prettyUrl();
}
bool RemoteService::isReady() const
{
return m_ready;
}
bool RemoteService::isBusy() const
{
return m_busy;
}
void RemoteService::callCompleted(Jolie::PendingCallWatcher *watcher)
{
Jolie::PendingReply reply = *watcher;
Jolie::Message response = reply.reply();
if (response.operationName() == "startConnection") {
#ifndef NDEBUG
kDebug() << "Started connection: fetching .operations";
#endif
m_token = JolieMessage::field(JolieMessage::Field::TOKEN, response);
Jolie::Message getOpDesc(m_location.path(KUrl::RemoveTrailingSlash).remove(0, 1).toUtf8(),
"getOperations");
//TODO: async
Jolie::PendingCall pendingReply = m_client->asyncCall(signMessage(getOpDesc));
Jolie::PendingCallWatcher *watcher = new Jolie::PendingCallWatcher(pendingReply, this);
connect(watcher, SIGNAL(finished(Jolie::PendingCallWatcher*)),
this, SLOT(callCompleted(Jolie::PendingCallWatcher*)));
} else if (response.operationName() == "getOperations") {
if (response.fault().name() == JolieMessage::Error::REQUIREPIN) {
#ifndef NDEBUG
kDebug() << "pin required, request auth interface";
#endif
ClientPinRequest *request = new ClientPinRequest(this);
connect(request, SIGNAL(changed(Plasma::ClientPinRequest*)),
this, SLOT(slotGotPin(Plasma::ClientPinRequest*)));
AuthorizationManager::self()->d->authorizationInterface->clientPinRequest(*request);
} else {
#ifndef NDEBUG
kDebug() << "RemoteService is now ready for use!";
#endif
m_operationsScheme = JolieMessage::field(JolieMessage::Field::OPERATIONSDESCRIPTION, response);
m_token = JolieMessage::field(JolieMessage::Field::TOKEN, response);
m_ready = true;
setName(m_location.prettyUrl());
//if there's stuff in the queue, let it continue.
slotFinished();
}
} else if (response.operationName() == "getEnabledOperations") {
//TODO: optimize.
m_token = JolieMessage::field(JolieMessage::Field::TOKEN, response);
QByteArray enabledOperations = JolieMessage::field(JolieMessage::Field::ENABLEDOPERATIONS, response);
QDataStream in(&enabledOperations, QIODevice::ReadOnly);
QStringList enabledOperationsList;
in >> enabledOperationsList;
foreach (const QString &operation, operationNames()) {
if (enabledOperationsList.contains(operation) && !isOperationEnabled(operation)) {
#ifndef NDEBUG
kDebug() << "yeah, we're enabling the operation with the name " << operation;
#endif
setOperationEnabled(operation, true);
} else if (!enabledOperationsList.contains(operation) && isOperationEnabled(operation)) {
#ifndef NDEBUG
kDebug() << "we're disabling the operation with the name " << operation;
#endif
setOperationEnabled(operation, false);
}
}
//if there's stuff in the queue, let it continue.
m_busy = false;
slotFinished();
} else {
#ifndef NDEBUG
kDebug() << "How did we end up here?";
#endif
}
}
void RemoteService::slotGotPin(Plasma::ClientPinRequest *request)
{
Jolie::Message getOpDesc(m_location.path(KUrl::RemoveTrailingSlash).remove(0, 1).toUtf8(),
"getOperations");
Jolie::Value value;
value.children(JolieMessage::Field::PARAMETERS) << Jolie::Value(QByteArray());
if (!request->pin().isEmpty()) {
value.children(JolieMessage::Field::PIN) << Jolie::Value(request->pin().toAscii());
}
getOpDesc.setData(value);
//TODO: async
Jolie::PendingCall pendingReply = m_client->asyncCall(signMessage(getOpDesc));
Jolie::PendingCallWatcher *watcher = new Jolie::PendingCallWatcher(pendingReply, this);
connect(watcher, SIGNAL(finished(Jolie::PendingCallWatcher*)),
this, SLOT(callCompleted(Jolie::PendingCallWatcher*)));
}
void RemoteService::registerOperationsScheme()
{
QBuffer buffer(&m_operationsScheme);
buffer.open(QBuffer::ReadWrite);
setOperationsScheme(&buffer);
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(slotUpdateEnabledOperations()));
//FIXME: get some sensible interval depending on the connection speed. This is kind of stupid.
timer->start(2000);
}
void RemoteService::slotUpdateEnabledOperations()
{
//TODO: maybe push the get enabled operations also on the queue?
if (!m_busy) {
m_busy = true;
Jolie::Message getOpDesc(m_location.path(KUrl::RemoveTrailingSlash).remove(0, 1).toUtf8(),
"getEnabledOperations");
Jolie::PendingCall pendingReply = m_client->asyncCall(signMessage(getOpDesc));
Jolie::PendingCallWatcher *watcher = new Jolie::PendingCallWatcher(pendingReply, this);
connect(watcher, SIGNAL(finished(Jolie::PendingCallWatcher*)),
this, SLOT(callCompleted(Jolie::PendingCallWatcher*)));
} else {
#ifndef NDEBUG
kDebug() << "We would like to update enabled operations, but are still busy so let's wait for now.";
#endif
}
}
ServiceJob* RemoteService::createJob(const QString& operation,
QHash<QString,QVariant>& parameters)
{
if (!m_ready) {
#ifndef NDEBUG
kDebug() << "Use of this service hasn't checked for the serviceReady signal, which it should.";
#endif
}
ServiceJob *job = new RemoteServiceJob(m_location, destination(), operation, parameters, m_token, this);
connect(job, SIGNAL(finished(KJob*)), this, SLOT(slotFinished()));
return job;
}
void RemoteService::slotFinished()
{
if (!m_queue.isEmpty()) {
#ifndef NDEBUG
kDebug() << "Job finished, there are still service jobs in queue, starting next in queue.";
#endif
ServiceJob *job = m_queue.dequeue();
QTimer::singleShot(0, job, SLOT(slotStart()));
}
}
Jolie::Message RemoteService::signMessage(const Jolie::Message &message) const
{
Jolie::Message response(message);
Credentials identity = AuthorizationManager::self()->d->myCredentials;
if (!identity.isValid()) {
#ifndef NDEBUG
kDebug() << "We don't have our identity yet, just drop this message";
#endif
return response;
}
Jolie::Value data = response.data();
data.children(JolieMessage::Field::IDENTITYID) << Jolie::Value(identity.id().toAscii());
data.children(JolieMessage::Field::TOKEN) << Jolie::Value(m_token);
data.children(JolieMessage::Field::UUID) << Jolie::Value(m_uuid.toAscii());
response.setData(data);
data.children(JolieMessage::Field::SIGNATURE) <<
Jolie::Value(identity.signMessage(JolieMessage::payload(response)));
response.setData(data);
return response;
}
} //namespace Plasma
#include "moc_remoteservice_p.cpp"