2014-06-09 10:52:16 +01:00
/**
* Copyright 2013 Albert Vaca < albertvaka @ gmail . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation ; either version 2 of
* the License or ( at your option ) version 3 or any later version
* accepted by the membership of KDE e . V . ( or its successor approved
* by the membership of KDE e . V . ) , which shall act as a proxy
* defined in Section 14 of version 3 of the license .
*
* 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 General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2013-06-25 17:06:51 +01:00
# include "device.h"
2013-08-12 15:09:52 +01:00
2014-06-09 10:52:16 +01:00
# ifdef interface // MSVC language extension, QDBusConnection uses this as a variable name
# undef interface
# endif
# include <QDBusConnection>
# include <QFile>
2014-09-22 00:23:27 +01:00
# include <QStandardPaths>
2014-06-09 10:52:16 +01:00
2013-08-12 15:09:52 +01:00
# include <KSharedConfig>
2013-07-03 02:52:44 +01:00
# include <KConfigGroup>
2014-09-22 01:37:10 +01:00
# include <KLocalizedString>
2014-09-13 00:04:48 +01:00
# include <QIcon>
2015-03-02 04:16:07 +00:00
# include <QDir>
2015-03-19 15:36:53 +00:00
# include <QJsonArray>
2013-08-13 04:07:32 +01:00
2014-09-21 23:59:34 +01:00
# include "core_debug.h"
2014-06-14 15:34:00 +01:00
# include "kdeconnectplugin.h"
# include "pluginloader.h"
2013-09-09 17:35:56 +01:00
# include "backends/devicelink.h"
# include "backends/linkprovider.h"
2013-08-12 15:09:52 +01:00
# include "networkpackage.h"
2015-03-02 04:16:07 +00:00
# include "kdeconnectconfig.h"
2015-03-24 11:26:37 +00:00
# include "daemon.h"
2013-08-12 15:09:52 +01:00
2014-09-21 22:54:27 +01:00
Q_LOGGING_CATEGORY ( KDECONNECT_CORE , " kdeconnect.core " )
2014-01-22 22:31:27 +00:00
Device : : Device ( QObject * parent , const QString & id )
: QObject ( parent )
, m_deviceId ( id )
2013-10-11 14:19:23 +01:00
, m_pairStatus ( Device : : Paired )
, m_protocolVersion ( NetworkPackage : : ProtocolVersion ) //We don't know it yet
2013-07-03 02:52:44 +01:00
{
2015-03-02 04:16:07 +00:00
KdeConnectConfig : : DeviceInfo info = KdeConnectConfig : : instance ( ) - > getTrustedDevice ( id ) ;
2013-07-26 15:21:19 +01:00
2015-03-02 04:16:07 +00:00
m_deviceName = info . deviceName ;
m_deviceType = str2type ( info . deviceType ) ;
m_publicKey = QCA : : RSAPublicKey : : fromPEM ( info . publicKey ) ;
2015-03-13 23:39:13 +00:00
2013-07-26 15:21:19 +01:00
//Register in bus
2013-08-20 12:52:25 +01:00
QDBusConnection : : sessionBus ( ) . registerObject ( dbusPath ( ) , this , QDBusConnection : : ExportScriptableContents | QDBusConnection : : ExportAdaptors ) ;
2013-06-25 17:06:51 +01:00
}
2013-07-03 02:52:44 +01:00
2014-01-22 22:31:27 +00:00
Device : : Device ( QObject * parent , const NetworkPackage & identityPackage , DeviceLink * dl )
: QObject ( parent )
, m_deviceId ( identityPackage . get < QString > ( " deviceId " ) )
2013-10-11 14:19:23 +01:00
, m_deviceName ( identityPackage . get < QString > ( " deviceName " ) )
2013-11-06 20:31:37 +00:00
, m_deviceType ( str2type ( identityPackage . get < QString > ( " deviceType " ) ) )
2013-10-11 14:19:23 +01:00
, m_pairStatus ( Device : : NotPaired )
2015-09-11 11:34:52 +01:00
, m_protocolVersion ( identityPackage . get < int > ( " protocolVersion " , - 1 ) )
2013-07-03 02:52:44 +01:00
{
2014-01-17 22:07:30 +00:00
addLink ( identityPackage , dl ) ;
2015-09-08 16:28:47 +01:00
2013-08-16 05:26:40 +01:00
//Register in bus
2013-08-20 12:52:25 +01:00
QDBusConnection : : sessionBus ( ) . registerObject ( dbusPath ( ) , this , QDBusConnection : : ExportScriptableContents | QDBusConnection : : ExportAdaptors ) ;
2015-06-12 16:54:47 +01:00
//Implement deprecated signals
connect ( this , & Device : : pairingChanged , this , [ this ] ( bool newPairing ) {
if ( newPairing )
Q_EMIT pairingSuccesful ( ) ;
else
Q_EMIT unpaired ( ) ;
} ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-16 08:27:32 +01:00
Device : : ~ Device ( )
{
2015-09-11 16:25:23 +01:00
qDeleteAll ( m_pairingHandlers ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-13 04:07:32 +01:00
2013-09-01 21:13:03 +01:00
bool Device : : hasPlugin ( const QString & name ) const
2013-08-13 22:23:32 +01:00
{
return m_plugins . contains ( name ) ;
}
2013-09-01 21:13:03 +01:00
QStringList Device : : loadedPlugins ( ) const
2013-08-18 19:27:25 +01:00
{
return m_plugins . keys ( ) ;
}
2013-08-13 04:07:32 +01:00
void Device : : reloadPlugins ( )
{
2015-03-14 03:07:55 +00:00
QHash < QString , KdeConnectPlugin * > newPluginMap ;
2014-06-14 19:35:00 +01:00
QMultiMap < QString , KdeConnectPlugin * > newPluginsByIncomingInterface ;
QMultiMap < QString , KdeConnectPlugin * > newPluginsByOutgoingInterface ;
2015-09-08 16:28:47 +01:00
QSet < QString > supportedIncomingInterfaces ;
2015-09-12 16:48:24 +01:00
QSet < QString > supportedOutgoingInterfaces ;
2015-09-08 16:38:33 +01:00
QStringList unsupportedPlugins ;
2013-08-13 04:07:32 +01:00
2013-08-31 12:04:00 +01:00
if ( isPaired ( ) & & isReachable ( ) ) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
2013-08-13 04:07:32 +01:00
2015-03-02 04:16:07 +00:00
KConfigGroup pluginStates = KSharedConfig : : openConfig ( pluginsConfigFile ( ) ) - > group ( " Plugins " ) ;
2013-08-13 04:07:32 +01:00
2013-08-14 00:35:12 +01:00
PluginLoader * loader = PluginLoader : : instance ( ) ;
2015-09-11 12:56:51 +01:00
const bool deviceSupportsCapabilities = ! m_incomingCapabilities . isEmpty ( ) | | ! m_outgoingCapabilities . isEmpty ( ) ;
2013-08-13 04:07:32 +01:00
2013-08-14 00:35:12 +01:00
foreach ( const QString & pluginName , loader - > getPluginList ( ) ) {
2015-09-08 19:03:44 +01:00
const KPluginMetaData service = loader - > getPluginInfo ( pluginName ) ;
const QSet < QString > incomingInterfaces = KPluginMetaData : : readStringList ( service . rawData ( ) , " X-KdeConnect-SupportedPackageType " ) . toSet ( ) ;
const QSet < QString > outgoingInterfaces = KPluginMetaData : : readStringList ( service . rawData ( ) , " X-KdeConnect-OutgoingPackageType " ) . toSet ( ) ;
2013-08-13 04:07:32 +01:00
2015-09-08 19:03:44 +01:00
const bool pluginEnabled = isPluginEnabled ( pluginName ) ;
2013-08-13 04:07:32 +01:00
2015-09-09 09:14:30 +01:00
if ( pluginEnabled ) {
2015-09-08 16:34:48 +01:00
supportedIncomingInterfaces + = incomingInterfaces ;
2015-09-12 16:48:24 +01:00
supportedOutgoingInterfaces + = outgoingInterfaces ;
2015-09-09 09:14:30 +01:00
}
2014-07-11 00:54:19 +01:00
2015-09-08 19:03:44 +01:00
//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 assume that the other client doesn't know about capabilities.
2015-09-11 13:04:54 +01:00
const bool capabilitiesSupported = deviceSupportsCapabilities & & ( ! incomingInterfaces . isEmpty ( ) | | ! outgoingInterfaces . isEmpty ( ) ) ;
if ( capabilitiesSupported
2015-09-08 19:03:44 +01:00
& & ( m_incomingCapabilities & outgoingInterfaces ) . isEmpty ( )
& & ( m_outgoingCapabilities & incomingInterfaces ) . isEmpty ( )
) {
qCWarning ( KDECONNECT_CORE ) < < " not loading " < < pluginName < < " because of unmatched capabilities " ;
unsupportedPlugins . append ( pluginName ) ;
continue ;
}
if ( pluginEnabled ) {
KdeConnectPlugin * plugin = m_plugins . take ( pluginName ) ;
2014-07-11 00:54:19 +01:00
if ( ! plugin ) {
plugin = loader - > instantiatePluginForDevice ( pluginName , this ) ;
}
2014-06-14 19:35:00 +01:00
foreach ( const QString & interface , incomingInterfaces ) {
newPluginsByIncomingInterface . insert ( interface , plugin ) ;
}
foreach ( const QString & interface , outgoingInterfaces ) {
newPluginsByOutgoingInterface . insert ( interface , plugin ) ;
2013-08-14 00:35:12 +01:00
}
2015-09-12 16:48:24 +01:00
2013-10-29 16:29:31 +00:00
newPluginMap [ pluginName ] = plugin ;
2013-08-14 00:35:12 +01:00
}
2013-08-13 04:07:32 +01:00
}
}
2013-10-11 14:19:23 +01:00
//Erase all left plugins in the original map (meaning that we don't want
//them anymore, otherwise they would have been moved to the newPluginMap)
2015-09-08 16:28:47 +01:00
const QStringList newSupportedIncomingInterfaces = supportedIncomingInterfaces . toList ( ) ;
2015-09-12 16:48:24 +01:00
const QStringList newSupportedOutgoingInterfaces = supportedOutgoingInterfaces . toList ( ) ;
2015-09-08 16:28:47 +01:00
const bool capabilitiesChanged = ( m_pluginsByOutgoingInterface ! = newPluginsByOutgoingInterface
| | m_supportedIncomingInterfaces ! = newSupportedIncomingInterfaces ) ;
2013-08-14 00:35:12 +01:00
qDeleteAll ( m_plugins ) ;
m_plugins = newPluginMap ;
2015-09-08 16:28:47 +01:00
m_supportedIncomingInterfaces = newSupportedIncomingInterfaces ;
2015-09-12 16:48:24 +01:00
m_supportedOutgoingInterfaces = newSupportedOutgoingInterfaces ;
m_pluginsByOutgoingInterface = newPluginsByOutgoingInterface ;
2015-09-08 16:28:47 +01:00
m_pluginsByIncomingInterface = newPluginsByIncomingInterface ;
2015-09-08 16:38:33 +01:00
m_unsupportedPlugins = unsupportedPlugins ;
2013-08-14 00:35:12 +01:00
2013-08-22 02:21:08 +01:00
Q_FOREACH ( KdeConnectPlugin * plugin , m_plugins ) {
2013-10-11 14:19:23 +01:00
plugin - > connected ( ) ;
2013-08-22 02:21:08 +01:00
}
2013-08-13 22:23:32 +01:00
Q_EMIT pluginsChanged ( ) ;
2013-08-13 04:07:32 +01:00
2015-09-09 09:14:30 +01:00
if ( capabilitiesChanged & & isReachable ( ) & & isPaired ( ) )
2015-09-08 16:28:47 +01:00
{
NetworkPackage np ( PACKAGE_TYPE_CAPABILITIES ) ;
2015-09-11 13:20:46 +01:00
np . set < QStringList > ( " IncomingCapabilities " , newSupportedIncomingInterfaces ) ;
2015-09-12 16:48:24 +01:00
np . set < QStringList > ( " OutgoingCapabilities " , newSupportedOutgoingInterfaces ) ;
2015-09-08 16:28:47 +01:00
sendPackage ( np ) ;
}
2013-08-13 04:07:32 +01:00
}
2015-03-02 04:16:07 +00:00
QString Device : : pluginsConfigFile ( ) const
{
return KdeConnectConfig : : instance ( ) - > deviceConfigDir ( id ( ) ) . absoluteFilePath ( " config " ) ;
}
2015-07-27 16:28:58 +01:00
bool Device : : pairRequested ( ) const
{
2015-08-11 04:34:02 +01:00
bool isPairRequested = false ;
2015-07-27 16:28:58 +01:00
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers ) {
2015-08-11 04:34:02 +01:00
isPairRequested = isPairRequested | | ph - > pairRequested ( ) ;
2015-07-27 16:28:58 +01:00
}
2015-08-11 04:34:02 +01:00
return isPairRequested ;
2015-07-27 16:28:58 +01:00
}
2013-08-30 18:10:43 +01:00
void Device : : requestPair ( )
2013-07-03 02:52:44 +01:00
{
2013-10-11 14:19:23 +01:00
switch ( m_pairStatus ) {
case Device : : Paired :
Q_EMIT pairingFailed ( i18n ( " Already paired " ) ) ;
return ;
2015-06-15 03:22:13 +01:00
case Device : : NotPaired :
;
}
if ( ! isReachable ( ) ) {
Q_EMIT pairingFailed ( i18n ( " Device not reachable " ) ) ;
return ;
2013-08-30 18:10:43 +01:00
}
//Send our own public key
2015-07-27 16:28:58 +01:00
bool success = false ;
2015-07-25 12:45:19 +01:00
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers . values ( ) ) {
2015-07-27 16:28:58 +01:00
success = success | | ph - > requestPairing ( ) ; // If one of many pairing handlers can successfully request pairing, consider it success
}
if ( ! success ) {
m_pairStatus = Device : : NotPaired ;
Q_EMIT pairingFailed ( i18n ( " Error contacting device " ) ) ;
return ;
2013-07-03 02:52:44 +01:00
}
2013-08-30 18:10:43 +01:00
2014-03-04 01:33:41 +00:00
if ( m_pairStatus = = Device : : Paired ) {
return ;
}
2013-08-30 18:10:43 +01:00
}
void Device : : unpair ( )
{
2015-07-25 12:45:19 +01:00
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers . values ( ) ) {
ph - > unpair ( ) ;
2015-07-09 22:51:08 +01:00
}
2015-08-11 04:34:02 +01:00
unpairInternal ( ) ; // We do not depend on pairing handlers for unpairing, this method is likely to be called due to user events
2015-03-16 02:13:54 +00:00
}
2013-08-30 18:10:43 +01:00
2015-03-16 02:13:54 +00:00
void Device : : unpairInternal ( )
{
2015-06-22 03:39:04 +01:00
bool alreadyUnpaired = ( m_pairStatus ! = Device : : Paired ) ;
2015-03-16 02:13:54 +00:00
m_pairStatus = Device : : NotPaired ;
KdeConnectConfig : : instance ( ) - > removeTrustedDevice ( id ( ) ) ;
reloadPlugins ( ) ; //Will unload the plugins
2015-06-22 03:39:04 +01:00
if ( ! alreadyUnpaired ) {
Q_EMIT pairingChanged ( false ) ;
}
2013-08-30 18:10:43 +01:00
}
void Device : : pairingTimeout ( )
{
2013-09-04 20:19:02 +01:00
Q_EMIT pairingFailed ( i18n ( " Timed out " ) ) ;
2013-07-03 02:52:44 +01:00
}
static bool lessThan ( DeviceLink * p1 , DeviceLink * p2 )
{
2013-07-24 17:42:33 +01:00
return p1 - > provider ( ) - > priority ( ) > p2 - > provider ( ) - > priority ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-10-01 02:11:22 +01:00
void Device : : addLink ( const NetworkPackage & identityPackage , DeviceLink * link )
2013-07-03 02:52:44 +01:00
{
2014-09-21 22:54:27 +01:00
//qCDebug(KDECONNECT_CORE) << "Adding link to" << id() << "via" << link->provider();
2013-07-23 15:11:54 +01:00
2015-09-11 11:34:52 +01:00
m_protocolVersion = identityPackage . get < int > ( " protocolVersion " , - 1 ) ;
2013-10-01 02:11:22 +01:00
if ( m_protocolVersion ! = NetworkPackage : : ProtocolVersion ) {
2015-09-07 17:54:11 +01:00
qCWarning ( KDECONNECT_CORE ) < < m_deviceName < < " - warning, device uses a different protocol version " < < m_protocolVersion < < " expected " < < NetworkPackage : : ProtocolVersion ;
2013-10-01 02:11:22 +01:00
}
2013-08-16 05:26:40 +01:00
connect ( link , SIGNAL ( destroyed ( QObject * ) ) ,
this , SLOT ( linkDestroyed ( QObject * ) ) ) ;
2013-07-04 18:17:22 +01:00
2013-07-03 02:52:44 +01:00
m_deviceLinks . append ( link ) ;
2013-08-10 04:21:55 +01:00
2013-10-14 17:25:44 +01:00
//re-read the device name from the identityPackage because it could have changed
2015-03-14 03:28:54 +00:00
setName ( identityPackage . get < QString > ( " deviceName " ) ) ;
2013-11-06 20:31:37 +00:00
m_deviceType = str2type ( identityPackage . get < QString > ( " deviceType " ) ) ;
2013-10-14 17:25:44 +01:00
2015-07-05 14:23:53 +01:00
// Set certificate if the link is on ssl, and it is added to identity package
// This is always sets certificate when link is added to device
if ( identityPackage . has ( " certificate " ) ) {
m_certificate = QSslCertificate ( identityPackage . get < QByteArray > ( " certificate " ) ) ;
}
2013-08-13 22:23:32 +01:00
//Theoretically we will never add two links from the same provider (the provider should destroy
//the old one before this is called), so we do not have to worry about destroying old links.
2015-03-02 04:16:07 +00:00
//-- Actually, we should not destroy them or the provider will store an invalid ref!
2013-08-10 04:21:55 +01:00
2013-09-01 21:13:03 +01:00
connect ( link , SIGNAL ( receivedPackage ( NetworkPackage ) ) ,
this , SLOT ( privateReceivedPackage ( NetworkPackage ) ) ) ;
2013-07-04 18:17:22 +01:00
2013-09-01 21:13:03 +01:00
qSort ( m_deviceLinks . begin ( ) , m_deviceLinks . end ( ) , lessThan ) ;
2013-07-28 21:00:45 +01:00
if ( m_deviceLinks . size ( ) = = 1 ) {
2015-09-11 13:20:46 +01:00
m_incomingCapabilities = identityPackage . get < QStringList > ( " IncomingCapabilities " , QStringList ( ) ) . toSet ( ) ;
m_outgoingCapabilities = identityPackage . get < QStringList > ( " OutgoingCapabilities " , QStringList ( ) ) . toSet ( ) ;
2013-08-22 02:21:08 +01:00
reloadPlugins ( ) ; //Will load the plugins
2013-08-13 22:23:32 +01:00
Q_EMIT reachableStatusChanged ( ) ;
2013-08-22 02:21:08 +01:00
} else {
Q_FOREACH ( KdeConnectPlugin * plugin , m_plugins ) {
plugin - > connected ( ) ;
}
2013-07-28 21:00:45 +01:00
}
2015-07-25 12:45:19 +01:00
// One pairing handler per type of device link, so check if there is already a pairing handler of same type, if not add it to the list
if ( ! m_pairingHandlers . contains ( link - > name ( ) ) ) {
PairingHandler * pairingHandler = link - > createPairingHandler ( this ) ;
m_pairingHandlers . insert ( link - > name ( ) , pairingHandler ) ;
2015-07-27 16:28:58 +01:00
connect ( m_pairingHandlers [ link - > name ( ) ] , SIGNAL ( linkNull ( ) ) , this , SLOT ( destroyPairingHandler ( ) ) ) ;
connect ( m_pairingHandlers [ link - > name ( ) ] , SIGNAL ( pairingDone ( ) ) , this , SLOT ( setAsPaired ( ) ) ) ;
connect ( m_pairingHandlers [ link - > name ( ) ] , SIGNAL ( unpairingDone ( ) ) , this , SLOT ( unpairInternal ( ) ) ) ;
connect ( m_pairingHandlers [ link - > name ( ) ] , SIGNAL ( pairingFailed ( const QString & ) ) , this , SIGNAL ( pairingFailed ( const QString & ) ) ) ;
2015-07-25 12:45:19 +01:00
}
2015-07-27 16:28:58 +01:00
m_pairingHandlers [ link - > name ( ) ] - > setLink ( link ) ;
2015-07-25 12:45:19 +01:00
connect ( link , SIGNAL ( destroyed ( QObject * ) ) , m_pairingHandlers [ link - > name ( ) ] , SLOT ( linkDestroyed ( QObject * ) ) ) ;
2013-07-03 02:52:44 +01:00
}
2013-07-04 18:17:22 +01:00
void Device : : linkDestroyed ( QObject * o )
{
removeLink ( static_cast < DeviceLink * > ( o ) ) ;
}
2013-07-03 02:52:44 +01:00
void Device : : removeLink ( DeviceLink * link )
{
2013-07-04 18:17:22 +01:00
m_deviceLinks . removeOne ( link ) ;
2013-07-28 21:00:45 +01:00
2014-09-21 22:54:27 +01:00
//qCDebug(KDECONNECT_CORE) << "RemoveLink" << m_deviceLinks.size() << "links remaining";
2013-07-28 21:00:45 +01:00
2013-10-11 14:19:23 +01:00
if ( m_deviceLinks . isEmpty ( ) ) {
2013-08-16 00:01:58 +01:00
reloadPlugins ( ) ;
2013-08-13 22:23:32 +01:00
Q_EMIT reachableStatusChanged ( ) ;
2013-07-28 21:00:45 +01:00
}
2013-07-03 02:52:44 +01:00
}
2015-07-25 12:45:19 +01:00
void Device : : destroyPairingHandler ( )
{
PairingHandler * ph = qobject_cast < PairingHandler * > ( sender ( ) ) ;
m_pairingHandlers . remove ( m_pairingHandlers . key ( ph ) ) ;
delete ph ;
}
2013-09-01 21:13:03 +01:00
bool Device : : sendPackage ( NetworkPackage & np )
2013-07-03 02:52:44 +01:00
{
2013-09-03 15:01:28 +01:00
if ( np . type ( ) ! = PACKAGE_TYPE_PAIR & & isPaired ( ) ) {
2013-09-13 22:27:16 +01:00
Q_FOREACH ( DeviceLink * dl , m_deviceLinks ) {
if ( dl - > sendPackageEncrypted ( m_publicKey , np ) ) return true ;
}
2013-09-01 21:13:03 +01:00
} else {
//Maybe we could block here any package that is not an identity or a pairing package to prevent sending non encrypted data
2013-09-13 22:27:16 +01:00
Q_FOREACH ( DeviceLink * dl , m_deviceLinks ) {
if ( dl - > sendPackage ( np ) ) return true ;
}
2013-08-13 04:40:39 +01:00
}
2013-07-23 15:11:54 +01:00
return false ;
2013-07-03 02:52:44 +01:00
}
void Device : : privateReceivedPackage ( const NetworkPackage & np )
{
2013-08-30 18:10:43 +01:00
if ( np . type ( ) = = PACKAGE_TYPE_PAIR ) {
2015-07-27 16:28:58 +01:00
// If PACKAGE_TYPE_PAIR, send it to pairing handlers without thinking
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers ) {
ph - > packageReceived ( np ) ;
2013-08-30 18:10:43 +01:00
}
2015-09-07 19:03:05 +01:00
} else if ( np . type ( ) = = PACKAGE_TYPE_CAPABILITIES ) {
2015-09-11 13:20:46 +01:00
QSet < QString > newIncomingCapabilities = np . get < QStringList > ( " IncomingCapabilities " , QStringList ( ) ) . toSet ( ) ;
QSet < QString > newOutgoingCapabilities = np . get < QStringList > ( " OutgoingCapabilities " , QStringList ( ) ) . toSet ( ) ;
2015-09-07 19:03:05 +01:00
if ( newOutgoingCapabilities ! = m_outgoingCapabilities | | newIncomingCapabilities ! = m_incomingCapabilities ) {
m_incomingCapabilities = newIncomingCapabilities ;
m_outgoingCapabilities = newOutgoingCapabilities ;
reloadPlugins ( ) ;
}
2013-10-29 16:29:31 +00:00
} else if ( isPaired ( ) ) {
2014-06-14 19:35:00 +01:00
QList < KdeConnectPlugin * > plugins = m_pluginsByIncomingInterface . values ( np . type ( ) ) ;
2013-10-29 16:29:31 +00:00
foreach ( KdeConnectPlugin * plugin , plugins ) {
plugin - > receivePackage ( np ) ;
}
} else {
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " device " < < name ( ) < < " not paired, ignoring package " < < np . type ( ) ;
2015-07-27 16:28:58 +01:00
unpair ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-30 18:10:43 +01:00
}
void Device : : rejectPairing ( )
{
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Rejected pairing " ;
2013-08-30 18:10:43 +01:00
2013-09-03 21:11:13 +01:00
m_pairStatus = Device : : NotPaired ;
2015-07-25 12:45:19 +01:00
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers . values ( ) ) {
ph - > rejectPairing ( ) ;
2015-07-09 22:51:08 +01:00
}
2013-08-30 18:10:43 +01:00
2013-09-03 21:11:13 +01:00
Q_EMIT pairingFailed ( i18n ( " Canceled by the user " ) ) ;
2013-08-30 18:10:43 +01:00
2013-07-03 02:52:44 +01:00
}
2013-11-06 20:34:06 +00:00
void Device : : acceptPairing ( )
{
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Accepted pairing " ;
2013-11-06 20:34:06 +00:00
2015-07-27 16:28:58 +01:00
bool success = false ;
2015-07-25 12:45:19 +01:00
Q_FOREACH ( PairingHandler * ph , m_pairingHandlers . values ( ) ) {
2015-07-27 16:28:58 +01:00
success = success | | ph - > acceptPairing ( ) ;
2015-07-09 22:51:08 +01:00
}
2013-11-06 20:34:06 +00:00
if ( ! success ) {
m_pairStatus = Device : : NotPaired ;
return ;
}
}
void Device : : setAsPaired ( )
{
2015-06-22 03:39:04 +01:00
bool alreadyPaired = ( m_pairStatus = = Device : : Paired ) ;
2013-11-06 20:34:06 +00:00
m_pairStatus = Device : : Paired ;
2015-03-02 04:16:07 +00:00
//Save device info in the config
2015-07-27 16:28:58 +01:00
KdeConnectConfig : : instance ( ) - > addTrustedDevice ( id ( ) , name ( ) , type2str ( m_deviceType ) ) ;
2013-11-06 20:34:06 +00:00
reloadPlugins ( ) ; //Will actually load the plugins
2015-06-22 03:39:04 +01:00
if ( ! alreadyPaired ) {
Q_EMIT pairingChanged ( true ) ;
}
2013-11-06 20:34:06 +00:00
}
2015-09-12 19:53:05 +01:00
DeviceLink : : ConnectionStarted Device : : connectionSource ( ) const
{
DeviceLink : : ConnectionStarted ret = DeviceLink : : Remotely ;
Q_FOREACH ( DeviceLink * link , m_deviceLinks ) {
if ( link - > connectionSource ( ) = = DeviceLink : : ConnectionStarted : : Locally ) {
ret = DeviceLink : : ConnectionStarted : : Locally ;
break ;
}
}
return ret ;
}
2013-07-23 15:11:54 +01:00
QStringList Device : : availableLinks ( ) const
{
QStringList sl ;
Q_FOREACH ( DeviceLink * dl , m_deviceLinks ) {
2013-07-24 17:42:33 +01:00
sl . append ( dl - > provider ( ) - > name ( ) ) ;
2013-07-23 15:11:54 +01:00
}
return sl ;
}
2015-09-12 08:45:59 +01:00
Device : : DeviceType Device : : str2type ( const QString & deviceType ) {
2013-11-06 20:31:37 +00:00
if ( deviceType = = " desktop " ) return Desktop ;
if ( deviceType = = " laptop " ) return Laptop ;
2015-05-18 07:28:58 +01:00
if ( deviceType = = " smartphone " | | deviceType = = " phone " ) return Phone ;
2013-11-06 20:31:37 +00:00
if ( deviceType = = " tablet " ) return Tablet ;
return Unknown ;
}
2013-11-06 20:34:06 +00:00
QString Device : : type2str ( Device : : DeviceType deviceType ) {
2013-11-06 20:31:37 +00:00
if ( deviceType = = Desktop ) return " desktop " ;
if ( deviceType = = Laptop ) return " laptop " ;
2015-05-18 07:28:58 +01:00
if ( deviceType = = Phone ) return " smartphone " ;
2013-11-06 20:31:37 +00:00
if ( deviceType = = Tablet ) return " tablet " ;
return " unknown " ;
2014-06-14 15:34:00 +01:00
}
2014-06-14 18:09:31 +01:00
2015-05-18 07:28:58 +01:00
QString Device : : statusIconName ( ) const
{
return iconForStatus ( isReachable ( ) , isPaired ( ) ) ;
}
2014-06-14 18:09:31 +01:00
QString Device : : iconName ( ) const
{
2015-05-18 07:28:58 +01:00
return iconForStatus ( true , false ) ;
}
QString Device : : iconForStatus ( bool reachable , bool paired ) const
{
Device : : DeviceType deviceType = m_deviceType ;
if ( deviceType = = Device : : Unknown ) {
deviceType = Device : : Phone ; //Assume phone if we don't know the type
} else if ( deviceType = = Device : : Desktop ) {
deviceType = Device : : Device : : Laptop ; // We don't have desktop icon yet
2014-06-14 18:09:31 +01:00
}
2015-05-18 07:28:58 +01:00
QString status = ( reachable ? ( paired ? QStringLiteral ( " connected " ) : QStringLiteral ( " disconnected " ) ) : QStringLiteral ( " trusted " ) ) ;
QString type = type2str ( deviceType ) ;
2015-08-21 17:38:54 +01:00
return type + ' - ' + status ;
2014-06-14 18:09:31 +01:00
}
2015-03-14 03:28:54 +00:00
void Device : : setName ( const QString & name )
{
if ( m_deviceName ! = name ) {
m_deviceName = name ;
Q_EMIT nameChanged ( name ) ;
}
}
2015-09-07 13:54:33 +01:00
2015-09-12 21:03:39 +01:00
Device : : PairStatus Device : : pairStatus ( ) const
{
return m_pairStatus ;
}
2015-09-07 13:54:33 +01:00
KdeConnectPlugin * Device : : plugin ( const QString & pluginName ) const
{
return m_plugins [ pluginName ] ;
}
2015-09-08 16:28:47 +01:00
void Device : : setPluginEnabled ( const QString & pluginName , bool enabled )
{
KConfigGroup pluginStates = KSharedConfig : : openConfig ( pluginsConfigFile ( ) ) - > group ( " Plugins " ) ;
const QString enabledKey = pluginName + QStringLiteral ( " Enabled " ) ;
pluginStates . writeEntry ( enabledKey , enabled ) ;
reloadPlugins ( ) ;
}
bool Device : : isPluginEnabled ( const QString & pluginName ) const
{
const QString enabledKey = pluginName + QStringLiteral ( " Enabled " ) ;
KConfigGroup pluginStates = KSharedConfig : : openConfig ( pluginsConfigFile ( ) ) - > group ( " Plugins " ) ;
return ( pluginStates . hasKey ( enabledKey ) ? pluginStates . readEntry ( enabledKey , false )
: PluginLoader : : instance ( ) - > getPluginInfo ( pluginName ) . isEnabledByDefault ( ) ) ;
}