Adblock now can efficiently perform unwanted element hiding.

This commit is contained in:
Martin Rotter 2021-01-08 11:08:37 +01:00
parent b3d86a8766
commit 6bdb1446a1
8 changed files with 66 additions and 7 deletions

View File

@ -157,7 +157,7 @@ You can right click on any item in embedded web browser and hit `Save as` button
You can download up to 6 files simultaneously.
## AdBlock
[Web-based variant](#web-based-and-lite-app-variants) of RSS Guard offers ad-blocking functionality too.
[Web-based variant](#web-based-and-lite-app-variants) of RSS Guard offers ad-blocking functionality. AdBlock uses standard AdBlock-Plus-like scripts, thus allowing you to use EasyList etc. AdBlock supports element hiding rules and site-wide blocking.
You can find its settings in `Web browser & tabs` section of main menu.

View File

@ -99,6 +99,7 @@
#define LOGSEC_FEEDMODEL "feed-model: "
#define LOGSEC_FEEDDOWNLOADER "feed-downloader: "
#define LOGSEC_MESSAGEMODEL "message-model: "
#define LOGSEC_JS "javascript: "
#define LOGSEC_GUI "gui: "
#define LOGSEC_CORE "core: "
#define LOGSEC_DB "database: "

View File

@ -329,6 +329,23 @@ QString AdBlockManager::elementHidingRulesForDomain(const QUrl& url) const {
}
}
QString AdBlockManager::generateJsForElementHiding(const QString& css) const {
QString source = QL1S("(function() {"
"var head = document.getElementsByTagName('head')[0];"
"if (!head) return;"
"var css = document.createElement('style');"
"css.setAttribute('type', 'text/css');"
"css.appendChild(document.createTextNode('%1'));"
"head.appendChild(css);"
"})()");
QString style = css;
style.replace(QL1S("'"), QL1S("\\'"));
style.replace(QL1S("\n"), QL1S("\\n"));
return source.arg(style);
}
AdBlockSubscription* AdBlockManager::subscriptionByName(const QString& name) const {
for (AdBlockSubscription* subscription : m_subscriptions) {
if (subscription->title() == name) {

View File

@ -58,6 +58,8 @@ class AdBlockManager : public QObject {
QString elementHidingRules(const QUrl& url) const;
QString elementHidingRulesForDomain(const QUrl& url) const;
QString generateJsForElementHiding(const QString& css) const;
AdBlockSubscription* subscriptionByName(const QString& name) const;
QList<AdBlockSubscription*> subscriptions() const;

View File

@ -30,6 +30,6 @@ void AdBlockUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
if (m_manager->block(AdblockRequestInfo(info)) != nullptr) {
info.block(true);
qWarning() << LOGSEC_ADBLOCK << "Blocked request:" << QUOTE_W_SPACE_DOT(info.requestUrl().toString());
qWarningNN << LOGSEC_ADBLOCK << "Blocked request:" << QUOTE_W_SPACE_DOT(info.requestUrl().toString());
}
}

View File

@ -17,19 +17,46 @@
#include <QStringList>
#include <QUrl>
#include <QUrlQuery>
#include <QWebEngineScript>
WebPage::WebPage(QObject* parent) : QWebEnginePage(parent) {
setBackgroundColor(Qt::transparent);
connect(this, &QWebEnginePage::loadFinished, this, &WebPage::hideUnwantedElements);
}
WebViewer* WebPage::view() const {
return qobject_cast<WebViewer*>(QWebEnginePage::view());
}
bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame) {
void WebPage::hideUnwantedElements() {
if (!qApp->web()->adBlock()->isEnabled()) {
return;
}
auto css = qApp->web()->adBlock()->elementHidingRules(url());
if (!css.isEmpty()) {
auto js = qApp->web()->adBlock()->generateJsForElementHiding(css);
runJavaScript(js);
qDebugNN << LOGSEC_JS << "Running global JS for element hiding rules.";
}
css = qApp->web()->adBlock()->elementHidingRulesForDomain(url());
if (!css.isEmpty()) {
auto js = qApp->web()->adBlock()->generateJsForElementHiding(css);
runJavaScript(js);
qDebugNN << LOGSEC_JS << "Running domain-specific JS for element hiding rules.";
}
}
bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool is_main_frame) {
const RootItem* root = view()->root();
if (isMainFrame) {
if (is_main_frame) {
auto* adblock_rule = qApp->web()->adBlock()->block(AdblockRequestInfo(url));
if (adblock_rule != nullptr) {
@ -57,6 +84,13 @@ bool WebPage::acceptNavigationRequest(const QUrl& url, NavigationType type, bool
return true;
}
else {
return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
return QWebEnginePage::acceptNavigationRequest(url, type, is_main_frame);
}
}
void WebPage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message,
int line_number, const QString& source_id) {
Q_UNUSED(level)
qWarningNN << LOGSEC_JS << message << QSL(" (source: %1:%2)").arg(source_id, QString::number(line_number));
}

View File

@ -15,8 +15,13 @@ class WebPage : public QWebEnginePage {
WebViewer* view() const;
private slots:
void hideUnwantedElements();
protected:
bool acceptNavigationRequest(const QUrl& url, NavigationType type, bool isMainFrame);
virtual bool acceptNavigationRequest(const QUrl& url, NavigationType type, bool is_main_frame);
virtual void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message,
int line_number, const QString& source_id);
};
#endif // WEBPAGE_H

View File

@ -704,7 +704,7 @@ void ServiceRoot::assembleFeeds(Assignment feeds) {
categories.value(feed.first)->appendChild(feed.second);
}
else {
qWarning("Feed '%s' is loose, skipping it.", qPrintable(feed.second->title()));
qWarningNN << LOGSEC_CORE << "Feed" << QUOTE_W_SPACE(feed.second->title()) << "is loose, skipping it.";
}
}
}