From 5e151d185e5d0b263f49cb3f455c1cff8992989a Mon Sep 17 00:00:00 2001 From: Aleix Pol Gonzalez Date: Tue, 29 Oct 2013 17:29:31 +0100 Subject: [PATCH] Improved package dispatch to the different plugins Before this patch, all plugins had to discard received packages that were not for themselves. This could be a security problem (a plugin could sniff other plugin's packages) and also adds some complexity and processing. This patch makes the device instance aware of what services are required by the different plugins and when a package is received the corresponding plugins will get the package. These services will be listed on the plugin's desktop file, so the user can decide whether to enable a plugin. Note that this only works for receiving, not sending. REVIEW: 113210 --- kded/device.cpp | 43 +++++++++---------- kded/device.h | 5 +-- kded/networkpackagetypes.h | 1 - kded/plugins/battery/batteryplugin.cpp | 3 -- .../battery/kdeconnect_battery.desktop | 2 + kded/plugins/clipboard/clipboardplugin.cpp | 11 ++--- .../clipboard/kdeconnect_clipboard.desktop | 2 + kded/plugins/kdeconnect_plugin.desktop | 4 ++ .../kdeconnect_mpriscontrol.desktop | 2 + .../mpriscontrol/mpriscontrolplugin.cpp | 5 --- .../kdeconnect_notifications.desktop | 2 + .../notifications/notificationsplugin.cpp | 1 - .../pausemusic/kdeconnect_pausemusic.desktop | 2 + kded/plugins/pausemusic/pausemusicplugin.cpp | 9 ++-- kded/plugins/ping/kdeconnect_ping.desktop | 2 + kded/plugins/ping/pingplugin.cpp | 3 -- kded/plugins/pluginloader.cpp | 19 ++++---- kded/plugins/pluginloader.h | 9 +++- .../kdeconnect_sharereceiver.desktop | 2 + .../sharereceiver/sharereceiverplugin.cpp | 1 - kded/plugins/telephony/telephonyplugin.cpp | 3 -- kded/plugins/telephony/telephonyplugin.h | 2 + 22 files changed, 68 insertions(+), 65 deletions(-) diff --git a/kded/device.cpp b/kded/device.cpp index aee0c8b50..fd9c43019 100644 --- a/kded/device.cpp +++ b/kded/device.cpp @@ -1,12 +1,10 @@ #include "device.h" -#include #include #include #include #include #include -#include #include #include @@ -66,7 +64,8 @@ QStringList Device::loadedPlugins() const void Device::reloadPlugins() { - QMap< QString, KdeConnectPlugin* > newPluginMap; + QMap newPluginMap; + QMultiMap newPluginsByInterface; if (isPaired() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices @@ -83,18 +82,19 @@ void Device::reloadPlugins() : loader->getPluginInfo(pluginName).isPluginEnabledByDefault()); if (isPluginEnabled) { - KdeConnectPlugin* reusedPluginInstance = m_plugins.take(pluginName); - if (reusedPluginInstance) { - //Already loaded, reuse it - newPluginMap[pluginName] = reusedPluginInstance; + KdeConnectPlugin* plugin = m_plugins.take(pluginName); + QStringList interfaces; + if (plugin) { + interfaces = m_pluginsByinterface.keys(plugin); } else { - KdeConnectPlugin* plugin = loader->instantiatePluginForDevice(pluginName, this); - - connect(this, SIGNAL(receivedPackage(NetworkPackage)), - plugin, SLOT(receivePackage(NetworkPackage))); - - newPluginMap[pluginName] = plugin; + PluginData data = loader->instantiatePluginForDevice(pluginName, this); + plugin = data.plugin; + interfaces = data.interfaces; } + foreach(const QString& interface, interfaces) { + newPluginsByInterface.insert(interface, plugin); + } + newPluginMap[pluginName] = plugin; } } } @@ -103,6 +103,7 @@ void Device::reloadPlugins() //them anymore, otherwise they would have been moved to the newPluginMap) qDeleteAll(m_plugins); m_plugins = newPluginMap; + m_pluginsByinterface = newPluginsByInterface; Q_FOREACH(KdeConnectPlugin* plugin, m_plugins) { plugin->connected(); @@ -346,16 +347,14 @@ void Device::privateReceivedPackage(const NetworkPackage& np) } - } else if (!isPaired()) { - + } else if (isPaired()) { + QList plugins = m_pluginsByinterface.values(np.type()); + foreach(KdeConnectPlugin* plugin, plugins) { + plugin->receivePackage(np); + } + } else { //TODO: Notify the other side that we don't trust them qDebug() << "device" << name() << "not paired, ignoring package" << np.type(); - - } else { - - //Forward package - Q_EMIT receivedPackage(np); - } } @@ -415,7 +414,7 @@ QStringList Device::availableLinks() const void Device::sendPing() { - NetworkPackage np("kdeconnect.ping"); + NetworkPackage np(PACKAGE_TYPE_PING); bool success = sendPackage(np); qDebug() << "sendPing:" << success; } diff --git a/kded/device.h b/kded/device.h index 196558bca..e01cc9b7f 100644 --- a/kded/device.h +++ b/kded/device.h @@ -82,10 +82,6 @@ public: Q_SCRIPTABLE QStringList loadedPlugins() const; Q_SCRIPTABLE bool hasPlugin(const QString& name) const; -Q_SIGNALS: - ///notifies about a @p np package that has just been received from the device - void receivedPackage(const NetworkPackage& np) const; - public Q_SLOTS: ///sends a @p np package to the device virtual bool sendPackage(NetworkPackage& np); @@ -121,6 +117,7 @@ private: QList m_deviceLinks; QMap m_plugins; + QMultiMap m_pluginsByinterface; QTimer pairingTimer; diff --git a/kded/networkpackagetypes.h b/kded/networkpackagetypes.h index 617d171e3..553faba5d 100644 --- a/kded/networkpackagetypes.h +++ b/kded/networkpackagetypes.h @@ -24,7 +24,6 @@ #define PACKAGE_TYPE_IDENTITY QLatin1String("kdeconnect.identity") #define PACKAGE_TYPE_PAIR QLatin1String("kdeconnect.pair") #define PACKAGE_TYPE_ENCRYPTED QLatin1String("kdeconnect.encrypted") -#define PACKAGE_TYPE_TELEPHONY QLatin1String("kdeconnect.telephony") #define PACKAGE_TYPE_PING QLatin1String("kdeconnect.ping") #endif // NETWORKPACKAGETYPES_H diff --git a/kded/plugins/battery/batteryplugin.cpp b/kded/plugins/battery/batteryplugin.cpp index ecd247e5a..2d9ccac2f 100644 --- a/kded/plugins/battery/batteryplugin.cpp +++ b/kded/plugins/battery/batteryplugin.cpp @@ -58,9 +58,6 @@ BatteryPlugin::~BatteryPlugin() bool BatteryPlugin::receivePackage(const NetworkPackage& np) { - - if (np.type() != PACKAGE_TYPE_BATTERY) return false; - bool isCharging = np.get("isCharging"); int currentCharge = np.get("currentCharge"); diff --git a/kded/plugins/battery/kdeconnect_battery.desktop b/kded/plugins/battery/kdeconnect_battery.desktop index 28a456f2f..eeab93cdf 100644 --- a/kded/plugins/battery/kdeconnect_battery.desktop +++ b/kded/plugins/battery/kdeconnect_battery.desktop @@ -37,3 +37,5 @@ Comment[ru]=Показывать значок батареи устройств Comment[sv]=Visa telefonens batteri intill datorbatteriet Comment[uk]=Показ даних щодо рівня заряду акумулятора на телефоні поряд з даними щодо рівня заряду акумулятора комп’ютера Comment[x-test]=xxShow your phone battery next to your computer batteryxx + +X-KdeConnect-SupportedPackageType=kdeconnect.battery diff --git a/kded/plugins/clipboard/clipboardplugin.cpp b/kded/plugins/clipboard/clipboardplugin.cpp index 15f1dca21..055926e3e 100644 --- a/kded/plugins/clipboard/clipboardplugin.cpp +++ b/kded/plugins/clipboard/clipboardplugin.cpp @@ -29,8 +29,8 @@ K_EXPORT_PLUGIN( KdeConnectPluginFactory("kdeconnect_clipboard", "kdeconnect_cli ClipboardPlugin::ClipboardPlugin(QObject *parent, const QVariantList &args) : KdeConnectPlugin(parent, args) - , clipboard(QApplication::clipboard()) , ignore_next_clipboard_change(false) + , clipboard(QApplication::clipboard()) { connect(clipboard, SIGNAL(changed(QClipboard::Mode)), this, SLOT(clipboardChanged(QClipboard::Mode))); } @@ -51,10 +51,7 @@ void ClipboardPlugin::clipboardChanged(QClipboard::Mode mode) bool ClipboardPlugin::receivePackage(const NetworkPackage& np) { - if (np.type() == PACKAGE_TYPE_CLIPBOARD) { - ignore_next_clipboard_change = true; - clipboard->setText(np.get("content")); - return true; - } - return false; + ignore_next_clipboard_change = true; + clipboard->setText(np.get("content")); + return true; } diff --git a/kded/plugins/clipboard/kdeconnect_clipboard.desktop b/kded/plugins/clipboard/kdeconnect_clipboard.desktop index c670236d6..9a5acd964 100644 --- a/kded/plugins/clipboard/kdeconnect_clipboard.desktop +++ b/kded/plugins/clipboard/kdeconnect_clipboard.desktop @@ -37,3 +37,5 @@ Comment[ru]=Общий буфер обмена для всех устройст Comment[sv]=Dela klippbordet mellan apparater Comment[uk]=Спільне використання буфера обміну даними на пристроях Comment[x-test]=xxShare the clipboard between devicesxx + +X-KdeConnect-SupportedPackageType=kdeconnect.clipboard diff --git a/kded/plugins/kdeconnect_plugin.desktop b/kded/plugins/kdeconnect_plugin.desktop index 368435af7..bf2bf0fc2 100644 --- a/kded/plugins/kdeconnect_plugin.desktop +++ b/kded/plugins/kdeconnect_plugin.desktop @@ -15,3 +15,7 @@ Name[sk]=Plugin KDEConnect Name[sv]=KDE anslutningsinsticksprogram Name[uk]=Додаток KDEConnect Name[x-test]=xxKDEConnect Pluginxx + +# mandatory, list of all the package types supported +[PropertyDef::X-KdeConnect-SupportedPackageType] +Type=QStringList diff --git a/kded/plugins/mpriscontrol/kdeconnect_mpriscontrol.desktop b/kded/plugins/mpriscontrol/kdeconnect_mpriscontrol.desktop index 873abfda1..59ef29b50 100644 --- a/kded/plugins/mpriscontrol/kdeconnect_mpriscontrol.desktop +++ b/kded/plugins/mpriscontrol/kdeconnect_mpriscontrol.desktop @@ -34,3 +34,5 @@ Comment[ru]=Дистанционное управление музыкой и в Comment[sv]=Fjärrstyr musik och videor Comment[uk]=Віддалене керування відтворенням музики та відео Comment[x-test]=xxRemote control your music and videosxx + +X-KdeConnect-SupportedPackageType=kdeconnect.mpris diff --git a/kded/plugins/mpriscontrol/mpriscontrolplugin.cpp b/kded/plugins/mpriscontrol/mpriscontrolplugin.cpp index 00189800f..a1886be02 100644 --- a/kded/plugins/mpriscontrol/mpriscontrolplugin.cpp +++ b/kded/plugins/mpriscontrol/mpriscontrolplugin.cpp @@ -137,11 +137,6 @@ void MprisControlPlugin::removePlayer(const QString& ifaceName) bool MprisControlPlugin::receivePackage (const NetworkPackage& np) { - - if (np.type() != PACKAGE_TYPE_MPRIS) { - return false; - } - if (np.has("playerList")) { return false; //Whoever sent this is an mpris client and not an mpris control! } diff --git a/kded/plugins/notifications/kdeconnect_notifications.desktop b/kded/plugins/notifications/kdeconnect_notifications.desktop index c686ed3fa..e55ef6999 100644 --- a/kded/plugins/notifications/kdeconnect_notifications.desktop +++ b/kded/plugins/notifications/kdeconnect_notifications.desktop @@ -35,3 +35,5 @@ Comment[ru]=Показывать телефонные уведомления в Comment[sv]=Visa telefonunderrättelser i KDE och håll dem synkroniserade Comment[uk]=Показ сповіщень з телефону у KDE та підтримання синхронізації даних сповіщень Comment[x-test]=xxShow phone notifications in KDE and keep them in syncxx + +X-KdeConnect-SupportedPackageType=kdeconnect.notifications diff --git a/kded/plugins/notifications/notificationsplugin.cpp b/kded/plugins/notifications/notificationsplugin.cpp index c2b900c38..77eb5d6bf 100644 --- a/kded/plugins/notifications/notificationsplugin.cpp +++ b/kded/plugins/notifications/notificationsplugin.cpp @@ -56,7 +56,6 @@ NotificationsPlugin::~NotificationsPlugin() bool NotificationsPlugin::receivePackage(const NetworkPackage& np) { - if (np.type() != PACKAGE_TYPE_NOTIFICATION) return false; if (np.get("request")) return false; notificationsDbusInterface->processPackage(np); diff --git a/kded/plugins/pausemusic/kdeconnect_pausemusic.desktop b/kded/plugins/pausemusic/kdeconnect_pausemusic.desktop index cbe869636..10a600c36 100644 --- a/kded/plugins/pausemusic/kdeconnect_pausemusic.desktop +++ b/kded/plugins/pausemusic/kdeconnect_pausemusic.desktop @@ -33,3 +33,5 @@ Comment[ru]=Приостанавливать музыку/видео во вре Comment[sv]=Pausa musik eller videor under ett telefonsamtal Comment[uk]=Призупинка відтворення музики і відео на час телефонних дзвінків Comment[x-test]=xxPause music/videos during a phone callxx + +X-KdeConnect-SupportedPackageType=kdeconnect.telephony diff --git a/kded/plugins/pausemusic/pausemusicplugin.cpp b/kded/plugins/pausemusic/pausemusicplugin.cpp index 8f6d3aa1b..b4ab54880 100644 --- a/kded/plugins/pausemusic/pausemusicplugin.cpp +++ b/kded/plugins/pausemusic/pausemusicplugin.cpp @@ -38,11 +38,6 @@ PauseMusicPlugin::PauseMusicPlugin(QObject* parent, const QVariantList& args) bool PauseMusicPlugin::receivePackage(const NetworkPackage& np) { - - if (np.type() != PACKAGE_TYPE_TELEPHONY) { - return false; - } - switch(pauseWhen) { case PauseWhenRinging: if (np.get("event") != "ringing" && np.get("event") != "talking") { @@ -54,6 +49,8 @@ bool PauseMusicPlugin::receivePackage(const NetworkPackage& np) return true; } break; + case NeverPause: + return true; } bool pauseConditionFulfilled = !np.get("isCancel"); @@ -76,7 +73,7 @@ bool PauseMusicPlugin::receivePackage(const NetworkPackage& np) } else { Q_FOREACH (const QString& iface, pausedSources) { QDBusInterface mprisInterface(iface, "/org/mpris/MediaPlayer2", "org.mpris.MediaPlayer2.Player"); - //Calling play does not work in spotify + //Calling play does not work for Spotify //mprisInterface->call(QDBus::Block,"Play"); //Workaround: Using playpause instead (checking first if it is already playing) QString status = mprisInterface.property("PlaybackStatus").toString(); diff --git a/kded/plugins/ping/kdeconnect_ping.desktop b/kded/plugins/ping/kdeconnect_ping.desktop index 2db146c7b..a60792d4c 100644 --- a/kded/plugins/ping/kdeconnect_ping.desktop +++ b/kded/plugins/ping/kdeconnect_ping.desktop @@ -39,3 +39,5 @@ Comment[sk]=Poslať a prijať pingy Comment[sv]=Skicka och ta emot ping Comment[uk]=Надсилання і отримання сигналів підтримання зв’язку Comment[x-test]=xxSend and receive pingsxx + +X-KdeConnect-SupportedPackageType=kdeconnect.ping diff --git a/kded/plugins/ping/pingplugin.cpp b/kded/plugins/ping/pingplugin.cpp index 052d41fa3..cd05f6a14 100644 --- a/kded/plugins/ping/pingplugin.cpp +++ b/kded/plugins/ping/pingplugin.cpp @@ -42,9 +42,6 @@ PingPlugin::~PingPlugin() bool PingPlugin::receivePackage(const NetworkPackage& np) { - - if (np.type() != PACKAGE_TYPE_PING) return false; - KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent notification->setPixmap(KIcon("dialog-ok").pixmap(48, 48)); notification->setComponentData(KComponentData("kdeconnect", "kdeconnect")); diff --git a/kded/plugins/pluginloader.cpp b/kded/plugins/pluginloader.cpp index f6ce89cc2..49e117035 100644 --- a/kded/plugins/pluginloader.cpp +++ b/kded/plugins/pluginloader.cpp @@ -59,30 +59,33 @@ KPluginInfo PluginLoader::getPluginInfo(const QString& name) const return KPluginInfo(service); } -KdeConnectPlugin* PluginLoader::instantiatePluginForDevice(const QString& name, Device* device) const +PluginData PluginLoader::instantiatePluginForDevice(const QString& name, Device* device) const { + PluginData ret; + KService::Ptr service = plugins[name]; if (!service) { qDebug() << "Plugin unknown" << name; - return NULL; + return ret; } KPluginFactory *factory = KPluginLoader(service->library()).factory(); if (!factory) { qDebug() << "KPluginFactory could not load the plugin:" << service->library(); - return NULL; + return ret; } + ret.interfaces = service->property("X-KdeConnect-SupportedPackageType", QVariant::StringList).toStringList(); + QVariant deviceVariant = QVariant::fromValue(device); - //FIXME: create return NULL - QObject *plugin = factory->create(device, QVariantList() << deviceVariant); - if (!plugin) { + ret.plugin = (KdeConnectPlugin*) factory->create(device, QVariantList() << deviceVariant); + if (!ret.plugin) { qDebug() << "Error loading plugin"; - return NULL; + return ret; } qDebug() << "Loaded plugin:" << service->name(); - return (KdeConnectPlugin*)plugin; + return ret; } diff --git a/kded/plugins/pluginloader.h b/kded/plugins/pluginloader.h index 32652e53f..1a03259b8 100644 --- a/kded/plugins/pluginloader.h +++ b/kded/plugins/pluginloader.h @@ -32,6 +32,13 @@ class Device; class KdeConnectPlugin; +struct PluginData +{ + PluginData() : plugin(0) {} + KdeConnectPlugin* plugin; + QStringList interfaces; +}; + class PluginLoader { @@ -40,7 +47,7 @@ public: QStringList getPluginList() const; KPluginInfo getPluginInfo(const QString& name) const; - KdeConnectPlugin* instantiatePluginForDevice(const QString& name, Device* device) const; + PluginData instantiatePluginForDevice(const QString& name, Device* device) const; private: PluginLoader(); diff --git a/kded/plugins/sharereceiver/kdeconnect_sharereceiver.desktop b/kded/plugins/sharereceiver/kdeconnect_sharereceiver.desktop index e37e349b1..aa759ad16 100644 --- a/kded/plugins/sharereceiver/kdeconnect_sharereceiver.desktop +++ b/kded/plugins/sharereceiver/kdeconnect_sharereceiver.desktop @@ -29,3 +29,5 @@ Comment[ru]=Получать общие файлы и адреса URL с тел Comment[sv]=Ta emot filer och webbadresser att dela från din telefon Comment[uk]=Отримання файлів та адрес, наданих у спільне користування з вашого телефону Comment[x-test]=xxReceive files and URLs shared from your phonexx + +X-KdeConnect-SupportedPackageType=kdeconnect.share diff --git a/kded/plugins/sharereceiver/sharereceiverplugin.cpp b/kded/plugins/sharereceiver/sharereceiverplugin.cpp index c301de2b6..e389eb669 100644 --- a/kded/plugins/sharereceiver/sharereceiverplugin.cpp +++ b/kded/plugins/sharereceiver/sharereceiverplugin.cpp @@ -66,7 +66,6 @@ bool ShareReceiverPlugin::receivePackage(const NetworkPackage& np) } */ - if (np.type() != PACKAGE_TYPE_SHARE) return false; qDebug() << "File transfer"; if (np.hasPayload()) { diff --git a/kded/plugins/telephony/telephonyplugin.cpp b/kded/plugins/telephony/telephonyplugin.cpp index 8386a219a..ecc43e11d 100644 --- a/kded/plugins/telephony/telephonyplugin.cpp +++ b/kded/plugins/telephony/telephonyplugin.cpp @@ -80,9 +80,6 @@ KNotification* TelephonyPlugin::createNotification(const NetworkPackage& np) bool TelephonyPlugin::receivePackage(const NetworkPackage& np) { - - if (np.type() != PACKAGE_TYPE_TELEPHONY) return false; - if (np.get("isCancel")) { //It would be awesome to remove the old notification from the system tray here, but there is no way to do it :( diff --git a/kded/plugins/telephony/telephonyplugin.h b/kded/plugins/telephony/telephonyplugin.h index ff66d638f..c9723aac4 100644 --- a/kded/plugins/telephony/telephonyplugin.h +++ b/kded/plugins/telephony/telephonyplugin.h @@ -27,6 +27,8 @@ #include +#define PACKAGE_TYPE_TELEPHONY QLatin1String("kdeconnect.telephony") + class TelephonyPlugin : public KdeConnectPlugin {