Commit 38000611 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧

Use the incoming/outgoing capabilities for trimming loaded plugins

Only lets the plugins that support something offered on the other end or
that offer something supported on the other end. If we don't have
information about the other device, we enable everything like we used to.

Also refactors a bit the plugin loader, to be able to provide information
step by step.

Currently it works, but we need support for capabilities at least on
Android to start taking good advantage of it.

REVIEW: 118820
CCMAIL: kdeconnect@kde.org
parent c935ea83
......@@ -70,6 +70,8 @@ Device::Device(QObject* parent, const NetworkPackage& identityPackage, DeviceLin
, m_deviceType(str2type(identityPackage.get<QString>("deviceType")))
, m_pairStatus(Device::NotPaired)
, m_protocolVersion(identityPackage.get<int>("protocolVersion"))
, m_incomingCapabilities(identityPackage.get<QStringList>("SupportedIncomingInterfaces", QStringList()).toSet())
, m_outgoingCapabilities(identityPackage.get<QStringList>("SupportedOutgoingInterfaces", QStringList()).toSet())
{
initPrivateKey();
......@@ -130,11 +132,27 @@ void Device::reloadPlugins()
incomingInterfaces = m_pluginsByIncomingInterface.keys(plugin);
outgoingInterfaces = m_pluginsByOutgoingInterface.keys(plugin);
} else {
PluginData data = loader->instantiatePluginForDevice(pluginName, this);
plugin = data.plugin;
incomingInterfaces = data.incomingInterfaces;
outgoingInterfaces = data.outgoingInterfaces;
KService::Ptr service = loader->pluginService(pluginName);
incomingInterfaces = service->property("X-KdeConnect-SupportedPackageType", QVariant::StringList).toStringList();
outgoingInterfaces = service->property("X-KdeConnect-OutgoingPackageType", QVariant::StringList).toStringList();
}
//If we don't find intersection with the received on one end and the sent on the other, we don't
//let the plugin stay
//Also, if no capabilities are specified on the other end, we don't apply this optimizaton, as
//we asume that the other client doesn't know about capabilities.
if (!m_incomingCapabilities.isEmpty() && !m_outgoingCapabilities.isEmpty()
&& m_incomingCapabilities.intersect(outgoingInterfaces.toSet()).isEmpty()
&& m_outgoingCapabilities.intersect(incomingInterfaces.toSet()).isEmpty()
) {
delete plugin;
continue;
}
if (!plugin) {
plugin = loader->instantiatePluginForDevice(pluginName, this);
}
foreach(const QString& interface, incomingInterfaces) {
newPluginsByIncomingInterface.insert(interface, plugin);
}
......
......@@ -135,6 +135,8 @@ private:
QMultiMap<QString, KdeConnectPlugin*> m_pluginsByOutgoingInterface;
QTimer m_pairingTimeut;
QSet<QString> m_incomingCapabilities;
QSet<QString> m_outgoingCapabilities;
void setAsPaired();
void storeAsTrusted();
......
......@@ -33,6 +33,7 @@
#include <qjson/qobjecthelper.h>
#include "filetransferjob.h"
#include "pluginloader.h"
const QCA::EncryptionAlgorithm NetworkPackage::EncryptionAlgorithm = QCA::EME_PKCS1v15;
const int NetworkPackage::ProtocolVersion = 5;
......@@ -58,6 +59,8 @@ void NetworkPackage::createIdentityPackage(NetworkPackage* np)
np->set("deviceName", qgetenv("USER") + "@" + QHostInfo::localHostName());
np->set("protocolType", "desktop"); //TODO: Detect laptop, tablet, phone...
np->set("protocolVersion", NetworkPackage::ProtocolVersion);
np->set("SupportedIncomingInterfaces", PluginLoader::instance()->incomingInterfaces().join(","));
np->set("SupportedOutgoingInterfaces", PluginLoader::instance()->outgoingInterfaces().join(","));
//kDebug(kdeconnect_kded()) << "createIdentityPackage" << np->serialize();
}
......
......@@ -57,9 +57,9 @@ KPluginInfo PluginLoader::getPluginInfo(const QString& name) const
return KPluginInfo(service);
}
PluginData PluginLoader::instantiatePluginForDevice(const QString& name, Device* device) const
KdeConnectPlugin* PluginLoader::instantiatePluginForDevice(const QString& name, Device* device) const
{
PluginData ret;
KdeConnectPlugin* ret = 0;
KService::Ptr service = plugins[name];
if (!service) {
......@@ -73,14 +73,12 @@ PluginData PluginLoader::instantiatePluginForDevice(const QString& name, Device*
return ret;
}
ret.incomingInterfaces = service->property("X-KdeConnect-SupportedPackageType", QVariant::StringList).toStringList();
ret.outgoingInterfaces = service->property("X-KdeConnect-OutgoingPackageType", QVariant::StringList).toStringList();
QStringList outgoingInterfaces = service->property("X-KdeConnect-OutgoingPackageType", QVariant::StringList).toStringList();
QVariant deviceVariant = QVariant::fromValue<Device*>(device);
//FIXME any reason to use QObject in template param instead KdeConnectPlugin?
ret.plugin = factory->create<KdeConnectPlugin>(device, QVariantList() << deviceVariant << ret.outgoingInterfaces);
if (!ret.plugin) {
ret = factory->create<KdeConnectPlugin>(device, QVariantList() << deviceVariant << outgoingInterfaces);
if (!ret) {
kDebug(debugArea()) << "Error loading plugin";
return ret;
}
......@@ -89,3 +87,25 @@ PluginData PluginLoader::instantiatePluginForDevice(const QString& name, Device*
return ret;
}
KService::Ptr PluginLoader::pluginService(const QString& pluginName) const
{
return plugins[pluginName];
}
QStringList PluginLoader::incomingInterfaces() const
{
QSet<QString> ret;
foreach(const KService::Ptr& service, plugins) {
ret += service->property("X-KdeConnect-SupportedPackageType", QVariant::StringList).toStringList().toSet();
}
return ret.toList();
}
QStringList PluginLoader::outgoingInterfaces() const
{
QSet<QString> ret;
foreach(const KService::Ptr& service, plugins) {
ret += service->property("X-KdeConnect-OutgoingPackageType", QVariant::StringList).toStringList().toSet();
}
return ret.toList();
}
......@@ -32,23 +32,18 @@
class Device;
class KdeConnectPlugin;
struct PluginData
{
PluginData() : plugin(0) {}
KdeConnectPlugin* plugin;
QStringList incomingInterfaces;
QStringList outgoingInterfaces;
};
class PluginLoader
{
public:
static PluginLoader* instance();
QStringList incomingInterfaces() const;
QStringList outgoingInterfaces() const;
QStringList getPluginList() const;
KPluginInfo getPluginInfo(const QString& name) const;
PluginData instantiatePluginForDevice(const QString& name, Device* device) const;
KService::Ptr pluginService(const QString& pluginName) const;
KdeConnectPlugin* instantiatePluginForDevice(const QString& name, Device* device) const;
private:
PluginLoader();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment