1
mirror of https://invent.kde.org/network/falkon.git synced 2024-11-11 09:32:12 +01:00

GreaseMonkey: Make sure to download all require scripts when userscript changes

This commit is contained in:
David Rosca 2017-04-19 15:41:21 +02:00
parent 13402b2983
commit 166fe13747
5 changed files with 118 additions and 99 deletions

View File

@ -29,12 +29,16 @@
#include <QSettings>
#include <QNetworkReply>
GM_Downloader::GM_Downloader(const QUrl &url, GM_Manager* manager)
GM_Downloader::GM_Downloader(const QUrl &url, GM_Manager *manager, Mode mode)
: QObject()
, m_manager(manager)
{
m_reply = mApp->networkManager()->get(QNetworkRequest(url));
if (mode == DownloadMainScript) {
connect(m_reply, &QNetworkReply::finished, this, &GM_Downloader::scriptDownloaded);
} else {
connect(m_reply, &QNetworkReply::finished, this, &GM_Downloader::requireDownloaded);
}
}
void GM_Downloader::updateScript(const QString &fileName)
@ -44,72 +48,76 @@ void GM_Downloader::updateScript(const QString &fileName)
void GM_Downloader::scriptDownloaded()
{
if (m_reply != qobject_cast<QNetworkReply*>(sender())) {
emit error();
Q_ASSERT(m_reply == qobject_cast<QNetworkReply*>(sender()));
deleteLater();
return;
}
m_reply->deleteLater();
if (m_reply->error() != QNetworkReply::NoError) {
qWarning() << "GreaseMonkey: Cannot download script" << m_reply->errorString();
emit error();
return;
}
else {
const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8();
if (response.contains(QByteArray("// ==UserScript=="))) {
if (!response.contains(QByteArray("// ==UserScript=="))) {
qWarning() << "GreaseMonkey: Script does not contain UserScript header" << m_reply->request().url();
emit error();
return;
}
if (m_fileName.isEmpty()) {
const QString filePath = QString("%1/%2").arg(m_manager->scriptsDirectory(), QzTools::getFileNameFromUrl(m_reply->url()));
m_fileName = QzTools::ensureUniqueFilename(filePath);
}
QFile file(m_fileName);
if (!file.open(QFile::WriteOnly)) {
qWarning() << "GreaseMonkey: Cannot open file for writing" << m_fileName;
emit error();
deleteLater();
return;
}
file.write(response);
file.close();
QSettings settings(m_manager->settinsPath() + QL1S("/greasemonkey/requires/requires.ini"), QSettings::IniFormat);
settings.beginGroup("Files");
QzRegExp rx("@require(.*)\\n");
rx.setMinimal(true);
rx.indexIn(response);
for (int i = 1; i <= rx.captureCount(); ++i) {
const QString url = rx.cap(i).trimmed();
if (!url.isEmpty() && !settings.contains(url)) {
m_requireUrls.append(QUrl(url));
}
}
}
}
m_reply->deleteLater();
m_reply = 0;
downloadRequires();
emit finished(m_fileName);
}
void GM_Downloader::requireDownloaded()
{
Q_ASSERT(m_reply == qobject_cast<QNetworkReply*>(sender()));
deleteLater();
m_reply->deleteLater();
if (m_reply != qobject_cast<QNetworkReply*>(sender())) {
emit error();
deleteLater();
return;
}
if (m_reply->error() != QNetworkReply::NoError) {
qWarning() << "GreaseMonkey: Cannot download require script" << m_reply->errorString();
emit error();
return;
}
else {
const QByteArray response = QString::fromUtf8(m_reply->readAll()).toUtf8();
if (!response.isEmpty()) {
if (response.isEmpty()) {
qWarning() << "GreaseMonkey: Empty script downloaded" << m_reply->request().url();
emit error();
return;
}
QSettings settings(m_manager->settinsPath() + QL1S("/greasemonkey/requires/requires.ini"), QSettings::IniFormat);
settings.beginGroup("Files");
if (m_fileName.isEmpty()) {
m_fileName = settings.value(m_reply->request().url().toString()).toString();
if (m_fileName.isEmpty()) {
QString name = QFileInfo(m_reply->request().url().path()).fileName();
if (name.isEmpty()) {
name = QSL("require.js");
@ -117,40 +125,25 @@ void GM_Downloader::requireDownloaded()
name.append(QSL(".js"));
}
const QString filePath = m_manager->settinsPath() + QL1S("/greasemonkey/requires/") + name;
const QString fileName = QzTools::ensureUniqueFilename(filePath, "%1");
m_fileName = QzTools::ensureUniqueFilename(filePath, "%1");
}
if (!QFileInfo(m_fileName).isAbsolute()) {
m_fileName.prepend(m_manager->settinsPath() + QL1S("/greasemonkey/requires/"));
}
}
QFile file(fileName);
QFile file(m_fileName);
if (!file.open(QFile::WriteOnly)) {
qWarning() << "GreaseMonkey: Cannot open file for writing" << fileName;
qWarning() << "GreaseMonkey: Cannot open file for writing" << m_fileName;
emit error();
deleteLater();
return;
}
file.write(response);
file.close();
QSettings settings(m_manager->settinsPath() + QL1S("/greasemonkey/requires/requires.ini"), QSettings::IniFormat);
settings.beginGroup("Files");
settings.setValue(m_reply->request().url().toString(), QFileInfo(fileName).fileName());
}
}
settings.setValue(m_reply->request().url().toString(), QFileInfo(m_fileName).fileName());
m_reply->deleteLater();
m_reply = 0;
downloadRequires();
}
void GM_Downloader::downloadRequires()
{
if (!m_requireUrls.isEmpty()) {
m_reply = mApp->networkManager()->get(QNetworkRequest(m_requireUrls.takeFirst()));
connect(m_reply, &QNetworkReply::finished, this, &GM_Downloader::requireDownloaded);
}
else {
emit finished(m_fileName);
deleteLater();
}
}

View File

@ -1,6 +1,6 @@
/* ============================================================
* GreaseMonkey plugin for QupZilla
* Copyright (C) 2012-2016 David Rosca <nowrep@gmail.com>
* Copyright (C) 2012-2017 David Rosca <nowrep@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
@ -30,7 +30,12 @@ class GM_Downloader : public QObject
{
Q_OBJECT
public:
explicit GM_Downloader(const QUrl &url, GM_Manager* manager);
enum Mode {
DownloadMainScript,
DownloadRequireScript
};
explicit GM_Downloader(const QUrl &url, GM_Manager *manager, Mode mode = DownloadMainScript);
void updateScript(const QString& fileName);
@ -47,10 +52,7 @@ private:
GM_Manager* m_manager;
QNetworkReply *m_reply;
QString m_fileName;
QList<QUrl> m_requireUrls;
};
#endif // GM_DOWNLOADER_H

View File

@ -86,7 +86,10 @@ QString GM_Manager::requireScripts(const QStringList &urlList) const
if (!QFileInfo(fileName).isAbsolute()) {
fileName = m_settingsPath + QL1S("/greasemonkey/requires/") + fileName;
}
script.append(QzTools::readAllFileContents(fileName).trimmed() + '\n');
const QString data = QzTools::readAllFileContents(fileName).trimmed();
if (!data.isEmpty()) {
script.append(data + QL1C('\n'));
}
}
}

View File

@ -115,9 +115,9 @@ QStringList GM_Script::exclude() const
return m_exclude;
}
QString GM_Script::script() const
QStringList GM_Script::require() const
{
return m_script;
return m_require;
}
QString GM_Script::fileName() const
@ -174,17 +174,13 @@ void GM_Script::updateScript()
m_updating = false;
emit updatingChanged(m_updating);
});
downloadRequires();
}
void GM_Script::watchedFileChanged(const QString &file)
{
if (m_fileName == file) {
parseScript();
m_manager->removeScript(this, false);
m_manager->addScript(this);
emit scriptChanged();
reloadScript();
}
}
@ -218,6 +214,7 @@ void GM_Script::parseScript()
m_version.clear();
m_include.clear();
m_exclude.clear();
m_require.clear();
m_downloadUrl.clear();
m_updateUrl.clear();
m_startAt = DocumentEnd;
@ -247,7 +244,6 @@ void GM_Script::parseScript()
return;
}
QStringList requireList;
QzRegExp rxNL(QSL("(?:\\r\\n|[\\r\\n])"));
const QStringList lines = metadataBlock.split(rxNL, QString::SkipEmptyParts);
@ -295,7 +291,7 @@ void GM_Script::parseScript()
m_exclude.append(value);
}
else if (key == QLatin1String("@require")) {
requireList.append(value);
m_require.append(value);
}
else if (key == QLatin1String("@run-at")) {
if (value == QLatin1String("document-end")) {
@ -335,6 +331,28 @@ void GM_Script::parseScript()
"}"
"delete __qz_includes;")).arg(toJavaScriptList(m_exclude), toJavaScriptList(m_include));
m_script = QSL("(function(){%1\n%2\n%3\n%4\n})();").arg(runCheck, gmValues, m_manager->requireScripts(requireList), fileData);
m_script = QSL("(function(){%1\n%2\n%3\n%4\n})();").arg(runCheck, gmValues, m_manager->requireScripts(m_require), fileData);
m_valid = true;
downloadRequires();
}
void GM_Script::reloadScript()
{
parseScript();
m_manager->removeScript(this, false);
m_manager->addScript(this);
emit scriptChanged();
}
void GM_Script::downloadRequires()
{
for (const QString &url : qAsConst(m_require)) {
if (m_manager->requireScripts({url}).isEmpty()) {
GM_Downloader *downloader = new GM_Downloader(QUrl(url), m_manager, GM_Downloader::DownloadRequireScript);
connect(downloader, &GM_Downloader::finished, this, &GM_Script::reloadScript);
}
}
}

View File

@ -1,6 +1,6 @@
/* ============================================================
* GreaseMonkey plugin for QupZilla
* Copyright (C) 2012-2016 David Rosca <nowrep@gmail.com>
* Copyright (C) 2012-2017 David Rosca <nowrep@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
@ -55,8 +55,8 @@ public:
QStringList include() const;
QStringList exclude() const;
QStringList require() const;
QString script() const;
QString metaData() const;
QString fileName() const;
@ -74,6 +74,8 @@ private slots:
private:
void parseScript();
void reloadScript();
void downloadRequires();
GM_Manager* m_manager;
DelayedFileWatcher* m_fileWatcher;
@ -85,6 +87,7 @@ private:
QStringList m_include;
QStringList m_exclude;
QStringList m_require;
QUrl m_downloadUrl;
QUrl m_updateUrl;