diff options
Diffstat (limited to 'src/slxbrowser.cpp')
| -rw-r--r-- | src/slxbrowser.cpp | 290 |
1 files changed, 116 insertions, 174 deletions
diff --git a/src/slxbrowser.cpp b/src/slxbrowser.cpp index 8eceea0..3bb1161 100644 --- a/src/slxbrowser.cpp +++ b/src/slxbrowser.cpp @@ -1,24 +1,29 @@ #include "slxbrowser.h" #include "webview.h" #include "nam.h" -#include <QtWebKitWidgets> -#include <QWebPage> -#include <QNetworkReply> -#include <QSslConfiguration> +#include <QtWebEngineWidgets/QWebEngineSettings> +#include <QtWebEngineWidgets/QWebEnginePage> +#include <QtWebEngineWidgets/QWebEngineProfile> +#include <QtWebEngineWidgets/QWebEngineHistory> #include <QProgressBar> #include <QDateTime> +#include <QVBoxLayout> +#include <QMessageBox> +#include <QRegularExpression> +#include <QDebug> +#include <utility> static QRegularExpression urlListToRegExp(const QStringList &list); SlxBrowser::SlxBrowser(BrowserSettings settings) : QMainWindow(nullptr), - _settings(settings), + _settings(std::move(settings)), _unsupportedUri(false), - _blockedSite(false), - _lastPageLoad(0), - _activity(false), - _lastActivity(0), - _pageValid(false) + _blockedSite(false), + _lastPageLoad(0), + _activity(false), + _lastActivity(0), + _pageValid(false) { _settings.reloadInterval *= 1000; if (_settings.zoom <= 0) { @@ -32,16 +37,17 @@ SlxBrowser::SlxBrowser(BrowserSettings settings) } else if (_settings.maximized) { this->showMaximized(); } - QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalStorageEnabled, true); - //QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true); - QWidget *w = new QWidget; - QLayout *l = new QVBoxLayout; - _browser = new WebView; - _browser->setZoomFactor(float(_settings.zoom) * .01f); - _progress = new QProgressBar; - _progress->hide(); - l->addWidget(_browser); - l->addWidget(_progress); + // Enable local storage in WebEngine + _browser = new WebView; + _browser->page()->settings()->setAttribute(QWebEngineSettings::LocalStorageEnabled, true); + _browser->setIgnoreSslErrors(_settings.ignoreSslErrors); + auto *w = new QWidget; + QLayout *l = new QVBoxLayout; + _browser->setZoomFactor(float(_settings.zoom) * .01f); + _progress = new QProgressBar; + _progress->hide(); + l->addWidget(_browser); + l->addWidget(_progress); l->setMargin(0); l->setSpacing(0); l->setContentsMargins(0,0,0,0); @@ -52,180 +58,117 @@ SlxBrowser::SlxBrowser(BrowserSettings settings) _reset.setSingleShot(true); connect(&_reset, &QTimer::timeout, this, &SlxBrowser::reloadInitial); - connect(_browser, &WebView::loadStarted, this, &SlxBrowser::loadStarted); - connect(_browser, &WebView::loadFinished, this, &SlxBrowser::loadFinished); - connect(_browser, &WebView::loadProgress, this, &SlxBrowser::loadProgress); - // - QWebPage *page = _browser->page(); - QNetworkAccessManager *nam; - if (_settings.whiteList.isEmpty() && _settings.blackList.isEmpty()) { - nam = new QNetworkAccessManager(this); - } else { - if (_settings.blackList.isEmpty()) { - _settings.blackList << "*"; - } - // Just to be safe - _settings.whiteList << _settings.url; - nam = new SlxNetworkAccessManager(urlListToRegExp(_settings.blackList), urlListToRegExp(_settings.whiteList)); - } - connect(nam, &QNetworkAccessManager::sslErrors, this, &SlxBrowser::sslErrors); - connect(nam, &QNetworkAccessManager::finished, this, &SlxBrowser::requestFinished); - page->setNetworkAccessManager(nam); - page->mainFrame()->load(_settings.url); - // - _browser->show(); + connect(_browser, &WebView::loadStarted, this, &SlxBrowser::loadStarted); + connect(_browser, &WebView::loadFinished, this, &SlxBrowser::loadFinished); + connect(_browser, &WebView::loadProgress, this, &SlxBrowser::loadProgress); + // URL filtering via interceptor + if (!_settings.whiteList.isEmpty() || !_settings.blackList.isEmpty()) { + if (_settings.blackList.isEmpty()) { + _settings.blackList << "*"; + } + _settings.whiteList << _settings.url; // ensure initial URL allowed + auto *interceptor = new SlxRequestInterceptor(urlListToRegExp(_settings.blackList), urlListToRegExp(_settings.whiteList), this); + connect(interceptor, &SlxRequestInterceptor::urlBlocked, this, [this](const QUrl&){ + _blockedSite = true; + }); + connect(interceptor, &SlxRequestInterceptor::unsupportedScheme, this, [this](const QUrl&){ + _unsupportedUri = true; + }); + _browser->page()->profile()->setUrlRequestInterceptor(interceptor); + } + _browser->load(QUrl(_settings.url)); + // + _browser->show(); } SlxBrowser::~SlxBrowser() -{ -} += default; void SlxBrowser::loadStarted() { - _pageValid = false; - _reset.stop(); - if (_settings.reloadInterval > 0) { - _reset.start(_settings.reloadInterval + 5000); - } - _normalError.clear(); - _sslErrors.clear(); - _progress->setValue(0); - _progress->show(); + _pageValid = false; + _reset.stop(); + if (_settings.reloadInterval > 0) { + _reset.start(_settings.reloadInterval + 5000); + } + _progress->setValue(0); + _progress->show(); } void SlxBrowser::maybeTriggerBack() { - auto elems = _browser->page()->mainFrame()->documentElement().findAll("*"); - if (elems.count() > 10) - return; - QStringList want{{ "HEAD", "TITLE", "H1", "HR", "A", "PRE" }}; - for (auto x : elems) { - if (x.tagName() != want.first()) - continue; - want.pop_front(); - if (want.isEmpty()) - break; - } - if (want.isEmpty()) { - // Was probably a JS redirect, go back before displaying the error - _browser->page()->triggerAction(QWebPage::Back); - } + // Best-effort: if there is a back entry, go back + if (_browser->page()->history()->canGoBack()) + _browser->back(); } void SlxBrowser::loadFinished(bool ok) { - _progress->hide(); - bool abortedDl = _browser->wasAbortedDownload(); - if (!abortedDl && !ok) { - if (_unsupportedUri) { - QMessageBox::warning(this, QString::fromUtf8("Denied"), - QString::fromUtf8("This URL type is not supported.\n\n" - "Diese Art Link wird nicht unterstützt.\n\n" - "(z.B. Mail)")); - } else if (_blockedSite) { - maybeTriggerBack(); - QTimer::singleShot(10, [=]() { - maybeTriggerBack(); - QMessageBox::warning(this, QString::fromUtf8("Denied"), - QString::fromUtf8("Target URL not allowed.\n\n" - "Dieser Link führt auf eine nicht erlaubte Seite.")); - }); - } else { - _browser->blockSignals(true); - _browser->page()->mainFrame()->setHtml("<html><body style='background:blue;color:white'><br><br>" - "<center><h1>Page Load Error</h1><div id='content'></div><br>" - "<p><a style='color:white' href='#' onclick='window.history.back()'>Back</a></p>" - "</center></body></html>"); - _browser->blockSignals(false); - QWebElement el = _browser->page()->mainFrame()->documentElement().findFirst("#content"); - QString str; - if (!_sslErrors.empty()) { - str.append("SSL Errors:\n"); - for (QSslError err : _sslErrors) { - str.append(err.errorString()); - str.append('\n'); - } - } else if (!_normalError.isEmpty()) { - str.append("Load Error:\n"); - str.append(_normalError); - } else { - str.append("Unknown Error"); - } - str.append("\n\n\n\n" + QDateTime::currentDateTime().toString()); - el.setPlainText(str); - _pageValid = false; - if (_settings.reloadInterval > 0) { - _reset.start(qMin(30000, _settings.reloadInterval)); - } else { - _reset.start(30000); - } - } - _sslErrors.clear(); - _normalError.clear(); - } else { - _pageValid = true; - if (_settings.reloadInterval > 0) { - _reset.start(qMax(_settings.reloadInterval / 20, 1000)); - } - } + _progress->hide(); + bool abortedDl = _browser->wasAbortedDownload(); + if (!abortedDl && !ok) { + if (_unsupportedUri) { + QMessageBox::warning(this, QString::fromUtf8("Denied"), + QString::fromUtf8("This URL type is not supported.\n\n" + "Diese Art Link wird nicht unterstützt.\n\n" + "(z.B. Mail)")); + } else if (_blockedSite) { + maybeTriggerBack(); + QTimer::singleShot(10, [this]() { + QMessageBox::warning(this, QString::fromUtf8("Denied"), + QString::fromUtf8("Target URL not allowed.\n\n" + "Dieser Link führt auf eine nicht erlaubte Seite.")); + }); + } else { + QString html = QString::fromUtf8( + "<html><body style='background:blue;color:white'><br><br>" + "<center><h1>Page Load Error</h1><div>%1</div><br>" + "<p><a style='color:white' href='#' onclick='history.back()'>Back</a></p>" + "</center></body></html>") + .arg(QDateTime::currentDateTime().toString()); + _browser->setHtml(html); + _pageValid = false; + if (_settings.reloadInterval > 0) { + _reset.start(qMin(30000, _settings.reloadInterval)); + } else { + _reset.start(30000); + } + } + } else { + _pageValid = true; + if (_settings.reloadInterval > 0) { + _reset.start(qMax(_settings.reloadInterval / 20, 1000)); + } + } _unsupportedUri = false; - _blockedSite = false; - _lastPageLoad = QDateTime::currentMSecsSinceEpoch();; + _blockedSite = false; + _lastPageLoad = QDateTime::currentMSecsSinceEpoch();; } void SlxBrowser::loadProgress(int progress) { - _progress->setValue(progress); -} - -void SlxBrowser::sslErrors(QNetworkReply* reply, const QList<QSslError>& errors) -{ - if (_settings.ignoreSslErrors) { - reply->ignoreSslErrors(); - return; - } - for (const auto& err : errors) { - qDebug() << "SSL:" << err; - } - _sslErrors.append(errors); -} - -void SlxBrowser::requestFinished(QNetworkReply *reply) -{ - if (reply->error() == QNetworkReply::ProtocolUnknownError) { - _unsupportedUri = true; - } else if (reply->error() == QNetworkReply::UnknownNetworkError) { - _blockedSite = true; - } else { - _normalError = reply->errorString(); - if (_normalError.isEmpty()) { - int ec = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); - if (ec >= 400) { - _normalError = QString::asprintf("HTTP ERROR %d", ec); - } - } - } + _progress->setValue(progress); } void SlxBrowser::reloadInitial() { - if (_pageValid) { - if (_activity) { - _lastActivity = QDateTime::currentMSecsSinceEpoch(); - _activity = false; - _reset.start(qMax(_settings.reloadInterval / 20, 1000)); - return; - } - qint64 now = QDateTime::currentMSecsSinceEpoch(); - if (now - qMax(_lastActivity, _lastPageLoad) > _settings.reloadInterval) { - _browser->page()->mainFrame()->load(_settings.url); - } else { - _reset.start(qMax(_settings.reloadInterval / 20, 1000)); - } - } else { - _browser->page()->mainFrame()->load(_settings.url); - } + if (_pageValid) { + if (_activity) { + _lastActivity = QDateTime::currentMSecsSinceEpoch(); + _activity = false; + _reset.start(qMax(_settings.reloadInterval / 20, 1000)); + return; + } + qint64 now = QDateTime::currentMSecsSinceEpoch(); + if (now - qMax(_lastActivity, _lastPageLoad) > _settings.reloadInterval) { + _browser->load(QUrl(_settings.url)); + } else { + _reset.start(qMax(_settings.reloadInterval / 20, 1000)); + } + } else { + _browser->load(QUrl(_settings.url)); + } } static QRegularExpression urlListToRegExp(const QStringList &list) @@ -233,10 +176,9 @@ static QRegularExpression urlListToRegExp(const QStringList &list) // We search in the escaped string, so actually look for \*\* and \* // Capture char before that because it must not be another backslash, as that // means the star was already escaped in the list. - // Since these are C strings there are some additional backslashes here. - static const QRegularExpression STARSTAR("(^|[^\\\\])\\\\\\*\\\\\\*"); - static const QRegularExpression STAR("(^|[^\\\\])\\\\\\*"); - static const QRegularExpression QUEST("(^|[^\\\\])\\\\\\?"); + static const QRegularExpression STARSTAR(R"((^|[^\\])\\\*\\\*)"); + static const QRegularExpression STAR(R"((^|[^\\])\\\*)"); + static const QRegularExpression QUEST(R"((^|[^\\])\\\?)"); static const QString STARSTAR_REP("\\1.*"); static const QString STAR_REP("\\1[^/]*"); static const QString QUEST_REP("\\1.?"); |
