Falkon Develop
Cross-platform Qt-based web browser
gm_manager.cpp
Go to the documentation of this file.
1/* ============================================================
2* GreaseMonkey plugin for Falkon
3* Copyright (C) 2012-2018 David Rosca <nowrep@gmail.com>
4*
5* This program is free software: you can redistribute it and/or modify
6* it under the terms of the GNU General Public License as published by
7* the Free Software Foundation, either version 3 of the License, or
8* (at your option) any later version.
9*
10* This program is distributed in the hope that it will be useful,
11* but WITHOUT ANY WARRANTY; without even the implied warranty of
12* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13* GNU General Public License for more details.
14*
15* You should have received a copy of the GNU General Public License
16* along with this program. If not, see <http://www.gnu.org/licenses/>.
17* ============================================================ */
18#include "gm_manager.h"
19#include "gm_script.h"
20#include "gm_downloader.h"
21#include "gm_jsobject.h"
22#include "gm_icon.h"
23#include "gm_addscriptdialog.h"
25
26#include "browserwindow.h"
27#include "webpage.h"
28#include "qztools.h"
29#include "mainapplication.h"
30#include "networkmanager.h"
31#include "navigationbar.h"
34#include "statusbar.h"
35
36#include <QTimer>
37#include <QDir>
38#include <QSettings>
39#include <QWebEngineProfile>
40#include <QWebEngineScriptCollection>
41
42GM_Manager::GM_Manager(const QString &sPath, QObject* parent)
43 : QObject(parent)
44 , m_settingsPath(sPath)
45 , m_jsObject(new GM_JSObject(this))
46{
47 load();
48}
49
51{
53}
54
55void GM_Manager::showSettings(QWidget* parent)
56{
57 if (!m_settings) {
58 m_settings = new GM_Settings(this, parent);
59 }
60
61 m_settings.data()->show();
62 m_settings.data()->raise();
63}
64
65void GM_Manager::downloadScript(const QUrl &url)
66{
67 auto *downloader = new GM_Downloader(url, this);
68 connect(downloader, &GM_Downloader::finished, this, [=](const QString &fileName) {
69 bool deleteScript = true;
70 auto *script = new GM_Script(this, fileName);
71 if (script->isValid()) {
72 if (!containsScript(script->fullName())) {
73 GM_AddScriptDialog dialog(this, script);
74 deleteScript = dialog.exec() != QDialog::Accepted;
75 }
76 else {
77 showNotification(tr("'%1' is already installed").arg(script->name()));
78 }
79 }
80
81 if (deleteScript) {
82 delete script;
83 QFile(fileName).remove();
84 }
85 });
86}
87
89{
90 return m_settingsPath;
91}
92
94{
95 return m_settingsPath + QL1S("/greasemonkey");
96}
97
98QString GM_Manager::requireScripts(const QStringList &urlList) const
99{
100 QDir requiresDir(m_settingsPath + QL1S("/greasemonkey/requires"));
101 if (!requiresDir.exists() || urlList.isEmpty()) {
102 return {};
103 }
104
105 QSettings settings(m_settingsPath + QL1S("/greasemonkey/requires/requires.ini"), QSettings::IniFormat);
106 settings.beginGroup(QSL("Files"));
107
108 QString script;
109
110 for (const QString &url : urlList) {
111 if (settings.contains(url)) {
112 QString fileName = settings.value(url).toString();
113 if (!QFileInfo(fileName).isAbsolute()) {
114 fileName = m_settingsPath + QL1S("/greasemonkey/requires/") + fileName;
115 }
116 const QString data = QzTools::readAllFileContents(fileName).trimmed();
117 if (!data.isEmpty()) {
118 script.append(data + QL1C('\n'));
119 }
120 }
121 }
122
123 return script;
124}
125
127{
128 return m_bootstrapScript;
129}
130
132{
133 return m_valuesScript;
134}
135
137{
138 // Save settings
139 QSettings settings(m_settingsPath + QSL("/extensions.ini"), QSettings::IniFormat);
140 settings.beginGroup(QSL("GreaseMonkey"));
141 settings.setValue(QSL("disabledScripts"), m_disabledScripts);
142 settings.endGroup();
143
144 delete m_settings.data();
145
146 // Remove icons from all windows
147 QHashIterator<BrowserWindow*, GM_Icon*> it(m_windows);
148 while (it.hasNext()) {
149 it.next();
150 mainWindowDeleted(it.key());
151 }
152}
153
154QList<GM_Script*> GM_Manager::allScripts() const
155{
156 return m_scripts;
157}
158
159bool GM_Manager::containsScript(const QString &fullName) const
160{
161 for (GM_Script* script : std::as_const(m_scripts)) {
162 if (fullName == script->fullName()) {
163 return true;
164 }
165 }
166
167 return false;
168}
169
171{
172 script->setEnabled(true);
173 m_disabledScripts.removeOne(script->fullName());
174
175 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
176 collection->insert(script->webScript());
177}
178
180{
181 script->setEnabled(false);
182 m_disabledScripts.append(script->fullName());
183
184 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
185 for (const auto &script : collection->find(script->fullName())) {
186 collection->remove(script);
187 }
188}
189
191{
192 if (!script || !script->isValid()) {
193 return false;
194 }
195
196 m_scripts.append(script);
197 connect(script, &GM_Script::scriptChanged, this, &GM_Manager::scriptChanged);
198
199 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
200 collection->insert(script->webScript());
201
202 Q_EMIT scriptsChanged();
203 return true;
204}
205
206bool GM_Manager::removeScript(GM_Script* script, bool removeFile)
207{
208 if (!script) {
209 return false;
210 }
211
212 m_scripts.removeOne(script);
213
214 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
215 for (const auto &script : collection->find(script->fullName())) {
216 collection->remove(script);
217 }
218
219 m_disabledScripts.removeOne(script->fullName());
220
221 if (removeFile) {
222 QFile::remove(script->fileName());
223 delete script;
224 }
225
226 Q_EMIT scriptsChanged();
227 return true;
228}
229
230void GM_Manager::showNotification(const QString &message, const QString &title)
231{
232 QIcon icon(QSL(":gm/data/icon.svg"));
233
234 mApp->desktopNotifications()->showNotification(icon.pixmap(48), title.isEmpty() ? tr("GreaseMonkey") : title, message);
235}
236
237void GM_Manager::load()
238{
239 QDir gmDir(m_settingsPath + QL1S("/greasemonkey"));
240 if (!gmDir.exists()) {
241 gmDir.mkdir(m_settingsPath + QL1S("/greasemonkey"));
242 }
243
244 if (!gmDir.exists(QSL("requires"))) {
245 gmDir.mkdir(QSL("requires"));
246 }
247
248 m_bootstrapScript = QzTools::readAllFileContents(QSL(":gm/data/bootstrap.min.js"));
249 m_valuesScript = QzTools::readAllFileContents(QSL(":gm/data/values.min.js"));
250
251 QSettings settings(m_settingsPath + QL1S("/extensions.ini"), QSettings::IniFormat);
252 settings.beginGroup(QSL("GreaseMonkey"));
253 m_disabledScripts = settings.value(QSL("disabledScripts"), QStringList()).toStringList();
254
255 const auto fileNames = gmDir.entryList(QStringList(QSL("*.js")), QDir::Files);
256 for (const QString &fileName : fileNames) {
257 const QString absolutePath = gmDir.absoluteFilePath(fileName);
258 auto* script = new GM_Script(this, absolutePath);
259
260 if (!script->isValid()) {
261 delete script;
262 continue;
263 }
264
265 m_scripts.append(script);
266
267 if (m_disabledScripts.contains(script->fullName())) {
268 script->setEnabled(false);
269 }
270 else {
271 mApp->webProfile()->scripts()->insert(script->webScript());
272 }
273 }
274
275 m_jsObject->setSettingsFile(m_settingsPath + QSL("/greasemonkey/values.ini"));
276 ExternalJsObject::registerExtraObject(QSL("greasemonkey"), m_jsObject);
277}
278
279void GM_Manager::scriptChanged()
280{
281 auto *script = qobject_cast<GM_Script*>(sender());
282 if (!script)
283 return;
284
285 QWebEngineScriptCollection *collection = mApp->webProfile()->scripts();
286 for (const auto &script : collection->find(script->fullName())) {
287 collection->remove(script);
288 }
289 collection->insert(script->webScript());
290}
291
292bool GM_Manager::canRunOnScheme(const QString &scheme)
293{
294 return (scheme == QLatin1String("http") || scheme == QLatin1String("https")
295 || scheme == QLatin1String("data") || scheme == QLatin1String("ftp"));
296}
297
299{
300 auto *icon = new GM_Icon(this);
301 window->statusBar()->addButton(icon);
302 window->navigationBar()->addToolButton(icon);
303 m_windows[window] = icon;
304}
305
307{
308 GM_Icon *icon = m_windows.take(window);
309 window->statusBar()->removeButton(icon);
310 window->navigationBar()->removeToolButton(icon);
311 delete icon;
312}
NavigationBar * navigationBar() const
StatusBar * statusBar() const
static void unregisterExtraObject(QObject *object)
static void registerExtraObject(const QString &id, QObject *object)
void finished(const QString &fileName)
void setSettingsFile(const QString &name)
Definition: gm_jsobject.cpp:31
GM_Manager(const QString &sPath, QObject *parent=nullptr)
Definition: gm_manager.cpp:42
QString requireScripts(const QStringList &urlList) const
Definition: gm_manager.cpp:98
void scriptsChanged()
void downloadScript(const QUrl &url)
Definition: gm_manager.cpp:65
void mainWindowDeleted(BrowserWindow *window)
Definition: gm_manager.cpp:306
bool containsScript(const QString &fullName) const
Definition: gm_manager.cpp:159
bool removeScript(GM_Script *script, bool removeFile=true)
Definition: gm_manager.cpp:206
void enableScript(GM_Script *script)
Definition: gm_manager.cpp:170
void showSettings(QWidget *parent)
Definition: gm_manager.cpp:55
static bool canRunOnScheme(const QString &scheme)
Definition: gm_manager.cpp:292
QString settingsPath() const
Definition: gm_manager.cpp:88
void showNotification(const QString &message, const QString &title=QString())
Definition: gm_manager.cpp:230
QString scriptsDirectory() const
Definition: gm_manager.cpp:93
bool addScript(GM_Script *script)
Definition: gm_manager.cpp:190
QList< GM_Script * > allScripts() const
Definition: gm_manager.cpp:154
QString bootstrapScript() const
Definition: gm_manager.cpp:126
void disableScript(GM_Script *script)
Definition: gm_manager.cpp:179
void mainWindowCreated(BrowserWindow *window)
Definition: gm_manager.cpp:298
void unloadPlugin()
Definition: gm_manager.cpp:136
QString valuesScript() const
Definition: gm_manager.cpp:131
QWebEngineScript webScript() const
Definition: gm_script.cpp:142
bool isValid() const
Definition: gm_script.cpp:52
void scriptChanged()
void setEnabled(bool enable)
Definition: gm_script.cpp:117
QString fullName() const
Definition: gm_script.cpp:67
QString fileName() const
Definition: gm_script.cpp:137
void removeToolButton(AbstractButtonInterface *button)
void addToolButton(AbstractButtonInterface *button)
static QString readAllFileContents(const QString &filename)
Definition: qztools.cpp:98
void addButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:217
void removeButton(AbstractButtonInterface *button)
Definition: statusbar.cpp:235
#define mApp
#define QL1S(x)
Definition: qzcommon.h:44
#define QL1C(x)
Definition: qzcommon.h:48
#define QSL(x)
Definition: qzcommon.h:40