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

AdBlock: Support for $elemhide and $document exception rules

- with @@||qupzilla.com^$document you can completely disable
  AdBlock from running on qupzilla.com site
This commit is contained in:
nowrep 2012-07-04 16:00:53 +02:00
parent 526c7475d4
commit 2dc0785aff
8 changed files with 116 additions and 14 deletions

View File

@ -90,6 +90,10 @@ QNetworkReply* AdBlockManager::block(const QNetworkRequest &request)
QVariant v = request.attribute((QNetworkRequest::Attribute)(QNetworkRequest::User + 100));
WebPage* webPage = static_cast<WebPage*>(v.value<void*>());
if (WebPage::isPointerSafeToUse(webPage)) {
if (!canBeBlocked(webPage->url())) {
return 0;
}
webPage->addAdBlockRule(blockedRule, request.url());
}
@ -269,6 +273,17 @@ bool AdBlockManager::canRunOnScheme(const QString &scheme) const
return !(scheme == "file" || scheme == "qrc" || scheme == "qupzilla" || scheme == "data" || scheme == "abp");
}
bool AdBlockManager::canBeBlocked(const QUrl &url) const
{
foreach(AdBlockSubscription * subscription, m_subscriptions) {
if (subscription->adBlockDisabledForUrl(url)) {
return false;
}
}
return true;
}
QString AdBlockManager::elementHidingRules() const
{
QString rules;
@ -285,12 +300,16 @@ QString AdBlockManager::elementHidingRules() const
return rules;
}
QString AdBlockManager::elementHidingRulesForDomain(const QString &domain) const
QString AdBlockManager::elementHidingRulesForDomain(const QUrl &url) const
{
QString rules;
foreach(AdBlockSubscription * subscription, m_subscriptions) {
rules.append(subscription->elementHidingRulesForDomain(domain));
if (subscription->elemHideDisabledForUrl(url)) {
return QString();
}
rules.append(subscription->elementHidingRulesForDomain(url.host()));
}
// Remove last ","

View File

@ -46,7 +46,7 @@ public:
bool canRunOnScheme(const QString &scheme) const;
QString elementHidingRules() const;
QString elementHidingRulesForDomain(const QString &domain) const;
QString elementHidingRulesForDomain(const QUrl &url) const;
AdBlockSubscription* subscriptionByName(const QString &name) const;
QList<AdBlockSubscription*> subscriptions() const;
@ -69,6 +69,7 @@ public slots:
AdBlockDialog* showDialog();
private:
bool canBeBlocked(const QUrl &url) const;
static AdBlockManager* s_adBlockManager;
bool m_loaded;

View File

@ -112,6 +112,8 @@ AdBlockRule::AdBlockRule(const QString &filter, AdBlockSubscription* subscriptio
, m_subdocumentException(false)
, m_xmlhttprequest(false)
, m_xmlhttprequestException(false)
, m_document(false)
, m_elemhide(false)
, m_caseSensitivity(Qt::CaseInsensitive)
{
setFilter(filter);
@ -148,6 +150,16 @@ QString AdBlockRule::cssSelector() const
return m_cssSelector;
}
bool AdBlockRule::isDocument() const
{
return m_document;
}
bool AdBlockRule::isElemhide() const
{
return m_elemhide;
}
bool AdBlockRule::isDomainRestricted() const
{
return m_domainRestricted;
@ -234,6 +246,18 @@ bool AdBlockRule::networkMatch(const QNetworkRequest &request, const QString &do
return matched;
}
bool AdBlockRule::urlMatch(const QUrl &url) const
{
if (!m_document && !m_elemhide) {
return false;
}
const QString &encodedUrl = url.toEncoded();
const QString &domain = url.host();
return networkMatch(QNetworkRequest(url), domain, encodedUrl);
}
bool AdBlockRule::matchDomain(const QString &domain) const
{
if (!m_domainRestricted) {
@ -386,6 +410,14 @@ void AdBlockRule::parseFilter()
m_xmlhttprequestException = option.startsWith('~');
++handledOptions;
}
else if (option == "document" && m_exception) {
m_document = true;
++handledOptions;
}
else if (option == "elemhide" && m_exception) {
m_elemhide = true;
++handledOptions;
}
else if (option == "collapse") {
// Hiding placeholders of blocked elements
++handledOptions;

View File

@ -71,6 +71,9 @@ public:
bool isCssRule() const;
QString cssSelector() const;
bool isDocument() const;
bool isElemhide() const;
bool isDomainRestricted() const;
bool isException() const;
@ -82,6 +85,7 @@ public:
bool isInternalDisabled() const;
bool networkMatch(const QNetworkRequest &request, const QString &domain, const QString &encodedUrl) const;
bool urlMatch(const QUrl &url) const;
bool matchDomain(const QString &domain) const;
bool matchThirdParty(const QNetworkRequest &request) const;
@ -128,6 +132,10 @@ private:
bool m_xmlhttprequest;
bool m_xmlhttprequestException;
// Exception only options
bool m_document;
bool m_elemhide;
Qt::CaseSensitivity m_caseSensitivity;
};

View File

@ -53,7 +53,6 @@
#include <QTimer>
#include <QNetworkReply>
#include <QDebug>
// #define ADBLOCKSUBSCRIPTION_DEBUG
AdBlockSubscription::AdBlockSubscription(const QString &title, QObject* parent)
: QObject(parent)
@ -203,6 +202,32 @@ const AdBlockRule* AdBlockSubscription::match(const QNetworkRequest &request, co
return 0;
}
bool AdBlockSubscription::adBlockDisabledForUrl(const QUrl &url) const
{
foreach(const AdBlockRule * rule, m_documentRules) {
if (rule->urlMatch(url)) {
return true;
}
}
return false;
}
bool AdBlockSubscription::elemHideDisabledForUrl(const QUrl &url) const
{
if (adBlockDisabledForUrl(url)) {
return true;
}
foreach(const AdBlockRule * rule, m_elemhideRules) {
if (rule->urlMatch(url)) {
return true;
}
}
return false;
}
QString AdBlockSubscription::elementHidingRules() const
{
return m_elementHidingRules;
@ -296,8 +321,11 @@ void AdBlockSubscription::populateCache()
m_networkBlockRules.clear();
m_domainRestrictedCssRules.clear();
m_elementHidingRules.clear();
m_documentRules.clear();
m_elemhideRules.clear();
for (int i = 0; i < m_rules.count(); ++i) {
int count = m_rules.count();
for (int i = 0; i < count; ++i) {
const AdBlockRule* rule = &m_rules.at(i);
if (!rule->isEnabled()) {
continue;
@ -310,10 +338,14 @@ void AdBlockSubscription::populateCache()
else {
m_elementHidingRules.append(rule->cssSelector() + ",");
}
continue;
}
if (rule->isException()) {
else if (rule->isDocument()) {
m_documentRules.append(rule);
}
else if (rule->isElemhide()) {
m_elemhideRules.append(rule);
}
else if (rule->isException()) {
m_networkExceptionRules.append(rule);
}
else {

View File

@ -46,6 +46,7 @@
#ifndef ADBLOCKSUBSCRIPTION_H
#define ADBLOCKSUBSCRIPTION_H
#include <QVarLengthArray>
#include <QList>
#include <QUrl>
@ -77,6 +78,9 @@ public:
const AdBlockRule* match(const QNetworkRequest &request, const QString &urlDomain, const QString &urlString) const;
bool adBlockDisabledForUrl(const QUrl &url) const;
bool elemHideDisabledForUrl(const QUrl &url) const;
QString elementHidingRules() const;
QString elementHidingRulesForDomain(const QString &domain) const;
@ -112,10 +116,12 @@ protected:
QList<AdBlockRule> m_rules;
QString m_elementHidingRules;
// sorted list
QList<const AdBlockRule*> m_networkExceptionRules;
QList<const AdBlockRule*> m_networkBlockRules;
QList<const AdBlockRule*> m_domainRestrictedCssRules;
QVarLengthArray<const AdBlockRule*> m_networkExceptionRules;
QVarLengthArray<const AdBlockRule*> m_networkBlockRules;
QVarLengthArray<const AdBlockRule*> m_domainRestrictedCssRules;
QVarLengthArray<const AdBlockRule*> m_documentRules;
QVarLengthArray<const AdBlockRule*> m_elemhideRules;
private:
QString m_title;

View File

@ -543,7 +543,11 @@ void WebPage::cleanBlockedObjects()
}
// Apply domain-specific element hiding rules
QString elementHiding = AdBlockManager::instance()->elementHidingRulesForDomain(url().host());
QString elementHiding = AdBlockManager::instance()->elementHidingRulesForDomain(url());
if (elementHiding.isEmpty()) {
return;
}
elementHiding.append("{display: none !important;}\n</style>");
QWebElement bodyElement = docElement.findFirst("body");

View File

@ -35,7 +35,7 @@
<location filename="../testplugin_sidebar.cpp" line="32"/>
<location filename="../testplugin_sidebar.cpp" line="37"/>
<source>Testing Sidebar</source>
<translation type="unfinished"></translation>
<translation>Testovací postranní bar</translation>
</message>
</context>
</TS>