[kdeconnect-kde] core: Use the incoming/outgoing capabilities for trimming loaded plugins

Aleix Pol aleixpol at kde.org
Thu Jul 10 23:54:56 UTC 2014


Git commit 380006114a3d3ebdea768c894ae9fe3c2cc4fe85 by Aleix Pol.
Committed on 10/07/2014 at 23:54.
Pushed by apol into branch 'master'.

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 at kde.org

M  +22   -4    core/device.cpp
M  +2    -0    core/device.h
M  +3    -0    core/networkpackage.cpp
M  +27   -7    core/pluginloader.cpp
M  +4    -9    core/pluginloader.h

http://commits.kde.org/kdeconnect-kde/380006114a3d3ebdea768c894ae9fe3c2cc4fe85

diff --git a/core/device.cpp b/core/device.cpp
index dacc7db..e0f9178 100644
--- a/core/device.cpp
+++ b/core/device.cpp
@@ -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);
                 }
diff --git a/core/device.h b/core/device.h
index d154300..82ecd81 100644
--- a/core/device.h
+++ b/core/device.h
@@ -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();
diff --git a/core/networkpackage.cpp b/core/networkpackage.cpp
index 330850c..bd3cccd 100644
--- a/core/networkpackage.cpp
+++ b/core/networkpackage.cpp
@@ -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();
 }
diff --git a/core/pluginloader.cpp b/core/pluginloader.cpp
index b5f9714..12d7864 100644
--- a/core/pluginloader.cpp
+++ b/core/pluginloader.cpp
@@ -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();
+}
diff --git a/core/pluginloader.h b/core/pluginloader.h
index 4983730..e92b73e 100644
--- a/core/pluginloader.h
+++ b/core/pluginloader.h
@@ -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();


More information about the KDEConnect mailing list