File indexing completed on 2024-05-19 04:59:16
0001 /* ============================================================ 0002 * GreaseMonkey plugin for Falkon 0003 * Copyright (C) 2012-2018 David Rosca <nowrep@gmail.com> 0004 * 0005 * This program is free software: you can redistribute it and/or modify 0006 * it under the terms of the GNU General Public License as published by 0007 * the Free Software Foundation, either version 3 of the License, or 0008 * (at your option) any later version. 0009 * 0010 * This program is distributed in the hope that it will be useful, 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0013 * GNU General Public License for more details. 0014 * 0015 * You should have received a copy of the GNU General Public License 0016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 0017 * ============================================================ */ 0018 #include "gm_manager.h" 0019 #include "gm_script.h" 0020 #include "gm_downloader.h" 0021 #include "gm_jsobject.h" 0022 #include "gm_icon.h" 0023 #include "gm_addscriptdialog.h" 0024 #include "settings/gm_settings.h" 0025 0026 #include "browserwindow.h" 0027 #include "webpage.h" 0028 #include "qztools.h" 0029 #include "mainapplication.h" 0030 #include "networkmanager.h" 0031 #include "navigationbar.h" 0032 #include "desktopnotificationsfactory.h" 0033 #include "javascript/externaljsobject.h" 0034 #include "statusbar.h" 0035 0036 #include <QTimer> 0037 #include <QDir> 0038 #include <QSettings> 0039 #include <QWebEngineProfile> 0040 #include <QWebEngineScriptCollection> 0041 0042 GM_Manager::GM_Manager(const QString &sPath, QObject* parent) 0043 : QObject(parent) 0044 , m_settingsPath(sPath) 0045 , m_jsObject(new GM_JSObject(this)) 0046 { 0047 load(); 0048 } 0049 0050 GM_Manager::~GM_Manager() 0051 { 0052 ExternalJsObject::unregisterExtraObject(m_jsObject); 0053 } 0054 0055 void GM_Manager::showSettings(QWidget* parent) 0056 { 0057 if (!m_settings) { 0058 m_settings = new GM_Settings(this, parent); 0059 } 0060 0061 m_settings.data()->show(); 0062 m_settings.data()->raise(); 0063 } 0064 0065 void GM_Manager::downloadScript(const QUrl &url) 0066 { 0067 auto *downloader = new GM_Downloader(url, this); 0068 connect(downloader, &GM_Downloader::finished, this, [=](const QString &fileName) { 0069 bool deleteScript = true; 0070 auto *script = new GM_Script(this, fileName); 0071 if (script->isValid()) { 0072 if (!containsScript(script->fullName())) { 0073 GM_AddScriptDialog dialog(this, script); 0074 deleteScript = dialog.exec() != QDialog::Accepted; 0075 } 0076 else { 0077 showNotification(tr("'%1' is already installed").arg(script->name())); 0078 } 0079 } 0080 0081 if (deleteScript) { 0082 delete script; 0083 QFile(fileName).remove(); 0084 } 0085 }); 0086 } 0087 0088 QString GM_Manager::settingsPath() const 0089 { 0090 return m_settingsPath; 0091 } 0092 0093 QString GM_Manager::scriptsDirectory() const 0094 { 0095 return m_settingsPath + QL1S("/greasemonkey"); 0096 } 0097 0098 QString GM_Manager::requireScripts(const QStringList &urlList) const 0099 { 0100 QDir requiresDir(m_settingsPath + QL1S("/greasemonkey/requires")); 0101 if (!requiresDir.exists() || urlList.isEmpty()) { 0102 return {}; 0103 } 0104 0105 QSettings settings(m_settingsPath + QL1S("/greasemonkey/requires/requires.ini"), QSettings::IniFormat); 0106 settings.beginGroup(QSL("Files")); 0107 0108 QString script; 0109 0110 for (const QString &url : urlList) { 0111 if (settings.contains(url)) { 0112 QString fileName = settings.value(url).toString(); 0113 if (!QFileInfo(fileName).isAbsolute()) { 0114 fileName = m_settingsPath + QL1S("/greasemonkey/requires/") + fileName; 0115 } 0116 const QString data = QzTools::readAllFileContents(fileName).trimmed(); 0117 if (!data.isEmpty()) { 0118 script.append(data + QL1C('\n')); 0119 } 0120 } 0121 } 0122 0123 return script; 0124 } 0125 0126 QString GM_Manager::bootstrapScript() const 0127 { 0128 return m_bootstrapScript; 0129 } 0130 0131 QString GM_Manager::valuesScript() const 0132 { 0133 return m_valuesScript; 0134 } 0135 0136 void GM_Manager::unloadPlugin() 0137 { 0138 // Save settings 0139 QSettings settings(m_settingsPath + QSL("/extensions.ini"), QSettings::IniFormat); 0140 settings.beginGroup(QSL("GreaseMonkey")); 0141 settings.setValue(QSL("disabledScripts"), m_disabledScripts); 0142 settings.endGroup(); 0143 0144 delete m_settings.data(); 0145 0146 // Remove icons from all windows 0147 QHashIterator<BrowserWindow*, GM_Icon*> it(m_windows); 0148 while (it.hasNext()) { 0149 it.next(); 0150 mainWindowDeleted(it.key()); 0151 } 0152 } 0153 0154 QList<GM_Script*> GM_Manager::allScripts() const 0155 { 0156 return m_scripts; 0157 } 0158 0159 bool GM_Manager::containsScript(const QString &fullName) const 0160 { 0161 for (GM_Script* script : std::as_const(m_scripts)) { 0162 if (fullName == script->fullName()) { 0163 return true; 0164 } 0165 } 0166 0167 return false; 0168 } 0169 0170 void GM_Manager::enableScript(GM_Script* script) 0171 { 0172 script->setEnabled(true); 0173 m_disabledScripts.removeOne(script->fullName()); 0174 0175 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts(); 0176 collection->insert(script->webScript()); 0177 } 0178 0179 void GM_Manager::disableScript(GM_Script* script) 0180 { 0181 script->setEnabled(false); 0182 m_disabledScripts.append(script->fullName()); 0183 0184 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts(); 0185 for (const auto &script : collection->find(script->fullName())) { 0186 collection->remove(script); 0187 } 0188 } 0189 0190 bool GM_Manager::addScript(GM_Script* script) 0191 { 0192 if (!script || !script->isValid()) { 0193 return false; 0194 } 0195 0196 m_scripts.append(script); 0197 connect(script, &GM_Script::scriptChanged, this, &GM_Manager::scriptChanged); 0198 0199 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts(); 0200 collection->insert(script->webScript()); 0201 0202 Q_EMIT scriptsChanged(); 0203 return true; 0204 } 0205 0206 bool GM_Manager::removeScript(GM_Script* script, bool removeFile) 0207 { 0208 if (!script) { 0209 return false; 0210 } 0211 0212 m_scripts.removeOne(script); 0213 0214 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts(); 0215 for (const auto &script : collection->find(script->fullName())) { 0216 collection->remove(script); 0217 } 0218 0219 m_disabledScripts.removeOne(script->fullName()); 0220 0221 if (removeFile) { 0222 QFile::remove(script->fileName()); 0223 delete script; 0224 } 0225 0226 Q_EMIT scriptsChanged(); 0227 return true; 0228 } 0229 0230 void GM_Manager::showNotification(const QString &message, const QString &title) 0231 { 0232 QIcon icon(QSL(":gm/data/icon.svg")); 0233 0234 mApp->desktopNotifications()->showNotification(icon.pixmap(48), title.isEmpty() ? tr("GreaseMonkey") : title, message); 0235 } 0236 0237 void GM_Manager::load() 0238 { 0239 QDir gmDir(m_settingsPath + QL1S("/greasemonkey")); 0240 if (!gmDir.exists()) { 0241 gmDir.mkdir(m_settingsPath + QL1S("/greasemonkey")); 0242 } 0243 0244 if (!gmDir.exists(QSL("requires"))) { 0245 gmDir.mkdir(QSL("requires")); 0246 } 0247 0248 m_bootstrapScript = QzTools::readAllFileContents(QSL(":gm/data/bootstrap.min.js")); 0249 m_valuesScript = QzTools::readAllFileContents(QSL(":gm/data/values.min.js")); 0250 0251 QSettings settings(m_settingsPath + QL1S("/extensions.ini"), QSettings::IniFormat); 0252 settings.beginGroup(QSL("GreaseMonkey")); 0253 m_disabledScripts = settings.value(QSL("disabledScripts"), QStringList()).toStringList(); 0254 0255 const auto fileNames = gmDir.entryList(QStringList(QSL("*.js")), QDir::Files); 0256 for (const QString &fileName : fileNames) { 0257 const QString absolutePath = gmDir.absoluteFilePath(fileName); 0258 auto* script = new GM_Script(this, absolutePath); 0259 0260 if (!script->isValid()) { 0261 delete script; 0262 continue; 0263 } 0264 0265 m_scripts.append(script); 0266 0267 if (m_disabledScripts.contains(script->fullName())) { 0268 script->setEnabled(false); 0269 } 0270 else { 0271 mApp->webProfile()->scripts()->insert(script->webScript()); 0272 } 0273 } 0274 0275 m_jsObject->setSettingsFile(m_settingsPath + QSL("/greasemonkey/values.ini")); 0276 ExternalJsObject::registerExtraObject(QSL("greasemonkey"), m_jsObject); 0277 } 0278 0279 void GM_Manager::scriptChanged() 0280 { 0281 auto *script = qobject_cast<GM_Script*>(sender()); 0282 if (!script) 0283 return; 0284 0285 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts(); 0286 for (const auto &script : collection->find(script->fullName())) { 0287 collection->remove(script); 0288 } 0289 collection->insert(script->webScript()); 0290 } 0291 0292 bool GM_Manager::canRunOnScheme(const QString &scheme) 0293 { 0294 return (scheme == QLatin1String("http") || scheme == QLatin1String("https") 0295 || scheme == QLatin1String("data") || scheme == QLatin1String("ftp")); 0296 } 0297 0298 void GM_Manager::mainWindowCreated(BrowserWindow* window) 0299 { 0300 auto *icon = new GM_Icon(this); 0301 window->statusBar()->addButton(icon); 0302 window->navigationBar()->addToolButton(icon); 0303 m_windows[window] = icon; 0304 } 0305 0306 void GM_Manager::mainWindowDeleted(BrowserWindow* window) 0307 { 0308 GM_Icon *icon = m_windows.take(window); 0309 window->statusBar()->removeButton(icon); 0310 window->navigationBar()->removeToolButton(icon); 0311 delete icon; 0312 }