Skip to content

Commit

Permalink
Support :remove/:remove-attr/:remove-class adblock filter syntax (
Browse files Browse the repository at this point in the history
#23702)

Support :remove/:remove-attr/:remove-class adblock filter syntax
with new injected content script.

Merge resource dicts to enable new remove keys supported by adblock-rs

onMutation search addedNodes instead of document.querySelector

Classes: check one exists
Attributes: no need for check, just remove
  • Loading branch information
bcaller authored Jun 12, 2024
1 parent 857e48e commit 706f518
Show file tree
Hide file tree
Showing 7 changed files with 392 additions and 34 deletions.
84 changes: 84 additions & 0 deletions browser/brave_shields/ad_block_service_browsertest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2246,6 +2246,90 @@ IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringCustomStyle) {
EXPECT_EQ(base::Value(true), result.value);
}

IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringRemoveStatic) {
UpdateAdBlockInstanceWithRules(
"b.com###ad-banner:remove()\n"
"b.com##.whatever:remove()");

GURL tab_url =
embedded_test_server()->GetURL("b.com", "/cosmetic_filtering.html");
NavigateToURL(tab_url);

content::WebContents* contents = web_contents();

EXPECT_EQ(true, EvalJs(contents, "check('#ad-banner', existence(false))"));
}

IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringRemoveDynamic) {
UpdateAdBlockInstanceWithRules("b.com##.blockme:remove()");

GURL tab_url =
embedded_test_server()->GetURL("b.com", "/cosmetic_filtering.html");
NavigateToURL(tab_url);

content::WebContents* contents = web_contents();

auto result = EvalJs(contents,
"addElementsDynamically();\n"
"wait('.dontblockme', existence(true)).then(() =>"
"wait('.blockme', existence(false)))");
ASSERT_TRUE(result.error.empty());
EXPECT_EQ(base::Value(true), result.value);
}

IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringRemoveAttribute) {
UpdateAdBlockInstanceWithRules(
"b.com##.ad img:remove-attr(something)\n"
"b.com##.ad img:remove-attr(src)\n"
"b.com##.ad img:remove-attr(nothing)\n"
"b.com##img:remove-attr(whatever)");

GURL tab_url =
embedded_test_server()->GetURL("b.com", "/cosmetic_filtering.html");
NavigateToURL(tab_url);

content::WebContents* contents = web_contents();

EXPECT_EQ(true, EvalJs(contents, "check('.ad img', attributes(['alt']))"));

// Sanity check selector
EXPECT_EQ(
true,
EvalJs(contents, "check('#relative-url-div img', attributes(['src']))"));
}

IN_PROC_BROWSER_TEST_F(AdBlockServiceTest,
CosmeticFilteringRemoveAttributeDynamic) {
UpdateAdBlockInstanceWithRules("b.com##img.blockme:remove-attr(src)");

GURL tab_url =
embedded_test_server()->GetURL("b.com", "/cosmetic_filtering.html");
NavigateToURL(tab_url);

content::WebContents* contents = web_contents();

auto result = EvalJs(contents,
"addElementsDynamically();\n"
"wait('img.blockme', attributes(['class']))");
ASSERT_TRUE(result.error.empty());
EXPECT_EQ(base::Value(true), result.value);
}

IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringRemoveClass) {
UpdateAdBlockInstanceWithRules(
"b.com##.ad:remove-class(ghi)\n"
"b.com##div:remove-class(whatever)");

GURL tab_url =
embedded_test_server()->GetURL("b.com", "/cosmetic_filtering.html");
NavigateToURL(tab_url);

content::WebContents* contents = web_contents();

EXPECT_EQ(true, EvalJs(contents, "check('.ghi', existence(false))"));
EXPECT_EQ(true, EvalJs(contents, "check('.ad.jkl', classes(['ad', 'jkl']))"));
}

// Test rules overridden by hostname-specific exception rules
IN_PROC_BROWSER_TEST_F(AdBlockServiceTest, CosmeticFilteringUnhide) {
UpdateAdBlockInstanceWithRules(
Expand Down
119 changes: 119 additions & 0 deletions components/brave_shields/content/test/cosmetic_merge_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ const char EMPTY_RESOURCES[] =
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\", "
"\"generichide\": false"
"}";
Expand All @@ -62,6 +65,15 @@ const char NONEMPTY_RESOURCES[] =
"\"d\": [\"color: #000\"]"
"}, "
"\"exceptions\": [\"e\", \"f\"], "
"\"remove_selectors\": [\"x\", \"y\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"console.log('g')\", "
"\"generichide\": false"
"}";
Expand All @@ -77,6 +89,9 @@ TEST_F(CosmeticResourceMergeTest, MergeTwoEmptyResources) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\n\", "
"\"generichide\": false"
"}";
Expand All @@ -98,6 +113,15 @@ TEST_F(CosmeticResourceMergeTest, MergeEmptyIntoNonEmpty) {
"\"d\": [\"color: #000\"]"
"}, "
"\"exceptions\": [\"e\", \"f\"], "
"\"remove_selectors\": [\"x\", \"y\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"console.log('g')\n\", "
"\"generichide\": false"
"}";
Expand All @@ -119,6 +143,15 @@ TEST_F(CosmeticResourceMergeTest, MergeNonEmptyIntoEmpty) {
"\"d\": [\"color: #000\"]"
"}, "
"\"exceptions\": [\"e\", \"f\"], "
"\"remove_selectors\": [\"x\", \"y\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"\nconsole.log('g')\", "
"\"generichide\": false"
"}";
Expand All @@ -136,6 +169,13 @@ TEST_F(CosmeticResourceMergeTest, MergeNonEmptyIntoNonEmpty) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"l\", \"m\"], "
"\"remove_selectors\": [\"k\"], "
"\"remove_attrs\": {"
"\"s\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"r\": [\"class-six\"]"
"}, "
"\"injected_script\": \"console.log('n')\", "
"\"generichide\": false"
"}";
Expand All @@ -150,6 +190,17 @@ TEST_F(CosmeticResourceMergeTest, MergeNonEmptyIntoNonEmpty) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"e\", \"f\", \"l\", \"m\"], "
"\"remove_selectors\": [\"x\", \"y\", \"k\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"], "
"\"s\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"], "
"\"r\": [\"class-six\"]"
"}, "
"\"injected_script\": \"console.log('g')\nconsole.log('n')\", "
"\"generichide\": false"
"}";
Expand All @@ -168,6 +219,9 @@ TEST_F(CosmeticResourceMergeTest, MergeEmptyForceHide) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\n\","
"\"generichide\": false, "
"\"force_hide_selectors\": []"
Expand All @@ -186,6 +240,9 @@ TEST_F(CosmeticResourceMergeTest, MergeNonEmptyForceHide) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"l\", \"m\"], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"console.log('n')\", "
"\"generichide\": false"
"}";
Expand All @@ -200,6 +257,15 @@ TEST_F(CosmeticResourceMergeTest, MergeNonEmptyForceHide) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"e\", \"f\", \"l\", \"m\"], "
"\"remove_selectors\": [\"x\", \"y\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"console.log('g')\nconsole.log('n')\","
"\"generichide\": false, "
"\"force_hide_selectors\": [\"h\", \"i\"]"
Expand All @@ -214,6 +280,9 @@ TEST_F(CosmeticResourceMergeTest, MergeNonGenerichideIntoGenerichide) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\n\", "
"\"generichide\": true"
"}";
Expand All @@ -224,6 +293,9 @@ TEST_F(CosmeticResourceMergeTest, MergeNonGenerichideIntoGenerichide) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\n\n\", "
"\"generichide\": true"
"}";
Expand All @@ -241,6 +313,9 @@ TEST_F(CosmeticResourceMergeTest, MergeGenerichideIntoNonGenerichide) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"l\", \"m\"], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"console.log('n')\", "
"\"generichide\": true"
"}";
Expand All @@ -255,6 +330,15 @@ TEST_F(CosmeticResourceMergeTest, MergeGenerichideIntoNonGenerichide) {
"\"k\": [\"color: #111\"]"
"}, "
"\"exceptions\": [\"e\", \"f\", \"l\", \"m\"], "
"\"remove_selectors\": [\"x\", \"y\"], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"console.log('g')\nconsole.log('n')\", "
"\"generichide\": true"
"}";
Expand All @@ -268,6 +352,9 @@ TEST_F(CosmeticResourceMergeTest, MergeGenerichideIntoGenerichide) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\", "
"\"generichide\": true"
"}";
Expand All @@ -277,6 +364,9 @@ TEST_F(CosmeticResourceMergeTest, MergeGenerichideIntoGenerichide) {
"\"hide_selectors\": [], "
"\"style_selectors\": {}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {}, "
"\"remove_classes\": {}, "
"\"injected_script\": \"\n\", "
"\"generichide\": true"
"}";
Expand All @@ -294,6 +384,15 @@ TEST_F(CosmeticResourceMergeTest, MergeStyles) {
"\".d\": [\"padding: 0\"]"
"}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\"], "
"\"w\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\"], "
"\"u\": [\"class-three\"]"
"}, "
"\"injected_script\": \"\", "
"\"generichide\": false"
"}";
Expand All @@ -306,6 +405,15 @@ TEST_F(CosmeticResourceMergeTest, MergeStyles) {
"\".a\": [\"background: #fff\"]"
"}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {"
"\"v\": [\"class\", \"data-no\"], "
"\"s\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-four\", \"class-five\"], "
"\"r\": [\"class-six\"]"
"}, "
"\"injected_script\": \"\", "
"\"generichide\": false"
"}";
Expand All @@ -320,6 +428,17 @@ TEST_F(CosmeticResourceMergeTest, MergeStyles) {
"\".d\": [\"padding: 0\"] "
"}, "
"\"exceptions\": [], "
"\"remove_selectors\": [], "
"\"remove_attrs\": {"
"\"v\": [\"href\", \"id\", \"class\", \"data-no\"], "
"\"w\": [\"attr\"], "
"\"s\": [\"attr\"]"
"}, "
"\"remove_classes\": {"
"\"t\": [\"class-one\", \"class-two\", \"class-four\", \"class-five\"], "
"\"u\": [\"class-three\"], "
"\"r\": [\"class-six\"]"
"}, "
"\"injected_script\": \"\n\", "
"\"generichide\": false"
"}";
Expand Down
42 changes: 23 additions & 19 deletions components/brave_shields/core/browser/ad_block_service_helper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,30 +63,34 @@ void MergeResourcesInto(base::Value::Dict from,
}
}

base::Value::Dict* resources_style_selectors =
into.FindDict("style_selectors");
base::Value::Dict* from_resources_style_selectors =
from.FindDict("style_selectors");
if (resources_style_selectors && from_resources_style_selectors) {
for (auto [key, value] : *from_resources_style_selectors) {
base::Value::List* resources_entry =
resources_style_selectors->FindList(key);
if (resources_entry) {
DCHECK(value.is_list());
for (auto& item : value.GetList()) {
resources_entry->Append(std::move(item));
constexpr std::string_view kDictListKeys[] = {
"style_selectors", "remove_classes", "remove_attrs"};
for (const auto& key_ : kDictListKeys) {
base::Value::Dict* resources = into.FindDict(key_);
base::Value::Dict* from_resources = from.FindDict(key_);
if (resources && from_resources) {
for (auto [key, value] : *from_resources) {
base::Value::List* resources_entry = resources->FindList(key);
if (resources_entry) {
DCHECK(value.is_list());
for (auto& item : value.GetList()) {
resources_entry->Append(std::move(item));
}
} else {
resources->Set(key, std::move(value));
}
} else {
resources_style_selectors->Set(key, std::move(value));
}
}
}

base::Value::List* resources_exceptions = into.FindList("exceptions");
base::Value::List* from_resources_exceptions = from.FindList("exceptions");
if (resources_exceptions && from_resources_exceptions) {
for (auto& exception : *from_resources_exceptions) {
resources_exceptions->Append(std::move(exception));
constexpr std::string_view kListKeys[] = {"exceptions", "remove_selectors"};
for (const auto& key_ : kListKeys) {
base::Value::List* resources = into.FindList(key_);
base::Value::List* from_resources = from.FindList(key_);
if (resources && from_resources) {
for (auto& exception : *from_resources) {
resources->Append(std::move(exception));
}
}
}

Expand Down
Loading

0 comments on commit 706f518

Please sign in to comment.