File indexing completed on 2024-05-05 17:41:33
0001 /* 0002 SPDX-FileCopyrightText: 2018 David Edmundson <davidedmundson@kde.org> 0003 SPDX-FileCopyrightText: 2018 Eike Hein <hein@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "browserintegrationreminder.h" 0009 0010 #include <QAction> 0011 #include <QDBusConnection> 0012 #include <QDBusConnectionInterface> 0013 #include <QDBusMessage> 0014 #include <QDBusServiceWatcher> 0015 #include <QDebug> 0016 #include <QDesktopServices> 0017 #include <QMenu> 0018 #include <QTimer> 0019 0020 #include <KActivities/ResourceInstance> 0021 #include <KConfig> 0022 #include <KConfigGroup> 0023 #include <KIO/ApplicationLauncherJob> 0024 #include <KLocalizedString> 0025 #include <KNotificationJobUiDelegate> 0026 #include <KService> 0027 #include <KSharedConfig> 0028 #include <KStatusNotifierItem> 0029 #include <kpluginfactory.h> 0030 0031 K_PLUGIN_FACTORY_WITH_JSON(BrowserIntegrationReminderFactory, "browserintegrationreminder.json", registerPlugin<BrowserIntegrationReminder>();) 0032 0033 static const QString s_dbusServiceName = QStringLiteral("org.kde.plasma.browser_integration"); 0034 0035 #define MAX_SHOW_COUNT 3 0036 0037 BrowserIntegrationReminder::BrowserIntegrationReminder(QObject *parent, const QList<QVariant> &) 0038 : KDEDModule(parent) 0039 { 0040 m_debug = qEnvironmentVariableIsSet("PLASMA_BROWSE_REMIND_FORCE"); 0041 auto config = KSharedConfig::openConfig()->group("PlasmaBrowserIntegration"); 0042 m_shownCount = config.readEntry("shownCount", 0); 0043 0044 if (m_shownCount > MAX_SHOW_COUNT && !m_debug) { 0045 disableAutoload(); // safer than it looks it won't be processed till we hit the event loop 0046 return; 0047 } 0048 0049 QUrl firefox(QStringLiteral("https://addons.mozilla.org/en-US/firefox/addon/plasma-integration/")); 0050 m_browsers[QStringLiteral("firefox.desktop")] = firefox; 0051 m_browsers[QStringLiteral("nightly.desktop")] = firefox; 0052 0053 QUrl chrome(QStringLiteral("https://chrome.google.com/webstore/detail/plasma-integration/cimiefiiaegbelhefglklhhakcgmhkai")); 0054 m_browsers[QStringLiteral("google-chrome.desktop")] = chrome; 0055 m_browsers[QStringLiteral("google-chrome-beta.desktop")] = chrome; 0056 m_browsers[QStringLiteral("google-chrome-unstable.desktop")] = chrome; 0057 m_browsers[QStringLiteral("chromium-browser.desktop")] = chrome; 0058 m_browsers[QStringLiteral("vivaldi-stable.desktop")] = chrome; 0059 m_browsers[QStringLiteral("brave-browser.desktop")] = chrome; 0060 0061 QUrl edge(QStringLiteral("https://microsoftedge.microsoft.com/addons/detail/plasma-integration/dnnckbejblnejeabhcmhklcaljjpdjeh")); 0062 m_browsers[QStringLiteral("microsoft-edge.desktop")] = edge; 0063 m_browsers[QStringLiteral("microsoft-edge-beta.desktop")] = edge; 0064 m_browsers[QStringLiteral("microsoft-edge-dev.desktop")] = edge; 0065 0066 setModuleName(QStringLiteral("BrowserIntegrationReminder")); 0067 QDBusConnection dbus = QDBusConnection::sessionBus(); 0068 dbus.connect(QStringLiteral("org.kde.ActivityManager"), 0069 QStringLiteral("/ActivityManager/Resources/Scoring"), 0070 QStringLiteral("org.kde.ActivityManager.ResourcesScoring"), 0071 QStringLiteral("ResourceScoreUpdated"), 0072 this, 0073 SLOT(onResourceScoresChanged(QString, QString, QString, double, unsigned int, unsigned int))); 0074 } 0075 0076 BrowserIntegrationReminder::~BrowserIntegrationReminder() 0077 { 0078 } 0079 0080 void BrowserIntegrationReminder::onResourceScoresChanged(const QString &activity, 0081 const QString &client, 0082 const QString &resource, 0083 double score, 0084 unsigned int lastUpdate, 0085 unsigned int firstUpdate) 0086 { 0087 Q_UNUSED(activity); 0088 Q_UNUSED(score); 0089 Q_UNUSED(lastUpdate); 0090 Q_UNUSED(firstUpdate); 0091 Q_UNUSED(client) 0092 0093 if (!resource.startsWith(QStringLiteral("applications:"))) { 0094 return; 0095 } 0096 const QString desktopFile = resource.mid(strlen("applications:")); 0097 if (!m_browsers.contains(desktopFile)) { 0098 return; 0099 } 0100 // wait a few seconds and then query if the extension is active 0101 QTimer::singleShot(10 * 1000, this, [this, desktopFile]() { 0102 onBrowserStarted(desktopFile); 0103 }); 0104 } 0105 0106 void BrowserIntegrationReminder::onBrowserStarted(const QString &browser) 0107 { 0108 QDBusConnection bus = QDBusConnection::sessionBus(); 0109 if (m_sni) { 0110 return; 0111 } 0112 0113 if (!KService::serviceByStorageId(browser)) { 0114 return; 0115 } 0116 0117 if (!m_watcher) { 0118 m_watcher = new QDBusServiceWatcher(s_dbusServiceName, bus, QDBusServiceWatcher::WatchForRegistration, this); 0119 connect(m_watcher, &QDBusServiceWatcher::serviceRegistered, this, [this](const QString &service) { 0120 Q_UNUSED(service); 0121 if (m_sni) { 0122 m_sni->deleteLater(); 0123 disableAutoload(); 0124 } 0125 }); 0126 } 0127 0128 if (!m_debug && bus.interface()->isServiceRegistered(s_dbusServiceName)) { 0129 // the user has the extension installed, we don't need to keep checking 0130 // env var exists for easier testing 0131 disableAutoload(); 0132 return; 0133 } 0134 0135 m_sni = new KStatusNotifierItem(this); 0136 m_shownCount++; 0137 auto config = KSharedConfig::openConfig()->group("PlasmaBrowserIntegration"); 0138 config.writeEntry("shownCount", m_shownCount); 0139 0140 m_sni->setTitle(i18n("Get Plasma Browser Integration")); 0141 m_sni->setIconByName(QStringLiteral("plasma-browser-integration")); 0142 m_sni->setStandardActionsEnabled(false); 0143 m_sni->setStatus(KStatusNotifierItem::Active); 0144 0145 connect(m_sni, &KStatusNotifierItem::activateRequested, this, [this, browser]() { 0146 const KService::Ptr service = KService::serviceByStorageId(browser); 0147 0148 if (!service) { 0149 unload(); 0150 return; 0151 } 0152 0153 KIO::ApplicationLauncherJob *job = new KIO::ApplicationLauncherJob(service); 0154 job->setUrls({m_browsers[browser]}); 0155 job->setUiDelegate(new KNotificationJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled)); 0156 job->start(); 0157 0158 KActivities::ResourceInstance::notifyAccessed(QUrl(QStringLiteral("applications:") + browser), 0159 QStringLiteral("org.kde.plasma.browserintegrationreminder")); 0160 // remove for this session. 0161 // If the user installed it successfully we won't show anything next session 0162 // If they didn't they'll get the link next login 0163 unload(); 0164 }); 0165 0166 auto *menu = new QMenu; 0167 auto *action = new QAction(QIcon::fromTheme(QStringLiteral("view-hidden")), i18n("Do not show again")); 0168 menu->addAction(action); 0169 connect(action, &QAction::triggered, this, [this]() { 0170 auto config = KSharedConfig::openConfig()->group("PlasmaBrowserIntegration"); 0171 config.writeEntry("shownCount", 100); 0172 disableAutoload(); 0173 }); 0174 0175 m_sni->setContextMenu(menu); 0176 } 0177 0178 void BrowserIntegrationReminder::unload() 0179 { 0180 QDBusConnection dbus = QDBusConnection::sessionBus(); 0181 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded5"), 0182 QStringLiteral("/kded"), 0183 QStringLiteral("org.kde.kded5"), 0184 QStringLiteral("unloadModule")); 0185 msg.setArguments({QVariant(QStringLiteral("browserintegrationreminder"))}); 0186 dbus.call(msg, QDBus::NoBlock); 0187 } 0188 0189 void BrowserIntegrationReminder::disableAutoload() 0190 { 0191 QDBusConnection dbus = QDBusConnection::sessionBus(); 0192 QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kded5"), 0193 QStringLiteral("/kded"), 0194 QStringLiteral("org.kde.kded5"), 0195 QStringLiteral("setModuleAutoloading")); 0196 msg.setArguments({QVariant(QStringLiteral("browserintegrationreminder")), QVariant(false)}); 0197 dbus.call(msg, QDBus::NoBlock); 0198 unload(); 0199 } 0200 0201 #include "browserintegrationreminder.moc"