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
m_pairingTimeut . setSingleShot ( true ) ;
m_pairingTimeut . setInterval ( 30 * 1000 ) ; //30 seconds of timeout
connect ( & m_pairingTimeut , SIGNAL ( timeout ( ) ) ,
this , SLOT ( pairingTimeout ( ) ) ) ;
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-08 08:30:55 +01:00
qDeleteAll ( m_deviceLinks ) ;
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 ( ) ;
2015-09-08 16:34:48 +01:00
2015-09-08 19:03:44 +01:00
const bool pluginEnabled = isPluginEnabled ( pluginName ) ;
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 " ) ;
}
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 ;
case Device : : Requested :
Q_EMIT pairingFailed ( i18n ( " Pairing already requested for this device " ) ) ;
return ;
2015-06-15 03:22:13 +01:00
case Device : : RequestedByPeer :
qCDebug ( KDECONNECT_CORE ) < < " Pairing already started by the other end, accepting their request. " ;
acceptPairing ( ) ;
return ;
case Device : : NotPaired :
;
}
if ( ! isReachable ( ) ) {
Q_EMIT pairingFailed ( i18n ( " Device not reachable " ) ) ;
return ;
2013-08-30 18:10:43 +01:00
}
2013-09-03 21:11:13 +01:00
m_pairStatus = Device : : Requested ;
2013-08-30 18:10:43 +01:00
//Send our own public key
2013-11-06 20:34:06 +00:00
bool success = sendOwnPublicKey ( ) ;
2013-08-30 18:10:43 +01:00
if ( ! success ) {
2013-09-03 21:11:13 +01:00
m_pairStatus = Device : : NotPaired ;
2013-08-30 18:10:43 +01:00
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 ;
}
2015-03-13 23:39:13 +00:00
m_pairingTimeut . start ( ) ;
2013-08-30 18:10:43 +01:00
}
void Device : : unpair ( )
{
2013-09-03 18:14:11 +01:00
NetworkPackage np ( PACKAGE_TYPE_PAIR ) ;
np . set ( " pair " , false ) ;
sendPackage ( np ) ;
2013-08-30 18:10:43 +01:00
2015-03-16 02:13:54 +00:00
unpairInternal ( ) ;
}
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-03 21:11:13 +01:00
NetworkPackage np ( PACKAGE_TYPE_PAIR ) ;
np . set ( " pair " , false ) ;
sendPackage ( np ) ;
m_pairStatus = Device : : NotPaired ;
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
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
}
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
}
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 ) {
2014-09-21 22:54:27 +01:00
//qCDebug(KDECONNECT_CORE) << "Pair package";
2013-08-30 18:10:43 +01:00
2013-08-31 12:04:00 +01:00
bool wantsPair = np . get < bool > ( " pair " ) ;
2013-09-01 21:13:03 +01:00
2013-08-31 12:04:00 +01:00
if ( wantsPair = = isPaired ( ) ) {
2015-09-08 09:04:41 +01:00
qCDebug ( KDECONNECT_CORE ) < < m_deviceName < < " already " < < ( wantsPair ? " paired " : " unpaired " ) ;
2013-09-03 21:11:13 +01:00
if ( m_pairStatus = = Device : : Requested ) {
2013-09-01 21:13:03 +01:00
m_pairStatus = Device : : NotPaired ;
2014-04-14 20:57:34 +01:00
m_pairingTimeut . stop ( ) ;
2013-09-01 21:13:03 +01:00
Q_EMIT pairingFailed ( i18n ( " Canceled by other peer " ) ) ;
}
2013-08-30 18:10:43 +01:00
return ;
}
2013-08-31 12:04:00 +01:00
if ( wantsPair ) {
2013-08-30 18:10:43 +01:00
2013-09-03 15:01:28 +01:00
//Retrieve their public key
const QString & key = np . get < QString > ( " publicKey " ) ;
m_publicKey = QCA : : RSAPublicKey : : fromPEM ( key ) ;
if ( m_publicKey . isNull ( ) ) {
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " ERROR decoding key " ;
2013-09-03 21:11:13 +01:00
if ( m_pairStatus = = Device : : Requested ) {
m_pairStatus = Device : : NotPaired ;
2014-04-14 20:57:34 +01:00
m_pairingTimeut . stop ( ) ;
2013-09-03 15:01:28 +01:00
}
Q_EMIT pairingFailed ( i18n ( " Received incorrect key " ) ) ;
return ;
}
2013-09-01 21:13:03 +01:00
2013-09-03 21:11:13 +01:00
if ( m_pairStatus = = Device : : Requested ) { //We started pairing
2013-08-30 18:10:43 +01:00
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Pair answer " ;
2013-11-06 20:34:06 +00:00
setAsPaired ( ) ;
2013-08-30 18:10:43 +01:00
} else {
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Pair request " ;
2013-08-30 18:10:43 +01:00
2015-03-24 11:26:37 +00:00
Daemon : : instance ( ) - > requestPairing ( this ) ;
2013-08-30 18:10:43 +01:00
2013-09-03 21:11:13 +01:00
m_pairStatus = Device : : RequestedByPeer ;
2013-08-30 18:10:43 +01:00
}
} else {
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Unpair request " ;
2013-09-03 15:01:28 +01:00
2014-01-16 14:48:40 +00:00
PairStatus prevPairStatus = m_pairStatus ;
m_pairStatus = Device : : NotPaired ;
if ( prevPairStatus = = Device : : Requested ) {
2014-04-14 20:57:34 +01:00
m_pairingTimeut . stop ( ) ;
2013-08-30 18:10:43 +01:00
Q_EMIT pairingFailed ( i18n ( " Canceled by other peer " ) ) ;
2014-01-16 14:48:40 +00:00
} else if ( prevPairStatus = = Device : : Paired ) {
2015-03-16 02:13:54 +00:00
unpairInternal ( ) ;
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-03-16 02:19:29 +00:00
if ( m_pairStatus ! = Device : : Requested )
2015-03-02 04:16:07 +00:00
unpair ( ) ;
2013-07-03 02:52:44 +01:00
}
2013-08-30 18:10:43 +01:00
}
2013-11-06 20:34:06 +00:00
bool Device : : sendOwnPublicKey ( )
2013-08-30 18:10:43 +01:00
{
NetworkPackage np ( PACKAGE_TYPE_PAIR ) ;
np . set ( " pair " , true ) ;
2015-03-02 04:16:07 +00:00
np . set ( " publicKey " , KdeConnectConfig : : instance ( ) - > publicKey ( ) . toPEM ( ) ) ;
2013-08-30 18:10:43 +01:00
bool success = sendPackage ( np ) ;
2013-11-06 20:34:06 +00:00
return success ;
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 ;
2013-08-30 18:10:43 +01:00
NetworkPackage np ( PACKAGE_TYPE_PAIR ) ;
np . set ( " pair " , false ) ;
sendPackage ( np ) ;
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 ( )
{
if ( m_pairStatus ! = Device : : RequestedByPeer ) return ;
2014-09-21 22:54:27 +01:00
qCDebug ( KDECONNECT_CORE ) < < " Accepted pairing " ;
2013-11-06 20:34:06 +00:00
bool success = sendOwnPublicKey ( ) ;
if ( ! success ) {
m_pairStatus = Device : : NotPaired ;
return ;
}
setAsPaired ( ) ;
}
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 ;
2014-04-14 20:57:34 +01:00
m_pairingTimeut . stop ( ) ; //Just in case it was started
2013-11-06 20:34:06 +00:00
2015-03-02 04:16:07 +00:00
//Save device info in the config
KdeConnectConfig : : instance ( ) - > addTrustedDevice ( id ( ) , name ( ) , type2str ( m_deviceType ) , m_publicKey . toPEM ( ) ) ;
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
}
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
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 ( ) ) ;
}