File indexing completed on 2024-04-14 03:52:57
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 1999 Torben Weis <weis@kde.org> 0004 SPDX-FileCopyrightText: 2003 Waldo Bastian <bastian@kde.org> 0005 SPDX-FileCopyrightText: 2012 David Faure <faure@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-only 0008 */ 0009 0010 #include "kprotocolinfo_p.h" 0011 #include "kprotocolinfofactory_p.h" 0012 0013 #include <KPluginMetaData> 0014 0015 #include <QCoreApplication> 0016 #include <QDirIterator> 0017 #include <QStandardPaths> 0018 0019 #include "kiocoredebug.h" 0020 0021 Q_GLOBAL_STATIC(KProtocolInfoFactory, kProtocolInfoFactoryInstance) 0022 0023 KProtocolInfoFactory *KProtocolInfoFactory::self() 0024 { 0025 return kProtocolInfoFactoryInstance(); 0026 } 0027 0028 KProtocolInfoFactory::KProtocolInfoFactory() 0029 : m_cacheDirty(true) 0030 { 0031 } 0032 0033 KProtocolInfoFactory::~KProtocolInfoFactory() 0034 { 0035 QMutexLocker locker(&m_mutex); 0036 qDeleteAll(m_cache); 0037 m_cache.clear(); 0038 } 0039 0040 QStringList KProtocolInfoFactory::protocols() 0041 { 0042 QMutexLocker locker(&m_mutex); 0043 0044 // fill cache, if not already done and use it 0045 fillCache(); 0046 return m_cache.keys(); 0047 } 0048 0049 QList<KProtocolInfoPrivate *> KProtocolInfoFactory::allProtocols() 0050 { 0051 QMutexLocker locker(&m_mutex); 0052 0053 // fill cache, if not already done and use it 0054 fillCache(); 0055 return m_cache.values(); 0056 } 0057 0058 KProtocolInfoPrivate *KProtocolInfoFactory::findProtocol(const QString &protocol, bool updateCacheIfNotfound) 0059 { 0060 Q_ASSERT(!protocol.isEmpty()); 0061 Q_ASSERT(!protocol.contains(QLatin1Char(':'))); 0062 0063 QMutexLocker locker(&m_mutex); 0064 0065 const bool filled = fillCache(); 0066 0067 KProtocolInfoPrivate *info = m_cache.value(protocol); 0068 if (!info && !filled && updateCacheIfNotfound) { 0069 // Unknown protocol! Maybe it just got installed and our cache is out of date? 0070 qCDebug(KIO_CORE) << "Refilling KProtocolInfoFactory cache in the hope to find" << protocol; 0071 m_cacheDirty = true; 0072 fillCache(); 0073 info = m_cache.value(protocol); 0074 } 0075 return info; 0076 } 0077 0078 bool KProtocolInfoFactory::fillCache() 0079 { 0080 // mutex MUST be locked from the outside! 0081 Q_ASSERT(!m_mutex.tryLock()); 0082 0083 // no work if filled 0084 if (!m_cacheDirty) { 0085 return false; 0086 } 0087 0088 qDeleteAll(m_cache); 0089 m_cache.clear(); 0090 0091 // first: search for meta data protocol info, that might be bundled with applications 0092 // we search in all library paths inside kf5/kio 0093 const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/kio")); 0094 for (const KPluginMetaData &md : plugins) { 0095 // get worker name & protocols it supports, if any 0096 const QString workerPath = md.fileName(); 0097 const QJsonObject protocols(md.rawData().value(QStringLiteral("KDE-KIO-Protocols")).toObject()); 0098 qCDebug(KIO_CORE) << workerPath << "supports protocols" << protocols.keys(); 0099 0100 // add all protocols, does nothing if object invalid 0101 for (auto it = protocols.begin(); it != protocols.end(); ++it) { 0102 // skip empty objects 0103 const QJsonObject protocol(it.value().toObject()); 0104 if (protocol.isEmpty()) { 0105 continue; 0106 } 0107 0108 // add to cache, skip double entries 0109 if (!m_cache.contains(it.key())) { 0110 m_cache.insert(it.key(), new KProtocolInfoPrivate(it.key(), workerPath, protocol)); 0111 } 0112 } 0113 } 0114 0115 // all done, don't do it again 0116 m_cacheDirty = false; 0117 return true; 0118 }