1
mirror of https://invent.kde.org/network/falkon.git synced 2024-12-20 18:56:34 +01:00

AdBlock: Track blocked requests on page

AdBlock icon now indicates number of blocked requests in badge text.
This commit is contained in:
David Rosca 2018-01-06 15:58:12 +01:00
parent ba2ea9cb09
commit a45dbdc883
7 changed files with 109 additions and 57 deletions

View File

@ -40,12 +40,7 @@ AdBlockIcon::AdBlockIcon(QObject *parent)
connect(this, &AbstractButtonInterface::clicked, this, &AdBlockIcon::clicked); connect(this, &AbstractButtonInterface::clicked, this, &AdBlockIcon::clicked);
connect(this, &AbstractButtonInterface::webPageChanged, this, &AdBlockIcon::webPageChanged); connect(this, &AbstractButtonInterface::webPageChanged, this, &AdBlockIcon::webPageChanged);
connect(AdBlockManager::instance(), &AdBlockManager::enabledChanged, this, &AdBlockIcon::updateState); connect(AdBlockManager::instance(), &AdBlockManager::enabledChanged, this, &AdBlockIcon::updateState);
} connect(AdBlockManager::instance(), &AdBlockManager::blockedRequestsChanged, this, &AdBlockIcon::blockedRequestsChanged);
AdBlockIcon::~AdBlockIcon()
{
for (int i = 0; i < m_blockedPopups.count(); ++i)
delete m_blockedPopups.at(i).first;
} }
QString AdBlockIcon::id() const QString AdBlockIcon::id() const
@ -84,20 +79,39 @@ void AdBlockIcon::updateState()
if (!page) { if (!page) {
setActive(false); setActive(false);
setToolTip(name()); setToolTip(name());
setBadgeText(QString());
return; return;
} }
if (!AdBlockManager::instance()->isEnabled()) { if (!AdBlockManager::instance()->isEnabled()) {
setActive(false); setActive(false);
setToolTip(tr("AdBlock is disabled")); setToolTip(tr("AdBlock is disabled"));
setBadgeText(QString());
return; return;
} }
if (!AdBlockManager::instance()->canRunOnScheme(page->url().scheme())) { if (!AdBlockManager::instance()->canRunOnScheme(page->url().scheme())) {
setActive(false); setActive(false);
setToolTip(tr("AdBlock is disabled on this site ")); setToolTip(tr("AdBlock is disabled on this site "));
setBadgeText(QString());
return; return;
} }
setActive(true); setActive(true);
setToolTip(tr("AdBlock is active")); setToolTip(tr("AdBlock is active"));
updateBadgeText();
}
void AdBlockIcon::updateBadgeText()
{
WebPage *page = webPage();
if (!page) {
return;
}
const int count = AdBlockManager::instance()->blockedRequestsForUrl(page->url()).count();
if (count > 0) {
setBadgeText(QString::number(count));
} else {
setBadgeText(QString());
}
} }
void AdBlockIcon::webPageChanged(WebPage *page) void AdBlockIcon::webPageChanged(WebPage *page)
@ -151,18 +165,14 @@ void AdBlockIcon::clicked(ClickController *controller)
menu.addSeparator(); menu.addSeparator();
} }
if (!m_blockedPopups.isEmpty()) {
menu.addAction(tr("Blocked Popup Windows"))->setEnabled(false);
for (int i = 0; i < m_blockedPopups.count(); i++) {
const QPair<AdBlockRule*, QUrl> &pair = m_blockedPopups.at(i);
QString address = pair.second.toString().right(55);
QString actionText = tr("%1 with (%2)").arg(address, pair.first->filter()).replace(QLatin1Char('&'), QLatin1String("&&"));
QAction* action = menu.addAction(actionText, manager, SLOT(showRule()));
action->setData(QVariant::fromValue((void*)pair.first));
}
}
menu.exec(controller->popupPosition(menu.sizeHint())); menu.exec(controller->popupPosition(menu.sizeHint()));
} }
void AdBlockIcon::blockedRequestsChanged(const QUrl &url)
{
WebPage *page = webPage();
if (!page || url != page->url()) {
return;
}
updateState();
}

View File

@ -23,23 +23,12 @@
#include "qzcommon.h" #include "qzcommon.h"
#include "abstractbuttoninterface.h" #include "abstractbuttoninterface.h"
class QUrl; class FALKON_EXPORT AdBlockIcon : public AbstractButtonInterface
class AdBlockRule;
<<<<<<< HEAD
class FALKON_EXPORT AdBlockIcon : public ClickableLabel
||||||| parent of d11997ee... AdBlockIcon: Move from statusbar to navigationbar as tool button
class QUPZILLA_EXPORT AdBlockIcon : public ClickableLabel
=======
class QUPZILLA_EXPORT AdBlockIcon : public AbstractButtonInterface
>>>>>>> d11997ee... AdBlockIcon: Move from statusbar to navigationbar as tool button
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AdBlockIcon(QObject *parent = nullptr); explicit AdBlockIcon(QObject *parent = nullptr);
~AdBlockIcon();
QString id() const override; QString id() const override;
QString name() const override; QString name() const override;
@ -49,11 +38,12 @@ private slots:
private: private:
void updateState(); void updateState();
void updateBadgeText();
void webPageChanged(WebPage *page); void webPageChanged(WebPage *page);
void clicked(ClickController *controller); void clicked(ClickController *controller);
void blockedRequestsChanged(const QUrl &url);
QPointer<WebPage> m_page; QPointer<WebPage> m_page;
QVector<QPair<AdBlockRule*, QUrl> > m_blockedPopups;
}; };
#endif // ADBLOCKICON_H #endif // ADBLOCKICON_H

View File

@ -52,6 +52,8 @@ AdBlockManager::AdBlockManager(QObject* parent)
, m_matcher(new AdBlockMatcher(this)) , m_matcher(new AdBlockMatcher(this))
, m_interceptor(new AdBlockUrlInterceptor(this)) , m_interceptor(new AdBlockUrlInterceptor(this))
{ {
qRegisterMetaType<AdBlockedRequest>();
load(); load();
} }
@ -96,7 +98,7 @@ QList<AdBlockSubscription*> AdBlockManager::subscriptions() const
return m_subscriptions; return m_subscriptions;
} }
bool AdBlockManager::block(QWebEngineUrlRequestInfo &request) bool AdBlockManager::block(QWebEngineUrlRequestInfo &request, QString &ruleFilter)
{ {
QMutexLocker locker(&m_mutex); QMutexLocker locker(&m_mutex);
@ -116,12 +118,10 @@ bool AdBlockManager::block(QWebEngineUrlRequestInfo &request)
return false; return false;
} }
bool res = false;
const AdBlockRule* blockedRule = m_matcher->match(request, urlDomain, urlString); const AdBlockRule* blockedRule = m_matcher->match(request, urlDomain, urlString);
if (blockedRule) { if (blockedRule) {
res = true; ruleFilter = blockedRule->filter();
if (request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) { if (request.resourceType() == QWebEngineUrlRequestInfo::ResourceTypeMainFrame) {
QUrl url(QSL("falkon:adblock")); QUrl url(QSL("falkon:adblock"));
QUrlQuery query; QUrlQuery query;
@ -129,8 +129,7 @@ bool AdBlockManager::block(QWebEngineUrlRequestInfo &request)
query.addQueryItem(QSL("subscription"), blockedRule->subscription()->title()); query.addQueryItem(QSL("subscription"), blockedRule->subscription()->title());
url.setQuery(query); url.setQuery(query);
request.redirect(url); request.redirect(url);
} } else {
else {
request.block(true); request.block(true);
} }
@ -143,7 +142,19 @@ bool AdBlockManager::block(QWebEngineUrlRequestInfo &request)
qDebug() << timer.elapsed() << request.requestUrl(); qDebug() << timer.elapsed() << request.requestUrl();
#endif #endif
return res; return blockedRule;
}
QVector<AdBlockedRequest> AdBlockManager::blockedRequestsForUrl(const QUrl &url) const
{
return m_blockedRequests.value(url);
}
void AdBlockManager::clearBlockedRequestsForUrl(const QUrl &url)
{
if (m_blockedRequests.remove(url)) {
emit blockedRequestsChanged(url);
}
} }
QStringList AdBlockManager::disabledRules() const QStringList AdBlockManager::disabledRules() const
@ -341,6 +352,11 @@ void AdBlockManager::load()
m_matcher->update(); m_matcher->update();
m_loaded = true; m_loaded = true;
connect(m_interceptor, &AdBlockUrlInterceptor::requestBlocked, this, [this](const AdBlockedRequest &request) {
m_blockedRequests[request.firstPartyUrl].append(request);
emit blockedRequestsChanged(request.firstPartyUrl);
});
mApp->networkManager()->installUrlInterceptor(m_interceptor); mApp->networkManager()->installUrlInterceptor(m_interceptor);
} }

View File

@ -1,6 +1,6 @@
/* ============================================================ /* ============================================================
* Falkon - Qt web browser * Falkon - Qt web browser
* Copyright (C) 2010-2017 David Rosca <nowrep@gmail.com> * Copyright (C) 2010-2018 David Rosca <nowrep@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -22,12 +22,11 @@
#include <QStringList> #include <QStringList>
#include <QPointer> #include <QPointer>
#include <QMutex> #include <QMutex>
#include <QUrl>
#include <QWebEngineUrlRequestInfo>
#include "qzcommon.h" #include "qzcommon.h"
class QUrl;
class QWebEngineUrlRequestInfo;
class AdBlockRule; class AdBlockRule;
class AdBlockDialog; class AdBlockDialog;
class AdBlockMatcher; class AdBlockMatcher;
@ -35,6 +34,17 @@ class AdBlockCustomList;
class AdBlockSubscription; class AdBlockSubscription;
class AdBlockUrlInterceptor; class AdBlockUrlInterceptor;
struct AdBlockedRequest
{
QUrl requestUrl;
QUrl firstPartyUrl;
QByteArray requestMethod;
QWebEngineUrlRequestInfo::ResourceType resourceType;
QWebEngineUrlRequestInfo::NavigationType navigationType;
QString rule;
};
Q_DECLARE_METATYPE(AdBlockedRequest)
class FALKON_EXPORT AdBlockManager : public QObject class FALKON_EXPORT AdBlockManager : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -48,6 +58,7 @@ public:
bool isEnabled() const; bool isEnabled() const;
bool canRunOnScheme(const QString &scheme) const; bool canRunOnScheme(const QString &scheme) const;
bool canBeBlocked(const QUrl &url) const;
QString elementHidingRules(const QUrl &url) const; QString elementHidingRules(const QUrl &url) const;
QString elementHidingRulesForDomain(const QUrl &url) const; QString elementHidingRulesForDomain(const QUrl &url) const;
@ -55,7 +66,10 @@ public:
AdBlockSubscription* subscriptionByName(const QString &name) const; AdBlockSubscription* subscriptionByName(const QString &name) const;
QList<AdBlockSubscription*> subscriptions() const; QList<AdBlockSubscription*> subscriptions() const;
bool block(QWebEngineUrlRequestInfo &request); bool block(QWebEngineUrlRequestInfo &request, QString &ruleFilter);
QVector<AdBlockedRequest> blockedRequestsForUrl(const QUrl &url) const;
void clearBlockedRequestsForUrl(const QUrl &url);
QStringList disabledRules() const; QStringList disabledRules() const;
void addDisabledRule(const QString &filter); void addDisabledRule(const QString &filter);
@ -72,6 +86,7 @@ public:
signals: signals:
void enabledChanged(bool enabled); void enabledChanged(bool enabled);
void blockedRequestsChanged(const QUrl &url);
public slots: public slots:
void setEnabled(bool enabled); void setEnabled(bool enabled);
@ -83,8 +98,6 @@ public slots:
AdBlockDialog* showDialog(); AdBlockDialog* showDialog();
private: private:
inline bool canBeBlocked(const QUrl &url) const;
bool m_loaded; bool m_loaded;
bool m_enabled; bool m_enabled;
@ -95,6 +108,7 @@ private:
AdBlockUrlInterceptor *m_interceptor; AdBlockUrlInterceptor *m_interceptor;
QPointer<AdBlockDialog> m_adBlockDialog; QPointer<AdBlockDialog> m_adBlockDialog;
QMutex m_mutex; QMutex m_mutex;
QHash<QUrl, QVector<AdBlockedRequest>> m_blockedRequests;
}; };
#endif // ADBLOCKMANAGER_H #endif // ADBLOCKMANAGER_H

View File

@ -1,6 +1,6 @@
/* ============================================================ /* ============================================================
* Falkon - Qt web browser * Falkon - Qt web browser
* Copyright (C) 2015 David Rosca <nowrep@gmail.com> * Copyright (C) 2015-2018 David Rosca <nowrep@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -17,7 +17,7 @@
* ============================================================ */ * ============================================================ */
#include "adblockurlinterceptor.h" #include "adblockurlinterceptor.h"
#include "adblockmanager.h" #include "adblockrule.h"
AdBlockUrlInterceptor::AdBlockUrlInterceptor(AdBlockManager *manager) AdBlockUrlInterceptor::AdBlockUrlInterceptor(AdBlockManager *manager)
: UrlInterceptor(manager) : UrlInterceptor(manager)
@ -25,8 +25,19 @@ AdBlockUrlInterceptor::AdBlockUrlInterceptor(AdBlockManager *manager)
{ {
} }
void AdBlockUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) void AdBlockUrlInterceptor::interceptRequest(QWebEngineUrlRequestInfo &request)
{ {
if (m_manager->block(info)) QString ruleFilter;
info.block(true); if (!m_manager->block(request, ruleFilter)) {
return;
}
AdBlockedRequest r;
r.requestUrl = request.requestUrl();
r.firstPartyUrl = request.firstPartyUrl();
r.requestMethod = request.requestMethod();
r.resourceType = request.resourceType();
r.navigationType = request.navigationType();
r.rule = ruleFilter;
emit requestBlocked(r);
} }

View File

@ -1,6 +1,6 @@
/* ============================================================ /* ============================================================
* Falkon - Qt web browser * Falkon - Qt web browser
* Copyright (C) 2015 David Rosca <nowrep@gmail.com> * Copyright (C) 2015-2018 David Rosca <nowrep@gmail.com>
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -19,17 +19,23 @@
#ifndef ADBLOCKURLINTERCEPTOR_H #ifndef ADBLOCKURLINTERCEPTOR_H
#define ADBLOCKURLINTERCEPTOR_H #define ADBLOCKURLINTERCEPTOR_H
#include "urlinterceptor.h"
#include "qzcommon.h" #include "qzcommon.h"
#include "urlinterceptor.h"
#include "adblockmanager.h"
class AdBlockManager; class AdBlockManager;
class FALKON_EXPORT AdBlockUrlInterceptor : public UrlInterceptor class FALKON_EXPORT AdBlockUrlInterceptor : public UrlInterceptor
{ {
Q_OBJECT
public: public:
explicit AdBlockUrlInterceptor(AdBlockManager *manager); explicit AdBlockUrlInterceptor(AdBlockManager *manager);
void interceptRequest(QWebEngineUrlRequestInfo &info); void interceptRequest(QWebEngineUrlRequestInfo &request);
signals:
void requestBlocked(const AdBlockedRequest &request);
private: private:
AdBlockManager *m_manager; AdBlockManager *m_manager;

View File

@ -368,8 +368,13 @@ bool WebPage::acceptNavigationRequest(const QUrl &url, QWebEnginePage::Navigatio
return false; return false;
// AdBlock // AdBlock
if (url.scheme() == QL1S("abp") && AdBlockManager::instance()->addSubscriptionFromUrl(url)) AdBlockManager *manager = AdBlockManager::instance();
if (isMainFrame) {
manager->clearBlockedRequestsForUrl(WebPage::url());
}
if (url.scheme() == QL1S("abp") && AdBlockManager::instance()->addSubscriptionFromUrl(url)) {
return false; return false;
}
return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame); return QWebEnginePage::acceptNavigationRequest(url, type, isMainFrame);
} }