Rename the local content blocking implementation and its tests from ContentFilter to ContentBlocker while keeping the existing substring matcher backend and behavior. Update the WebContent IPC method, WebView option names, debug toggle, and default config file name to use content blocker terminology.
126 lines
3.4 KiB
C++
126 lines
3.4 KiB
C++
/*
|
|
* Copyright (c) 2025, Tim Ledbetter <tim.ledbetter@ladybird.org>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <LibTest/TestCase.h>
|
|
#include <LibURL/Parser.h>
|
|
#include <LibURL/URL.h>
|
|
#include <LibWeb/Loader/ContentBlocker.h>
|
|
|
|
namespace Web {
|
|
|
|
static ContentBlocker& make_blocker(Vector<String> patterns)
|
|
{
|
|
auto& blocker = ContentBlocker::the();
|
|
MUST(blocker.set_patterns(patterns));
|
|
return blocker;
|
|
}
|
|
|
|
static URL::URL url(StringView string)
|
|
{
|
|
auto result = URL::Parser::basic_parse(string);
|
|
EXPECT(result.has_value());
|
|
return result.release_value();
|
|
}
|
|
|
|
TEST_CASE(empty_pattern_list)
|
|
{
|
|
auto& blocker = make_blocker({});
|
|
|
|
EXPECT(!blocker.is_filtered(url("https://anything.com"sv)));
|
|
EXPECT(!blocker.is_filtered(url("data:text/plain,hi"sv)));
|
|
}
|
|
|
|
TEST_CASE(basic_blocking)
|
|
{
|
|
Vector<String> patterns = {
|
|
"ads."_string,
|
|
"?banner"_string,
|
|
"tracker"_string
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
|
|
EXPECT(blocker.is_filtered(url("https://example.com/ads.js"sv)));
|
|
EXPECT(blocker.is_filtered(url("http://site.com/page.html?banner=true"sv)));
|
|
EXPECT(blocker.is_filtered(url("https://tracker.example.org/ping"sv)));
|
|
EXPECT(!blocker.is_filtered(url("https://ds.example.com/page.html"sv)));
|
|
}
|
|
|
|
TEST_CASE(data_urls_exempt)
|
|
{
|
|
Vector<String> patterns = {
|
|
{ "data:"_string },
|
|
{ "evil.com"_string }
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
|
|
EXPECT(!blocker.is_filtered(url("data:text/plain,hello"sv)));
|
|
EXPECT(!blocker.is_filtered(url("data:image/png;base64,abc123"sv)));
|
|
EXPECT(blocker.is_filtered(url("https://evil.com/script.js"sv)));
|
|
}
|
|
|
|
TEST_CASE(disable_filtering)
|
|
{
|
|
Vector<String> patterns = {
|
|
{ "example.com"_string }
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
blocker.set_filtering_enabled(false);
|
|
|
|
EXPECT(!blocker.is_filtered(url("https://example.com"sv)));
|
|
EXPECT(!blocker.is_filtered(url("http://example.com/ads"sv)));
|
|
|
|
blocker.set_filtering_enabled(true);
|
|
EXPECT(blocker.is_filtered(url("https://example.com"sv)));
|
|
}
|
|
|
|
TEST_CASE(substring_matches)
|
|
{
|
|
Vector<String> patterns = {
|
|
{ "ads"_string },
|
|
{ "ad/"_string }
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
|
|
EXPECT(blocker.is_filtered(url("https://site.com/ads/banner.jpg"sv)));
|
|
EXPECT(blocker.is_filtered(url("http://marketing.com/ad/page"sv)));
|
|
EXPECT(!blocker.is_filtered(url("https://site.com/content/article.html"sv)));
|
|
EXPECT(!blocker.is_filtered(url("http://advancedtech.com/home"sv)));
|
|
}
|
|
|
|
TEST_CASE(file_scheme_can_be_filtered)
|
|
{
|
|
Vector<String> patterns = {
|
|
{ "secret"_string },
|
|
{ ".txt"_string }
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
|
|
EXPECT(blocker.is_filtered(url("file:///home/user/secret.txt"sv)));
|
|
EXPECT(!blocker.is_filtered(url("file:///home/user/document.pdf"sv)));
|
|
}
|
|
|
|
TEST_CASE(query_parameters_and_fragments)
|
|
{
|
|
Vector<String> patterns = {
|
|
{ "#ad="_string },
|
|
{ "?ad="_string },
|
|
{ "#sponsored"_string }
|
|
};
|
|
|
|
auto& blocker = make_blocker(move(patterns));
|
|
|
|
EXPECT(blocker.is_filtered(url("https://site.com/page?ad=123"sv)));
|
|
EXPECT(blocker.is_filtered(url("https://site.com/page#ad=456"sv)));
|
|
EXPECT(blocker.is_filtered(url("https://site.com/page?ref=home&ad=1#sponsored"sv)));
|
|
EXPECT(!blocker.is_filtered(url("https://site.com/page?ref=home"sv)));
|
|
}
|
|
|
|
}
|