| OLD | NEW |
| 1 /* | 1 /* |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
| 3 * Copyright (C) 2006-present eyeo GmbH | 3 * Copyright (C) 2006-present eyeo GmbH |
| 4 * | 4 * |
| 5 * Adblock Plus is free software: you can redistribute it and/or modify | 5 * Adblock Plus is free software: you can redistribute it and/or modify |
| 6 * it under the terms of the GNU General Public License version 3 as | 6 * it under the terms of the GNU General Public License version 3 as |
| 7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
| 8 * | 8 * |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
| 13 * | 13 * |
| 14 * You should have received a copy of the GNU General Public License | 14 * You should have received a copy of the GNU General Public License |
| 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
| 16 */ | 16 */ |
| 17 | 17 |
| 18 "use strict"; | 18 "use strict"; |
| 19 | 19 |
| 20 const assert = require("assert"); |
| 20 const {createSandbox} = require("./_common"); | 21 const {createSandbox} = require("./_common"); |
| 21 | 22 |
| 22 let Filter = null; | 23 let Filter = null; |
| 23 let InvalidFilter = null; | 24 let InvalidFilter = null; |
| 24 let CommentFilter = null; | 25 let CommentFilter = null; |
| 25 let ActiveFilter = null; | 26 let ActiveFilter = null; |
| 26 let RegExpFilter = null; | 27 let RegExpFilter = null; |
| 27 let BlockingFilter = null; | 28 let BlockingFilter = null; |
| 28 let ContentFilter = null; | 29 let ContentFilter = null; |
| 29 let WhitelistFilter = null; | 30 let WhitelistFilter = null; |
| 30 let ElemHideBase = null; | 31 let ElemHideBase = null; |
| 31 let ElemHideFilter = null; | 32 let ElemHideFilter = null; |
| 32 let ElemHideException = null; | 33 let ElemHideException = null; |
| 33 let ElemHideEmulationFilter = null; | 34 let ElemHideEmulationFilter = null; |
| 34 let SnippetFilter = null; | 35 let SnippetFilter = null; |
| 35 | 36 |
| 36 let t = null; | 37 let t = null; |
| 37 let defaultTypes = null; | 38 let defaultTypes = null; |
| 38 | 39 |
| 39 exports.setUp = function(callback) | 40 describe("Filters Classes", () => |
| 40 { | 41 { |
| 41 let sandboxedRequire = createSandbox(); | 42 beforeEach(() => |
| 42 ( | 43 { |
| 43 {Filter, InvalidFilter, CommentFilter, ActiveFilter, RegExpFilter, | 44 let sandboxedRequire = createSandbox(); |
| 44 BlockingFilter, WhitelistFilter, ContentFilter, ElemHideBase, | 45 ( |
| 45 ElemHideFilter, ElemHideException, ElemHideEmulationFilter, | 46 {Filter, InvalidFilter, CommentFilter, ActiveFilter, RegExpFilter, |
| 46 SnippetFilter} = sandboxedRequire("../lib/filterClasses") | 47 BlockingFilter, WhitelistFilter, ContentFilter, ElemHideBase, |
| 47 ); | 48 ElemHideFilter, ElemHideException, ElemHideEmulationFilter, |
| 48 t = RegExpFilter.typeMap; | 49 SnippetFilter} = sandboxedRequire("../lib/filterClasses") |
| 49 defaultTypes = 0x7FFFFFFF & ~(t.CSP | t.ELEMHIDE | t.DOCUMENT | t.POPUP | | 50 ); |
| 50 t.GENERICHIDE | t.GENERICBLOCK); | 51 t = RegExpFilter.typeMap; |
| 51 | 52 defaultTypes = 0x7FFFFFFF & ~(t.CSP | t.ELEMHIDE | t.DOCUMENT | t.POPUP | |
| 52 callback(); | 53 t.GENERICHIDE | t.GENERICBLOCK); |
| 53 }; | 54 }); |
| 54 | 55 |
| 55 function serializeFilter(filter) | 56 function serializeFilter(filter) |
| 56 { | 57 { |
| 57 // Filter serialization only writes out essential properties, need to do a ful
l serialization here | 58 // Filter serialization only writes out essential properties, need to do a f
ull serialization here |
| 58 let result = []; | 59 let result = []; |
| 59 result.push("text=" + filter.text); | 60 result.push("text=" + filter.text); |
| 60 if (filter instanceof InvalidFilter) | 61 if (filter instanceof InvalidFilter) |
| 61 { | 62 { |
| 62 result.push("type=invalid"); | 63 result.push("type=invalid"); |
| 63 result.push("reason=" + filter.reason); | 64 result.push("reason=" + filter.reason); |
| 65 } |
| 66 else if (filter instanceof CommentFilter) |
| 67 result.push("type=comment"); |
| 68 else if (filter instanceof ActiveFilter) |
| 69 { |
| 70 result.push("disabled=" + filter.disabled); |
| 71 result.push("lastHit=" + filter.lastHit); |
| 72 result.push("hitCount=" + filter.hitCount); |
| 73 |
| 74 let domains = []; |
| 75 if (filter.domains) |
| 76 { |
| 77 for (let [domain, isIncluded] of filter.domains) |
| 78 { |
| 79 if (domain != "") |
| 80 domains.push(isIncluded ? domain : "~" + domain); |
| 81 } |
| 82 } |
| 83 result.push("domains=" + domains.sort().join("|")); |
| 84 |
| 85 if (filter instanceof RegExpFilter) |
| 86 { |
| 87 result.push("regexp=" + (filter.regexp ? filter.regexp.source : null)); |
| 88 result.push("contentType=" + filter.contentType); |
| 89 result.push("matchCase=" + filter.matchCase); |
| 90 |
| 91 let sitekeys = filter.sitekeys || []; |
| 92 result.push("sitekeys=" + sitekeys.slice().sort().join("|")); |
| 93 |
| 94 result.push("thirdParty=" + filter.thirdParty); |
| 95 if (filter instanceof BlockingFilter) |
| 96 { |
| 97 result.push("type=filterlist"); |
| 98 result.push("collapse=" + filter.collapse); |
| 99 result.push("csp=" + filter.csp); |
| 100 result.push("rewrite=" + filter.rewrite); |
| 101 } |
| 102 else if (filter instanceof WhitelistFilter) |
| 103 result.push("type=whitelist"); |
| 104 } |
| 105 else if (filter instanceof ElemHideBase) |
| 106 { |
| 107 if (filter instanceof ElemHideFilter) |
| 108 result.push("type=elemhide"); |
| 109 else if (filter instanceof ElemHideException) |
| 110 result.push("type=elemhideexception"); |
| 111 else if (filter instanceof ElemHideEmulationFilter) |
| 112 result.push("type=elemhideemulation"); |
| 113 |
| 114 result.push("selectorDomains=" + |
| 115 [...filter.domains || []] |
| 116 .filter(([domain, isIncluded]) => isIncluded) |
| 117 .map(([domain]) => domain.toLowerCase())); |
| 118 result.push("selector=" + filter.selector); |
| 119 } |
| 120 else if (filter instanceof SnippetFilter) |
| 121 { |
| 122 result.push("type=snippet"); |
| 123 result.push("scriptDomains=" + |
| 124 [...filter.domains || []] |
| 125 .filter(([domain, isIncluded]) => isIncluded) |
| 126 .map(([domain]) => domain.toLowerCase())); |
| 127 result.push("script=" + filter.script); |
| 128 } |
| 129 } |
| 130 return result; |
| 64 } | 131 } |
| 65 else if (filter instanceof CommentFilter) | 132 |
| 66 result.push("type=comment"); | 133 function addDefaults(expected) |
| 67 else if (filter instanceof ActiveFilter) | 134 { |
| 68 { | 135 let type = null; |
| 69 result.push("disabled=" + filter.disabled); | 136 let hasProperty = {}; |
| 70 result.push("lastHit=" + filter.lastHit); | 137 for (let entry of expected) |
| 71 result.push("hitCount=" + filter.hitCount); | 138 { |
| 72 | 139 if (/^type=(.*)/.test(entry)) |
| 73 let domains = []; | 140 type = RegExp.$1; |
| 74 if (filter.domains) | 141 else if (/^(\w+)/.test(entry)) |
| 75 { | 142 hasProperty[RegExp.$1] = true; |
| 76 for (let [domain, isIncluded] of filter.domains) | 143 } |
| 77 { | 144 |
| 78 if (domain != "") | 145 function addProperty(prop, value) |
| 79 domains.push(isIncluded ? domain : "~" + domain); | 146 { |
| 80 } | 147 if (!(prop in hasProperty)) |
| 81 } | 148 expected.push(prop + "=" + value); |
| 82 result.push("domains=" + domains.sort().join("|")); | 149 } |
| 83 | 150 |
| 84 if (filter instanceof RegExpFilter) | 151 if (type == "whitelist" || type == "filterlist" || type == "elemhide" || |
| 85 { | 152 type == "elemhideexception" || type == "elemhideemulation" || |
| 86 result.push("regexp=" + (filter.regexp ? filter.regexp.source : null)); | 153 type == "snippet") |
| 87 result.push("contentType=" + filter.contentType); | 154 { |
| 88 result.push("matchCase=" + filter.matchCase); | 155 addProperty("disabled", "false"); |
| 89 | 156 addProperty("lastHit", "0"); |
| 90 let sitekeys = filter.sitekeys || []; | 157 addProperty("hitCount", "0"); |
| 91 result.push("sitekeys=" + sitekeys.slice().sort().join("|")); | 158 } |
| 92 | 159 if (type == "whitelist" || type == "filterlist") |
| 93 result.push("thirdParty=" + filter.thirdParty); | 160 { |
| 94 if (filter instanceof BlockingFilter) | 161 addProperty("contentType", 0x7FFFFFFF & ~( |
| 95 { | 162 t.CSP | t.DOCUMENT | t.ELEMHIDE | t.POPUP | t.GENERICHIDE | t.GENERICBLO
CK |
| 96 result.push("type=filterlist"); | 163 )); |
| 97 result.push("collapse=" + filter.collapse); | 164 addProperty("regexp", "null"); |
| 98 result.push("csp=" + filter.csp); | 165 addProperty("matchCase", "false"); |
| 99 result.push("rewrite=" + filter.rewrite); | 166 addProperty("thirdParty", "null"); |
| 100 } | 167 addProperty("domains", ""); |
| 101 else if (filter instanceof WhitelistFilter) | 168 addProperty("sitekeys", ""); |
| 102 result.push("type=whitelist"); | 169 } |
| 103 } | 170 if (type == "filterlist") |
| 104 else if (filter instanceof ElemHideBase) | 171 { |
| 105 { | 172 addProperty("collapse", "null"); |
| 106 if (filter instanceof ElemHideFilter) | 173 addProperty("csp", "null"); |
| 107 result.push("type=elemhide"); | 174 addProperty("rewrite", "null"); |
| 108 else if (filter instanceof ElemHideException) | 175 } |
| 109 result.push("type=elemhideexception"); | 176 if (type == "elemhide" || type == "elemhideexception" || |
| 110 else if (filter instanceof ElemHideEmulationFilter) | 177 type == "elemhideemulation") |
| 111 result.push("type=elemhideemulation"); | 178 { |
| 112 | 179 addProperty("selectorDomains", ""); |
| 113 result.push("selectorDomains=" + | 180 addProperty("domains", ""); |
| 114 [...filter.domains || []] | 181 } |
| 115 .filter(([domain, isIncluded]) => isIncluded) | 182 if (type == "snippet") |
| 116 .map(([domain]) => domain.toLowerCase())); | 183 { |
| 117 result.push("selector=" + filter.selector); | 184 addProperty("scriptDomains", ""); |
| 118 } | 185 addProperty("domains", ""); |
| 119 else if (filter instanceof SnippetFilter) | |
| 120 { | |
| 121 result.push("type=snippet"); | |
| 122 result.push("scriptDomains=" + | |
| 123 [...filter.domains || []] | |
| 124 .filter(([domain, isIncluded]) => isIncluded) | |
| 125 .map(([domain]) => domain.toLowerCase())); | |
| 126 result.push("script=" + filter.script); | |
| 127 } | 186 } |
| 128 } | 187 } |
| 129 return result; | 188 |
| 130 } | 189 function compareFilter(text, expected, postInit) |
| 131 | 190 { |
| 132 function addDefaults(expected) | 191 addDefaults(expected); |
| 133 { | 192 |
| 134 let type = null; | 193 let filter = Filter.fromText(text); |
| 135 let hasProperty = {}; | 194 if (postInit) |
| 136 for (let entry of expected) | 195 postInit(filter); |
| 137 { | 196 let result = serializeFilter(filter); |
| 138 if (/^type=(.*)/.test(entry)) | 197 assert.equal(result.sort().join("\n"), expected.sort().join("\n"), text); |
| 139 type = RegExp.$1; | 198 |
| 140 else if (/^(\w+)/.test(entry)) | 199 // Test round-trip |
| 141 hasProperty[RegExp.$1] = true; | 200 let filter2; |
| 201 let buffer = [...filter.serialize()]; |
| 202 if (buffer.length) |
| 203 { |
| 204 let map = Object.create(null); |
| 205 for (let line of buffer.slice(1)) |
| 206 { |
| 207 if (/(.*?)=(.*)/.test(line)) |
| 208 map[RegExp.$1] = RegExp.$2; |
| 209 } |
| 210 filter2 = Filter.fromObject(map); |
| 211 } |
| 212 else |
| 213 filter2 = Filter.fromText(filter.text); |
| 214 |
| 215 assert.equal(serializeFilter(filter).join("\n"), serializeFilter(filter2).jo
in("\n"), text + " deserialization"); |
| 142 } | 216 } |
| 143 | 217 |
| 144 function addProperty(prop, value) | 218 it("Definitions", () => |
| 145 { | 219 { |
| 146 if (!(prop in hasProperty)) | 220 assert.equal(typeof Filter, "function", "typeof Filter"); |
| 147 expected.push(prop + "=" + value); | 221 assert.equal(typeof InvalidFilter, "function", "typeof InvalidFilter"); |
| 148 } | 222 assert.equal(typeof CommentFilter, "function", "typeof CommentFilter"); |
| 149 | 223 assert.equal(typeof ActiveFilter, "function", "typeof ActiveFilter"); |
| 150 if (type == "whitelist" || type == "filterlist" || type == "elemhide" || | 224 assert.equal(typeof RegExpFilter, "function", "typeof RegExpFilter"); |
| 151 type == "elemhideexception" || type == "elemhideemulation" || | 225 assert.equal(typeof BlockingFilter, "function", "typeof BlockingFilter"); |
| 152 type == "snippet") | 226 assert.equal(typeof ContentFilter, "function", "typeof ContentFilter"); |
| 153 { | 227 assert.equal(typeof WhitelistFilter, "function", "typeof WhitelistFilter"); |
| 154 addProperty("disabled", "false"); | 228 assert.equal(typeof ElemHideBase, "function", "typeof ElemHideBase"); |
| 155 addProperty("lastHit", "0"); | 229 assert.equal(typeof ElemHideFilter, "function", "typeof ElemHideFilter"); |
| 156 addProperty("hitCount", "0"); | 230 assert.equal(typeof ElemHideException, |
| 157 } | 231 "function", "typeof ElemHideException"); |
| 158 if (type == "whitelist" || type == "filterlist") | 232 assert.equal(typeof ElemHideEmulationFilter, "function", |
| 159 { | 233 "typeof ElemHideEmulationFilter"); |
| 160 addProperty("contentType", 0x7FFFFFFF & ~( | 234 assert.equal(typeof SnippetFilter, "function", "typeof SnippetFilter"); |
| 161 t.CSP | t.DOCUMENT | t.ELEMHIDE | t.POPUP | t.GENERICHIDE | t.GENERICBLOCK | 235 }); |
| 162 )); | 236 |
| 163 addProperty("regexp", "null"); | 237 it("Comments", () => |
| 164 addProperty("matchCase", "false"); | 238 { |
| 165 addProperty("thirdParty", "null"); | 239 compareFilter("!asdf", ["type=comment", "text=!asdf"]); |
| 166 addProperty("domains", ""); | 240 compareFilter("!foo#bar", ["type=comment", "text=!foo#bar"]); |
| 167 addProperty("sitekeys", ""); | 241 compareFilter("!foo##bar", ["type=comment", "text=!foo##bar"]); |
| 168 } | 242 }); |
| 169 if (type == "filterlist") | 243 |
| 170 { | 244 it("Invalid Filters", () => |
| 171 addProperty("collapse", "null"); | 245 { |
| 172 addProperty("csp", "null"); | 246 compareFilter("/??/", ["type=invalid", "text=/??/", "reason=filter_invalid_r
egexp"]); |
| 173 addProperty("rewrite", "null"); | 247 compareFilter("asd$foobar", ["type=invalid", "text=asd$foobar", "reason=filt
er_unknown_option"]); |
| 174 } | 248 |
| 175 if (type == "elemhide" || type == "elemhideexception" || | 249 // No $domain or $~third-party |
| 176 type == "elemhideemulation") | 250 compareFilter("||example.com/ad.js$rewrite=abp-resource:noopjs", ["type=inva
lid", "text=||example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter_inv
alid_rewrite"]); |
| 177 { | 251 compareFilter("*example.com/ad.js$rewrite=abp-resource:noopjs", ["type=inval
id", "text=*example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter_inval
id_rewrite"]); |
| 178 addProperty("selectorDomains", ""); | 252 compareFilter("example.com/ad.js$rewrite=abp-resource:noopjs", ["type=invali
d", "text=example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter_invalid
_rewrite"]); |
| 179 addProperty("domains", ""); | 253 // Patterns not starting with || or * |
| 180 } | 254 compareFilter("example.com/ad.js$rewrite=abp-resource:noopjs,domain=foo.com"
, ["type=invalid", "text=example.com/ad.js$rewrite=abp-resource:noopjs,domain=fo
o.com", "reason=filter_invalid_rewrite"]); |
| 181 if (type == "snippet") | 255 compareFilter("example.com/ad.js$rewrite=abp-resource:noopjs,~third-party",
["type=invalid", "text=example.com/ad.js$rewrite=abp-resource:noopjs,~third-part
y", "reason=filter_invalid_rewrite"]); |
| 182 { | 256 // $~third-party requires || |
| 183 addProperty("scriptDomains", ""); | 257 compareFilter("*example.com/ad.js$rewrite=abp-resource:noopjs,~third-party",
["type=invalid", "text=*example.com/ad.js$rewrite=abp-resource:noopjs,~third-pa
rty", "reason=filter_invalid_rewrite"]); |
| 184 addProperty("domains", ""); | 258 |
| 185 } | 259 function checkElemHideEmulationFilterInvalid(domains) |
| 186 } | 260 { |
| 187 | 261 let filterText = domains + "#?#:-abp-properties(abc)"; |
| 188 function compareFilter(test, text, expected, postInit) | 262 compareFilter( |
| 189 { | 263 filterText, [ |
| 190 addDefaults(expected); | 264 "type=invalid", "text=" + filterText, |
| 191 | 265 "reason=filter_elemhideemulation_nodomain" |
| 192 let filter = Filter.fromText(text); | 266 ] |
| 193 if (postInit) | 267 ); |
| 194 postInit(filter); | 268 } |
| 195 let result = serializeFilter(filter); | 269 checkElemHideEmulationFilterInvalid(""); |
| 196 test.equal(result.sort().join("\n"), expected.sort().join("\n"), text); | 270 checkElemHideEmulationFilterInvalid("~foo.com"); |
| 197 | 271 checkElemHideEmulationFilterInvalid("~foo.com,~bar.com"); |
| 198 // Test round-trip | 272 checkElemHideEmulationFilterInvalid("foo"); |
| 199 let filter2; | 273 checkElemHideEmulationFilterInvalid("~foo.com,bar"); |
| 200 let buffer = [...filter.serialize()]; | 274 }); |
| 201 if (buffer.length) | 275 |
| 202 { | 276 it("Filters with State", () => |
| 203 let map = Object.create(null); | 277 { |
| 204 for (let line of buffer.slice(1)) | 278 compareFilter("blabla", ["type=filterlist", "text=blabla"]); |
| 205 { | |
| 206 if (/(.*?)=(.*)/.test(line)) | |
| 207 map[RegExp.$1] = RegExp.$2; | |
| 208 } | |
| 209 filter2 = Filter.fromObject(map); | |
| 210 } | |
| 211 else | |
| 212 filter2 = Filter.fromText(filter.text); | |
| 213 | |
| 214 test.equal(serializeFilter(filter).join("\n"), serializeFilter(filter2).join("
\n"), text + " deserialization"); | |
| 215 } | |
| 216 | |
| 217 exports.testFilterClassDefinitions = function(test) | |
| 218 { | |
| 219 test.equal(typeof Filter, "function", "typeof Filter"); | |
| 220 test.equal(typeof InvalidFilter, "function", "typeof InvalidFilter"); | |
| 221 test.equal(typeof CommentFilter, "function", "typeof CommentFilter"); | |
| 222 test.equal(typeof ActiveFilter, "function", "typeof ActiveFilter"); | |
| 223 test.equal(typeof RegExpFilter, "function", "typeof RegExpFilter"); | |
| 224 test.equal(typeof BlockingFilter, "function", "typeof BlockingFilter"); | |
| 225 test.equal(typeof ContentFilter, "function", "typeof ContentFilter"); | |
| 226 test.equal(typeof WhitelistFilter, "function", "typeof WhitelistFilter"); | |
| 227 test.equal(typeof ElemHideBase, "function", "typeof ElemHideBase"); | |
| 228 test.equal(typeof ElemHideFilter, "function", "typeof ElemHideFilter"); | |
| 229 test.equal(typeof ElemHideException, "function", "typeof ElemHideException"); | |
| 230 test.equal(typeof ElemHideEmulationFilter, "function", | |
| 231 "typeof ElemHideEmulationFilter"); | |
| 232 test.equal(typeof SnippetFilter, "function", "typeof SnippetFilter"); | |
| 233 | |
| 234 test.done(); | |
| 235 }; | |
| 236 | |
| 237 exports.testComments = function(test) | |
| 238 { | |
| 239 compareFilter(test, "!asdf", ["type=comment", "text=!asdf"]); | |
| 240 compareFilter(test, "!foo#bar", ["type=comment", "text=!foo#bar"]); | |
| 241 compareFilter(test, "!foo##bar", ["type=comment", "text=!foo##bar"]); | |
| 242 | |
| 243 test.done(); | |
| 244 }; | |
| 245 | |
| 246 exports.testInvalidFilters = function(test) | |
| 247 { | |
| 248 compareFilter(test, "/??/", ["type=invalid", "text=/??/", "reason=filter_inval
id_regexp"]); | |
| 249 compareFilter(test, "asd$foobar", ["type=invalid", "text=asd$foobar", "reason=
filter_unknown_option"]); | |
| 250 | |
| 251 // No $domain or $~third-party | |
| 252 compareFilter(test, "||example.com/ad.js$rewrite=abp-resource:noopjs", ["type=
invalid", "text=||example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter
_invalid_rewrite"]); | |
| 253 compareFilter(test, "*example.com/ad.js$rewrite=abp-resource:noopjs", ["type=i
nvalid", "text=*example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter_i
nvalid_rewrite"]); | |
| 254 compareFilter(test, "example.com/ad.js$rewrite=abp-resource:noopjs", ["type=in
valid", "text=example.com/ad.js$rewrite=abp-resource:noopjs", "reason=filter_inv
alid_rewrite"]); | |
| 255 // Patterns not starting with || or * | |
| 256 compareFilter(test, "example.com/ad.js$rewrite=abp-resource:noopjs,domain=foo.
com", ["type=invalid", "text=example.com/ad.js$rewrite=abp-resource:noopjs,domai
n=foo.com", "reason=filter_invalid_rewrite"]); | |
| 257 compareFilter(test, "example.com/ad.js$rewrite=abp-resource:noopjs,~third-part
y", ["type=invalid", "text=example.com/ad.js$rewrite=abp-resource:noopjs,~third-
party", "reason=filter_invalid_rewrite"]); | |
| 258 // $~third-party requires || | |
| 259 compareFilter(test, "*example.com/ad.js$rewrite=abp-resource:noopjs,~third-par
ty", ["type=invalid", "text=*example.com/ad.js$rewrite=abp-resource:noopjs,~thir
d-party", "reason=filter_invalid_rewrite"]); | |
| 260 | |
| 261 function checkElemHideEmulationFilterInvalid(domains) | |
| 262 { | |
| 263 let filterText = domains + "#?#:-abp-properties(abc)"; | |
| 264 compareFilter( | 279 compareFilter( |
| 265 test, filterText, [ | 280 "blabla_default", ["type=filterlist", "text=blabla_default"], |
| 266 "type=invalid", "text=" + filterText, | 281 filter => |
| 267 "reason=filter_elemhideemulation_nodomain" | 282 { |
| 283 filter.disabled = false; |
| 284 filter.hitCount = 0; |
| 285 filter.lastHit = 0; |
| 286 } |
| 287 ); |
| 288 compareFilter( |
| 289 "blabla_non_default", |
| 290 ["type=filterlist", "text=blabla_non_default", "disabled=true", "hitCount=
12", "lastHit=20"], |
| 291 filter => |
| 292 { |
| 293 filter.disabled = true; |
| 294 filter.hitCount = 12; |
| 295 filter.lastHit = 20; |
| 296 } |
| 297 ); |
| 298 }); |
| 299 |
| 300 it("Special Characters", () => |
| 301 { |
| 302 compareFilter("/ddd|f?a[s]d/", ["type=filterlist", "text=/ddd|f?a[s]d/", "re
gexp=ddd|f?a[s]d"]); |
| 303 compareFilter("*asdf*d**dd*", ["type=filterlist", "text=*asdf*d**dd*", "rege
xp=asdf.*d.*dd"]); |
| 304 compareFilter("|*asd|f*d**dd*|", ["type=filterlist", "text=|*asd|f*d**dd*|",
"regexp=^.*asd\\|f.*d.*dd.*$"]); |
| 305 compareFilter("dd[]{}$%<>&()*d", ["type=filterlist", "text=dd[]{}$%<>&()*d",
"regexp=dd\\[\\]\\{\\}\\$\\%\\<\\>\\&\\(\\).*d"]); |
| 306 |
| 307 // Leading and trailing wildcards should be left in for rewrite filters (#68
68). |
| 308 compareFilter("*asdf*d**dd*$rewrite=", ["type=filterlist", "text=*asdf*d**dd
*$rewrite=", "regexp=.*asdf.*d.*dd.*", "rewrite=", "contentType=" + (defaultType
s & ~(t.SCRIPT | t.SUBDOCUMENT | t.OBJECT | t.OBJECT_SUBREQUEST))]); |
| 309 |
| 310 compareFilter("@@/ddd|f?a[s]d/", ["type=whitelist", "text=@@/ddd|f?a[s]d/",
"regexp=ddd|f?a[s]d", "contentType=" + defaultTypes]); |
| 311 compareFilter("@@*asdf*d**dd*", ["type=whitelist", "text=@@*asdf*d**dd*", "r
egexp=asdf.*d.*dd", "contentType=" + defaultTypes]); |
| 312 compareFilter("@@|*asd|f*d**dd*|", ["type=whitelist", "text=@@|*asd|f*d**dd*
|", "regexp=^.*asd\\|f.*d.*dd.*$", "contentType=" + defaultTypes]); |
| 313 compareFilter("@@dd[]{}$%<>&()*d", ["type=whitelist", "text=@@dd[]{}$%<>&()*
d", "regexp=dd\\[\\]\\{\\}\\$\\%\\<\\>\\&\\(\\).*d", "contentType=" + defaultTyp
es]); |
| 314 }); |
| 315 |
| 316 it("Filter Options", () => |
| 317 { |
| 318 compareFilter("bla$match-case,csp=first csp,script,other,third-party,domain=
FOO.cOm,sitekey=foo", ["type=filterlist", "text=bla$match-case,csp=first csp,scr
ipt,other,third-party,domain=FOO.cOm,sitekey=foo", "matchCase=true", "contentTyp
e=" + (t.SCRIPT | t.OTHER | t.CSP), "thirdParty=true", "domains=foo.com", "sitek
eys=FOO", "csp=first csp"]); |
| 319 compareFilter("bla$~match-case,~csp=csp,~script,~other,~third-party,domain=~
bAr.coM", ["type=filterlist", "text=bla$~match-case,~csp=csp,~script,~other,~thi
rd-party,domain=~bAr.coM", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHER
)), "thirdParty=false", "domains=~bar.com"]); |
| 320 compareFilter("@@bla$match-case,script,other,third-party,domain=foo.com|bar.
com|~bAR.foO.Com|~Foo.Bar.com,csp=c s p,sitekey=foo|bar", ["type=whitelist", "te
xt=@@bla$match-case,script,other,third-party,domain=foo.com|bar.com|~bAR.foO.Com
|~Foo.Bar.com,csp=c s p,sitekey=foo|bar", "matchCase=true", "contentType=" + (t.
SCRIPT | t.OTHER | t.CSP), "thirdParty=true", "domains=bar.com|foo.com|~bar.foo.
com|~foo.bar.com", "sitekeys=BAR|FOO"]); |
| 321 compareFilter("@@bla$match-case,script,other,third-party,domain=foo.com|bar.
com|~bar.foo.com|~foo.bar.com,sitekey=foo|bar", ["type=whitelist", "text=@@bla$m
atch-case,script,other,third-party,domain=foo.com|bar.com|~bar.foo.com|~foo.bar.
com,sitekey=foo|bar", "matchCase=true", "contentType=" + (t.SCRIPT | t.OTHER), "
thirdParty=true", "domains=bar.com|foo.com|~bar.foo.com|~foo.bar.com", "sitekeys
=BAR|FOO"]); |
| 322 compareFilter("||content.server.com/files/*.php$rewrite=$1", ["type=filterli
st", "text=||content.server.com/files/*.php$rewrite=$1", "regexp=^[\\w\\-]+:\\/+
(?!\\/)(?:[^\\/]+\\.)?content\\.server\\.com\\/files\\/.*\\.php", "matchCase=fal
se", "rewrite=$1", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.SUBDOCUMENT |
t.OBJECT | t.OBJECT_SUBREQUEST))]); |
| 323 |
| 324 compareFilter("||example.com/ad.js$rewrite=abp-resource:noopjs,domain=foo.co
m|bar.com", ["type=filterlist", "text=||example.com/ad.js$rewrite=abp-resource:n
oopjs,domain=foo.com|bar.com", "regexp=null", "matchCase=false", "rewrite=abp-re
source:noopjs", "contentType=" + (defaultTypes), "domains=bar.com|foo.com"]); |
| 325 compareFilter("*example.com/ad.js$rewrite=abp-resource:noopjs,domain=foo.com
|bar.com", ["type=filterlist", "text=*example.com/ad.js$rewrite=abp-resource:noo
pjs,domain=foo.com|bar.com", "regexp=null", "matchCase=false", "rewrite=abp-reso
urce:noopjs", "contentType=" + (defaultTypes), "domains=bar.com|foo.com"]); |
| 326 compareFilter("||example.com/ad.js$rewrite=abp-resource:noopjs,~third-party"
, ["type=filterlist", "text=||example.com/ad.js$rewrite=abp-resource:noopjs,~thi
rd-party", "regexp=null", "matchCase=false", "rewrite=abp-resource:noopjs", "thi
rdParty=false", "contentType=" + (defaultTypes)]); |
| 327 |
| 328 // background and image should be the same for backwards compatibility |
| 329 compareFilter("bla$image", ["type=filterlist", "text=bla$image", "contentTyp
e=" + (t.IMAGE)]); |
| 330 compareFilter("bla$background", ["type=filterlist", "text=bla$background", "
contentType=" + (t.IMAGE)]); |
| 331 compareFilter("bla$~image", ["type=filterlist", "text=bla$~image", "contentT
ype=" + (defaultTypes & ~t.IMAGE)]); |
| 332 compareFilter("bla$~background", ["type=filterlist", "text=bla$~background",
"contentType=" + (defaultTypes & ~t.IMAGE)]); |
| 333 |
| 334 compareFilter("@@bla$~script,~other", ["type=whitelist", "text=@@bla$~script
,~other", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHER))]); |
| 335 compareFilter("@@http://bla$~script,~other", ["type=whitelist", "text=@@http
://bla$~script,~other", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHER))]
); |
| 336 compareFilter("@@|ftp://bla$~script,~other", ["type=whitelist", "text=@@|ftp
://bla$~script,~other", "regexp=^ftp\\:\\/\\/bla", "contentType=" + (defaultType
s & ~(t.SCRIPT | t.OTHER))]); |
| 337 compareFilter("@@bla$~script,~other,document", ["type=whitelist", "text=@@bl
a$~script,~other,document", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHE
R) | t.DOCUMENT)]); |
| 338 compareFilter("@@bla$~script,~other,~document", ["type=whitelist", "text=@@b
la$~script,~other,~document", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OT
HER))]); |
| 339 compareFilter("@@bla$document", ["type=whitelist", "text=@@bla$document", "c
ontentType=" + t.DOCUMENT]); |
| 340 compareFilter("@@bla$~script,~other,elemhide", ["type=whitelist", "text=@@bl
a$~script,~other,elemhide", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHE
R) | t.ELEMHIDE)]); |
| 341 compareFilter("@@bla$~script,~other,~elemhide", ["type=whitelist", "text=@@b
la$~script,~other,~elemhide", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OT
HER))]); |
| 342 compareFilter("@@bla$elemhide", ["type=whitelist", "text=@@bla$elemhide", "c
ontentType=" + t.ELEMHIDE]); |
| 343 |
| 344 compareFilter("@@bla$~script,~other,donottrack", ["type=invalid", "text=@@bl
a$~script,~other,donottrack", "reason=filter_unknown_option"]); |
| 345 compareFilter("@@bla$~script,~other,~donottrack", ["type=invalid", "text=@@b
la$~script,~other,~donottrack", "reason=filter_unknown_option"]); |
| 346 compareFilter("@@bla$donottrack", ["type=invalid", "text=@@bla$donottrack",
"reason=filter_unknown_option"]); |
| 347 compareFilter("@@bla$foobar", ["type=invalid", "text=@@bla$foobar", "reason=
filter_unknown_option"]); |
| 348 compareFilter("@@bla$image,foobar", ["type=invalid", "text=@@bla$image,fooba
r", "reason=filter_unknown_option"]); |
| 349 compareFilter("@@bla$foobar,image", ["type=invalid", "text=@@bla$foobar,imag
e", "reason=filter_unknown_option"]); |
| 350 |
| 351 compareFilter("bla$csp", ["type=invalid", "text=bla$csp", "reason=filter_inv
alid_csp"]); |
| 352 compareFilter("bla$csp=", ["type=invalid", "text=bla$csp=", "reason=filter_i
nvalid_csp"]); |
| 353 |
| 354 // Blank CSP values are allowed for whitelist filters. |
| 355 compareFilter("@@bla$csp", ["type=whitelist", "text=@@bla$csp", "contentType
=" + t.CSP]); |
| 356 compareFilter("@@bla$csp=", ["type=whitelist", "text=@@bla$csp=", "contentTy
pe=" + t.CSP]); |
| 357 |
| 358 compareFilter("bla$csp=report-uri", ["type=invalid", "text=bla$csp=report-ur
i", "reason=filter_invalid_csp"]); |
| 359 compareFilter("bla$csp=foo,csp=report-to", ["type=invalid", "text=bla$csp=fo
o,csp=report-to", "reason=filter_invalid_csp"]); |
| 360 compareFilter("bla$csp=foo,csp=referrer foo", ["type=invalid", "text=bla$csp
=foo,csp=referrer foo", "reason=filter_invalid_csp"]); |
| 361 compareFilter("bla$csp=foo,csp=base-uri", ["type=invalid", "text=bla$csp=foo
,csp=base-uri", "reason=filter_invalid_csp"]); |
| 362 compareFilter("bla$csp=foo,csp=upgrade-insecure-requests", ["type=invalid",
"text=bla$csp=foo,csp=upgrade-insecure-requests", "reason=filter_invalid_csp"]); |
| 363 compareFilter("bla$csp=foo,csp=ReFeRReR", ["type=invalid", "text=bla$csp=foo
,csp=ReFeRReR", "reason=filter_invalid_csp"]); |
| 364 }); |
| 365 |
| 366 it("Element Hiding Rules", () => |
| 367 { |
| 368 compareFilter("##ddd", ["type=elemhide", "text=##ddd", "selector=ddd"]); |
| 369 compareFilter("##body > div:first-child", ["type=elemhide", "text=##body > d
iv:first-child", "selector=body > div:first-child"]); |
| 370 compareFilter("fOO##ddd", ["type=elemhide", "text=fOO##ddd", "selectorDomain
s=foo", "selector=ddd", "domains=foo"]); |
| 371 compareFilter("Foo,bAr##ddd", ["type=elemhide", "text=Foo,bAr##ddd", "select
orDomains=foo,bar", "selector=ddd", "domains=bar|foo"]); |
| 372 compareFilter("foo,~baR##ddd", ["type=elemhide", "text=foo,~baR##ddd", "sele
ctorDomains=foo", "selector=ddd", "domains=foo|~bar"]); |
| 373 compareFilter("foo,~baz,bar##ddd", ["type=elemhide", "text=foo,~baz,bar##ddd
", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo|~baz"]); |
| 374 }); |
| 375 |
| 376 it("Element Hiding Exceptions", () => |
| 377 { |
| 378 compareFilter("#@#ddd", ["type=elemhideexception", "text=#@#ddd", "selector=
ddd"]); |
| 379 compareFilter("#@#body > div:first-child", ["type=elemhideexception", "text=
#@#body > div:first-child", "selector=body > div:first-child"]); |
| 380 compareFilter("fOO#@#ddd", ["type=elemhideexception", "text=fOO#@#ddd", "sel
ectorDomains=foo", "selector=ddd", "domains=foo"]); |
| 381 compareFilter("Foo,bAr#@#ddd", ["type=elemhideexception", "text=Foo,bAr#@#dd
d", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo"]); |
| 382 compareFilter("foo,~baR#@#ddd", ["type=elemhideexception", "text=foo,~baR#@#
ddd", "selectorDomains=foo", "selector=ddd", "domains=foo|~bar"]); |
| 383 compareFilter("foo,~baz,bar#@#ddd", ["type=elemhideexception", "text=foo,~ba
z,bar#@#ddd", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo|~baz"]
); |
| 384 }); |
| 385 |
| 386 it("Element Hiding Emulation Filters", () => |
| 387 { |
| 388 // Check valid domain combinations |
| 389 compareFilter("fOO.cOm#?#:-abp-properties(abc)", ["type=elemhideemulation",
"text=fOO.cOm#?#:-abp-properties(abc)", "selectorDomains=foo.com", "selector=:-a
bp-properties(abc)", "domains=foo.com"]); |
| 390 compareFilter("Foo.com,~bAr.com#?#:-abp-properties(abc)", ["type=elemhideemu
lation", "text=Foo.com,~bAr.com#?#:-abp-properties(abc)", "selectorDomains=foo.c
om", "selector=:-abp-properties(abc)", "domains=foo.com|~bar.com"]); |
| 391 compareFilter("foo.com,~baR#?#:-abp-properties(abc)", ["type=elemhideemulati
on", "text=foo.com,~baR#?#:-abp-properties(abc)", "selectorDomains=foo.com", "se
lector=:-abp-properties(abc)", "domains=foo.com|~bar"]); |
| 392 compareFilter("~foo.com,bar.com#?#:-abp-properties(abc)", ["type=elemhideemu
lation", "text=~foo.com,bar.com#?#:-abp-properties(abc)", "selectorDomains=bar.c
om", "selector=:-abp-properties(abc)", "domains=bar.com|~foo.com"]); |
| 393 |
| 394 // Check some special cases |
| 395 compareFilter("#?#:-abp-properties(abc)", ["type=invalid", "text=#?#:-abp-pr
operties(abc)", "reason=filter_elemhideemulation_nodomain"]); |
| 396 compareFilter("foo.com#?#abc", ["type=elemhideemulation", "text=foo.com#?#ab
c", "selectorDomains=foo.com", "selector=abc", "domains=foo.com"]); |
| 397 compareFilter("foo.com#?#:-abp-foobar(abc)", ["type=elemhideemulation", "tex
t=foo.com#?#:-abp-foobar(abc)", "selectorDomains=foo.com", "selector=:-abp-fooba
r(abc)", "domains=foo.com"]); |
| 398 compareFilter("foo.com#?#aaa :-abp-properties(abc) bbb", ["type=elemhideemul
ation", "text=foo.com#?#aaa :-abp-properties(abc) bbb", "selectorDomains=foo.com
", "selector=aaa :-abp-properties(abc) bbb", "domains=foo.com"]); |
| 399 compareFilter("foo.com#?#:-abp-properties(|background-image: url(data:*))",
["type=elemhideemulation", "text=foo.com#?#:-abp-properties(|background-image: u
rl(data:*))", "selectorDomains=foo.com", "selector=:-abp-properties(|background-
image: url(data:*))", "domains=foo.com"]); |
| 400 |
| 401 // Support element hiding emulation filters for localhost (#6931). |
| 402 compareFilter("localhost#?#:-abp-properties(abc)", ["type=elemhideemulation"
, "text=localhost#?#:-abp-properties(abc)", "selectorDomains=localhost", "select
or=:-abp-properties(abc)", "domains=localhost"]); |
| 403 compareFilter("localhost,~www.localhost#?#:-abp-properties(abc)", ["type=ele
mhideemulation", "text=localhost,~www.localhost#?#:-abp-properties(abc)", "selec
torDomains=localhost", "selector=:-abp-properties(abc)", "domains=localhost|~www
.localhost"]); |
| 404 compareFilter("~www.localhost,localhost#?#:-abp-properties(abc)", ["type=ele
mhideemulation", "text=~www.localhost,localhost#?#:-abp-properties(abc)", "selec
torDomains=localhost", "selector=:-abp-properties(abc)", "domains=localhost|~www
.localhost"]); |
| 405 }); |
| 406 |
| 407 it("Empty ElemeHide domains", () => |
| 408 { |
| 409 let emptyDomainFilters = [ |
| 410 ",##selector", ",,,##selector", "~,foo.com##selector", "foo.com,##selector
", |
| 411 ",foo.com##selector", "foo.com,~##selector", |
| 412 "foo.com,,bar.com##selector", "foo.com,~,bar.com##selector" |
| 413 ]; |
| 414 |
| 415 for (let filterText of emptyDomainFilters) |
| 416 { |
| 417 let filter = Filter.fromText(filterText); |
| 418 assert.ok(filter instanceof InvalidFilter); |
| 419 assert.equal(filter.reason, "filter_invalid_domain"); |
| 420 } |
| 421 }); |
| 422 |
| 423 it("ElemHide rules with braces", () => |
| 424 { |
| 425 compareFilter( |
| 426 "###foo{color: red}", [ |
| 427 "type=elemhide", |
| 428 "text=###foo{color: red}", |
| 429 "selectorDomains=", |
| 430 "selector=#foo{color: red}", |
| 431 "domains=" |
| 268 ] | 432 ] |
| 269 ); | 433 ); |
| 270 } | 434 compareFilter( |
| 271 checkElemHideEmulationFilterInvalid(""); | 435 "foo.com#?#:-abp-properties(/margin: [3-4]{2}/)", [ |
| 272 checkElemHideEmulationFilterInvalid("~foo.com"); | 436 "type=elemhideemulation", |
| 273 checkElemHideEmulationFilterInvalid("~foo.com,~bar.com"); | 437 "text=foo.com#?#:-abp-properties(/margin: [3-4]{2}/)", |
| 274 checkElemHideEmulationFilterInvalid("foo"); | 438 "selectorDomains=foo.com", |
| 275 checkElemHideEmulationFilterInvalid("~foo.com,bar"); | 439 "selector=:-abp-properties(/margin: [3-4]{2}/)", |
| 276 | 440 "domains=foo.com" |
| 277 test.done(); | 441 ] |
| 278 }; | 442 ); |
| 279 | 443 }); |
| 280 exports.testFiltersWithState = function(test) | 444 |
| 281 { | 445 it("Snippet Filters", () => |
| 282 compareFilter(test, "blabla", ["type=filterlist", "text=blabla"]); | 446 { |
| 283 compareFilter( | 447 compareFilter("foo.com#$#abc", ["type=snippet", "text=foo.com#$#abc", "scrip
tDomains=foo.com", "script=abc", "domains=foo.com"]); |
| 284 test, "blabla_default", ["type=filterlist", "text=blabla_default"], | 448 compareFilter("foo.com,~bar.com#$#abc", ["type=snippet", "text=foo.com,~bar.
com#$#abc", "scriptDomains=foo.com", "script=abc", "domains=foo.com|~bar.com"]); |
| 285 filter => | 449 compareFilter("foo.com,~bar#$#abc", ["type=snippet", "text=foo.com,~bar#$#ab
c", "scriptDomains=foo.com", "script=abc", "domains=foo.com|~bar"]); |
| 286 { | 450 compareFilter("~foo.com,bar.com#$#abc", ["type=snippet", "text=~foo.com,bar.
com#$#abc", "scriptDomains=bar.com", "script=abc", "domains=bar.com|~foo.com"]); |
| 287 filter.disabled = false; | 451 }); |
| 288 filter.hitCount = 0; | 452 |
| 289 filter.lastHit = 0; | 453 it("Filter normalization", () => |
| 290 } | 454 { |
| 291 ); | 455 // Line breaks etc |
| 292 compareFilter( | 456 assert.equal(Filter.normalize("\n\t\nad\ns"), |
| 293 test, "blabla_non_default", | 457 "ads"); |
| 294 ["type=filterlist", "text=blabla_non_default", "disabled=true", "hitCount=12
", "lastHit=20"], | 458 |
| 295 filter => | 459 // Comment filters |
| 296 { | 460 assert.equal(Filter.normalize(" ! fo o## bar "), |
| 297 filter.disabled = true; | 461 "! fo o## bar"); |
| 298 filter.hitCount = 12; | 462 |
| 299 filter.lastHit = 20; | 463 // Element hiding filters |
| 300 } | 464 assert.equal(Filter.normalize(" domain.c om## # sele ctor "), |
| 301 ); | 465 "domain.com### sele ctor"); |
| 302 | 466 |
| 303 test.done(); | 467 // Element hiding emulation filters |
| 304 }; | 468 assert.equal(Filter.normalize(" domain.c om#?# # sele ctor "), |
| 305 | 469 "domain.com#?## sele ctor"); |
| 306 exports.testSpecialCharacters = function(test) | 470 |
| 307 { | 471 // Incorrect syntax: the separator "#?#" cannot contain spaces; treated as a |
| 308 compareFilter(test, "/ddd|f?a[s]d/", ["type=filterlist", "text=/ddd|f?a[s]d/",
"regexp=ddd|f?a[s]d"]); | 472 // regular filter instead |
| 309 compareFilter(test, "*asdf*d**dd*", ["type=filterlist", "text=*asdf*d**dd*", "
regexp=asdf.*d.*dd"]); | 473 assert.equal(Filter.normalize(" domain.c om# ?#. sele ctor "), |
| 310 compareFilter(test, "|*asd|f*d**dd*|", ["type=filterlist", "text=|*asd|f*d**dd
*|", "regexp=^.*asd\\|f.*d.*dd.*$"]); | 474 "domain.com#?#.selector"); |
| 311 compareFilter(test, "dd[]{}$%<>&()*d", ["type=filterlist", "text=dd[]{}$%<>&()
*d", "regexp=dd\\[\\]\\{\\}\\$\\%\\<\\>\\&\\(\\).*d"]); | 475 // Incorrect syntax: the separator "#?#" cannot contain spaces; treated as a
n |
| 312 | 476 // element hiding filter instead, because the "##" following the "?" is take
n |
| 313 // Leading and trailing wildcards should be left in for rewrite filters (#6868
). | 477 // to be the separator instead |
| 314 compareFilter(test, "*asdf*d**dd*$rewrite=", ["type=filterlist", "text=*asdf*d
**dd*$rewrite=", "regexp=.*asdf.*d.*dd.*", "rewrite=", "contentType=" + (default
Types & ~(t.SCRIPT | t.SUBDOCUMENT | t.OBJECT | t.OBJECT_SUBREQUEST))]); | 478 assert.equal(Filter.normalize(" domain.c om# ?##sele ctor "), |
| 315 | 479 "domain.com#?##sele ctor"); |
| 316 compareFilter(test, "@@/ddd|f?a[s]d/", ["type=whitelist", "text=@@/ddd|f?a[s]d
/", "regexp=ddd|f?a[s]d", "contentType=" + defaultTypes]); | 480 |
| 317 compareFilter(test, "@@*asdf*d**dd*", ["type=whitelist", "text=@@*asdf*d**dd*"
, "regexp=asdf.*d.*dd", "contentType=" + defaultTypes]); | 481 // Element hiding exception filters |
| 318 compareFilter(test, "@@|*asd|f*d**dd*|", ["type=whitelist", "text=@@|*asd|f*d*
*dd*|", "regexp=^.*asd\\|f.*d.*dd.*$", "contentType=" + defaultTypes]); | 482 assert.equal(Filter.normalize(" domain.c om#@# # sele ctor "), |
| 319 compareFilter(test, "@@dd[]{}$%<>&()*d", ["type=whitelist", "text=@@dd[]{}$%<>
&()*d", "regexp=dd\\[\\]\\{\\}\\$\\%\\<\\>\\&\\(\\).*d", "contentType=" + defaul
tTypes]); | 483 "domain.com#@## sele ctor"); |
| 320 | 484 |
| 321 test.done(); | 485 // Incorrect syntax: the separator "#@#" cannot contain spaces; treated as a |
| 322 }; | 486 // regular filter instead (not an element hiding filter either!), because |
| 323 | 487 // unlike the case with "# ?##" the "##" following the "@" is not considered |
| 324 exports.testFilterOptions = function(test) | 488 // to be a separator |
| 325 { | 489 assert.equal(Filter.normalize(" domain.c om# @## sele ctor "), |
| 326 compareFilter(test, "bla$match-case,csp=first csp,script,other,third-party,dom
ain=FOO.cOm,sitekey=foo", ["type=filterlist", "text=bla$match-case,csp=first csp
,script,other,third-party,domain=FOO.cOm,sitekey=foo", "matchCase=true", "conten
tType=" + (t.SCRIPT | t.OTHER | t.CSP), "thirdParty=true", "domains=foo.com", "s
itekeys=FOO", "csp=first csp"]); | 490 "domain.com#@##selector"); |
| 327 compareFilter(test, "bla$~match-case,~csp=csp,~script,~other,~third-party,doma
in=~bAr.coM", ["type=filterlist", "text=bla$~match-case,~csp=csp,~script,~other,
~third-party,domain=~bAr.coM", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.O
THER)), "thirdParty=false", "domains=~bar.com"]); | 491 |
| 328 compareFilter(test, "@@bla$match-case,script,other,third-party,domain=foo.com|
bar.com|~bAR.foO.Com|~Foo.Bar.com,csp=c s p,sitekey=foo|bar", ["type=whitelist",
"text=@@bla$match-case,script,other,third-party,domain=foo.com|bar.com|~bAR.foO
.Com|~Foo.Bar.com,csp=c s p,sitekey=foo|bar", "matchCase=true", "contentType=" +
(t.SCRIPT | t.OTHER | t.CSP), "thirdParty=true", "domains=bar.com|foo.com|~bar.
foo.com|~foo.bar.com", "sitekeys=BAR|FOO"]); | 492 // Snippet filters |
| 329 compareFilter(test, "@@bla$match-case,script,other,third-party,domain=foo.com|
bar.com|~bar.foo.com|~foo.bar.com,sitekey=foo|bar", ["type=whitelist", "text=@@b
la$match-case,script,other,third-party,domain=foo.com|bar.com|~bar.foo.com|~foo.
bar.com,sitekey=foo|bar", "matchCase=true", "contentType=" + (t.SCRIPT | t.OTHER
), "thirdParty=true", "domains=bar.com|foo.com|~bar.foo.com|~foo.bar.com", "site
keys=BAR|FOO"]); | 493 assert.equal(Filter.normalize(" domain.c om#$# sni pp et "), |
| 330 compareFilter(test, "||content.server.com/files/*.php$rewrite=$1", ["type=filt
erlist", "text=||content.server.com/files/*.php$rewrite=$1", "regexp=^[\\w\\-]+:
\\/+(?!\\/)(?:[^\\/]+\\.)?content\\.server\\.com\\/files\\/.*\\.php", "matchCase
=false", "rewrite=$1", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.SUBDOCUME
NT | t.OBJECT | t.OBJECT_SUBREQUEST))]); | 494 "domain.com#$#sni pp et"); |
| 331 | 495 |
| 332 compareFilter(test, "||example.com/ad.js$rewrite=abp-resource:noopjs,domain=fo
o.com|bar.com", ["type=filterlist", "text=||example.com/ad.js$rewrite=abp-resour
ce:noopjs,domain=foo.com|bar.com", "regexp=null", "matchCase=false", "rewrite=ab
p-resource:noopjs", "contentType=" + (defaultTypes), "domains=bar.com|foo.com"])
; | 496 // Regular filters |
| 333 compareFilter(test, "*example.com/ad.js$rewrite=abp-resource:noopjs,domain=foo
.com|bar.com", ["type=filterlist", "text=*example.com/ad.js$rewrite=abp-resource
:noopjs,domain=foo.com|bar.com", "regexp=null", "matchCase=false", "rewrite=abp-
resource:noopjs", "contentType=" + (defaultTypes), "domains=bar.com|foo.com"]); | 497 let normalized = Filter.normalize( |
| 334 compareFilter(test, "||example.com/ad.js$rewrite=abp-resource:noopjs,~third-pa
rty", ["type=filterlist", "text=||example.com/ad.js$rewrite=abp-resource:noopjs,
~third-party", "regexp=null", "matchCase=false", "rewrite=abp-resource:noopjs",
"thirdParty=false", "contentType=" + (defaultTypes)]); | 498 " b$l a$sitekey= foo ,domain= do main.com |foo .com,c sp= c s p
" |
| 335 | 499 ); |
| 336 // background and image should be the same for backwards compatibility | 500 assert.equal( |
| 337 compareFilter(test, "bla$image", ["type=filterlist", "text=bla$image", "conten
tType=" + (t.IMAGE)]); | 501 normalized, |
| 338 compareFilter(test, "bla$background", ["type=filterlist", "text=bla$background
", "contentType=" + (t.IMAGE)]); | 502 "b$la$sitekey=foo,domain=domain.com|foo.com,csp=c s p" |
| 339 compareFilter(test, "bla$~image", ["type=filterlist", "text=bla$~image", "cont
entType=" + (defaultTypes & ~t.IMAGE)]); | 503 ); |
| 340 compareFilter(test, "bla$~background", ["type=filterlist", "text=bla$~backgrou
nd", "contentType=" + (defaultTypes & ~t.IMAGE)]); | 504 compareFilter( |
| 341 | 505 normalized, [ |
| 342 compareFilter(test, "@@bla$~script,~other", ["type=whitelist", "text=@@bla$~sc
ript,~other", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHER))]); | 506 "type=filterlist", |
| 343 compareFilter(test, "@@http://bla$~script,~other", ["type=whitelist", "text=@@
http://bla$~script,~other", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.OTHE
R))]); | 507 "text=" + normalized, |
| 344 compareFilter(test, "@@|ftp://bla$~script,~other", ["type=whitelist", "text=@@
|ftp://bla$~script,~other", "regexp=^ftp\\:\\/\\/bla", "contentType=" + (default
Types & ~(t.SCRIPT | t.OTHER))]); | 508 "csp=c s p", |
| 345 compareFilter(test, "@@bla$~script,~other,document", ["type=whitelist", "text=
@@bla$~script,~other,document", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.
OTHER) | t.DOCUMENT)]); | 509 "domains=domain.com|foo.com", |
| 346 compareFilter(test, "@@bla$~script,~other,~document", ["type=whitelist", "text
=@@bla$~script,~other,~document", "contentType=" + (defaultTypes & ~(t.SCRIPT |
t.OTHER))]); | 510 "sitekeys=FOO", |
| 347 compareFilter(test, "@@bla$document", ["type=whitelist", "text=@@bla$document"
, "contentType=" + t.DOCUMENT]); | 511 "contentType=" + t.CSP |
| 348 compareFilter(test, "@@bla$~script,~other,elemhide", ["type=whitelist", "text=
@@bla$~script,~other,elemhide", "contentType=" + (defaultTypes & ~(t.SCRIPT | t.
OTHER) | t.ELEMHIDE)]); | 512 ] |
| 349 compareFilter(test, "@@bla$~script,~other,~elemhide", ["type=whitelist", "text
=@@bla$~script,~other,~elemhide", "contentType=" + (defaultTypes & ~(t.SCRIPT |
t.OTHER))]); | 513 ); |
| 350 compareFilter(test, "@@bla$elemhide", ["type=whitelist", "text=@@bla$elemhide"
, "contentType=" + t.ELEMHIDE]); | 514 |
| 351 | 515 // Some $csp edge cases |
| 352 compareFilter(test, "@@bla$~script,~other,donottrack", ["type=invalid", "text=
@@bla$~script,~other,donottrack", "reason=filter_unknown_option"]); | 516 assert.equal(Filter.normalize("$csp= "), |
| 353 compareFilter(test, "@@bla$~script,~other,~donottrack", ["type=invalid", "text
=@@bla$~script,~other,~donottrack", "reason=filter_unknown_option"]); | 517 "$csp="); |
| 354 compareFilter(test, "@@bla$donottrack", ["type=invalid", "text=@@bla$donottrac
k", "reason=filter_unknown_option"]); | 518 assert.equal(Filter.normalize("$csp= c s p"), |
| 355 compareFilter(test, "@@bla$foobar", ["type=invalid", "text=@@bla$foobar", "rea
son=filter_unknown_option"]); | 519 "$csp=c s p"); |
| 356 compareFilter(test, "@@bla$image,foobar", ["type=invalid", "text=@@bla$image,f
oobar", "reason=filter_unknown_option"]); | 520 assert.equal(Filter.normalize("$$csp= c s p"), |
| 357 compareFilter(test, "@@bla$foobar,image", ["type=invalid", "text=@@bla$foobar,
image", "reason=filter_unknown_option"]); | 521 "$$csp=c s p"); |
| 358 | 522 assert.equal(Filter.normalize("$$$csp= c s p"), |
| 359 compareFilter(test, "bla$csp", ["type=invalid", "text=bla$csp", "reason=filter
_invalid_csp"]); | 523 "$$$csp=c s p"); |
| 360 compareFilter(test, "bla$csp=", ["type=invalid", "text=bla$csp=", "reason=filt
er_invalid_csp"]); | 524 assert.equal(Filter.normalize("foo?csp=b a r$csp=script-src 'self'"), |
| 361 | 525 "foo?csp=bar$csp=script-src 'self'"); |
| 362 // Blank CSP values are allowed for whitelist filters. | 526 assert.equal(Filter.normalize("foo$bar=c s p = ba z,cs p = script-src 'self
'"), |
| 363 compareFilter(test, "@@bla$csp", ["type=whitelist", "text=@@bla$csp", "content
Type=" + t.CSP]); | 527 "foo$bar=csp=baz,csp=script-src 'self'"); |
| 364 compareFilter(test, "@@bla$csp=", ["type=whitelist", "text=@@bla$csp=", "conte
ntType=" + t.CSP]); | 528 assert.equal(Filter.normalize("foo$csp=c s p csp= ba z,cs p = script-src '
self'"), |
| 365 | 529 "foo$csp=c s p csp= ba z,csp=script-src 'self'"); |
| 366 compareFilter(test, "bla$csp=report-uri", ["type=invalid", "text=bla$csp=repor
t-uri", "reason=filter_invalid_csp"]); | 530 assert.equal(Filter.normalize("foo$csp=bar,$c sp=c s p"), |
| 367 compareFilter(test, "bla$csp=foo,csp=report-to", ["type=invalid", "text=bla$cs
p=foo,csp=report-to", "reason=filter_invalid_csp"]); | 531 "foo$csp=bar,$csp=c s p"); |
| 368 compareFilter(test, "bla$csp=foo,csp=referrer foo", ["type=invalid", "text=bla
$csp=foo,csp=referrer foo", "reason=filter_invalid_csp"]); | 532 assert.equal(Filter.normalize(" f o o $ bar $csp=ba r"), |
| 369 compareFilter(test, "bla$csp=foo,csp=base-uri", ["type=invalid", "text=bla$csp
=foo,csp=base-uri", "reason=filter_invalid_csp"]); | 533 "foo$bar$csp=ba r"); |
| 370 compareFilter(test, "bla$csp=foo,csp=upgrade-insecure-requests", ["type=invali
d", "text=bla$csp=foo,csp=upgrade-insecure-requests", "reason=filter_invalid_csp
"]); | 534 assert.equal(Filter.normalize("f $ o $ o $ csp=f o o "), |
| 371 compareFilter(test, "bla$csp=foo,csp=ReFeRReR", ["type=invalid", "text=bla$csp
=foo,csp=ReFeRReR", "reason=filter_invalid_csp"]); | 535 "f$o$o$csp=f o o"); |
| 372 | 536 assert.equal(Filter.normalize("/foo$/$ csp = script-src http://example.com/
?$1=1&$2=2&$3=3"), |
| 373 test.done(); | 537 "/foo$/$csp=script-src http://example.com/?$1=1&$2=2&$3=3"); |
| 374 }; | 538 assert.equal(Filter.normalize("||content.server.com/files/*.php$rewrite= $1"
), |
| 375 | 539 "||content.server.com/files/*.php$rewrite=$1"); |
| 376 exports.testElementHidingRules = function(test) | 540 }); |
| 377 { | 541 |
| 378 compareFilter(test, "##ddd", ["type=elemhide", "text=##ddd", "selector=ddd"]); | 542 it("Filter rewrite option", () => |
| 379 compareFilter(test, "##body > div:first-child", ["type=elemhide", "text=##body
> div:first-child", "selector=body > div:first-child"]); | 543 { |
| 380 compareFilter(test, "fOO##ddd", ["type=elemhide", "text=fOO##ddd", "selectorDo
mains=foo", "selector=ddd", "domains=foo"]); | 544 let text = "/(content\\.server\\/file\\/.*\\.txt)\\?.*$/$rewrite=$1"; |
| 381 compareFilter(test, "Foo,bAr##ddd", ["type=elemhide", "text=Foo,bAr##ddd", "se
lectorDomains=foo,bar", "selector=ddd", "domains=bar|foo"]); | 545 |
| 382 compareFilter(test, "foo,~baR##ddd", ["type=elemhide", "text=foo,~baR##ddd", "
selectorDomains=foo", "selector=ddd", "domains=foo|~bar"]); | 546 let filter = Filter.fromText(text); |
| 383 compareFilter(test, "foo,~baz,bar##ddd", ["type=elemhide", "text=foo,~baz,bar#
#ddd", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo|~baz"]); | 547 |
| 384 | 548 assert.equal(filter.rewrite, "$1"); |
| 385 test.done(); | 549 // no rewrite occured: didn't match. |
| 386 }; | 550 assert.equal(filter.rewriteUrl("foo"), "foo"); |
| 387 | 551 // rewrite occured: matched. |
| 388 exports.testElementHidingExceptions = function(test) | 552 assert.equal(filter.rewriteUrl("http://content.server/file/foo.txt?bar"), |
| 389 { | 553 "http://content.server/file/foo.txt"); |
| 390 compareFilter(test, "#@#ddd", ["type=elemhideexception", "text=#@#ddd", "selec
tor=ddd"]); | 554 |
| 391 compareFilter(test, "#@#body > div:first-child", ["type=elemhideexception", "t
ext=#@#body > div:first-child", "selector=body > div:first-child"]); | 555 // checking for same origin. |
| 392 compareFilter(test, "fOO#@#ddd", ["type=elemhideexception", "text=fOO#@#ddd",
"selectorDomains=foo", "selector=ddd", "domains=foo"]); | 556 let rewriteDiffOrigin = |
| 393 compareFilter(test, "Foo,bAr#@#ddd", ["type=elemhideexception", "text=Foo,bAr#
@#ddd", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo"]); | |
| 394 compareFilter(test, "foo,~baR#@#ddd", ["type=elemhideexception", "text=foo,~ba
R#@#ddd", "selectorDomains=foo", "selector=ddd", "domains=foo|~bar"]); | |
| 395 compareFilter(test, "foo,~baz,bar#@#ddd", ["type=elemhideexception", "text=foo
,~baz,bar#@#ddd", "selectorDomains=foo,bar", "selector=ddd", "domains=bar|foo|~b
az"]); | |
| 396 | |
| 397 test.done(); | |
| 398 }; | |
| 399 | |
| 400 exports.testElemHideEmulationFilters = function(test) | |
| 401 { | |
| 402 // Check valid domain combinations | |
| 403 compareFilter(test, "fOO.cOm#?#:-abp-properties(abc)", ["type=elemhideemulatio
n", "text=fOO.cOm#?#:-abp-properties(abc)", "selectorDomains=foo.com", "selector
=:-abp-properties(abc)", "domains=foo.com"]); | |
| 404 compareFilter(test, "Foo.com,~bAr.com#?#:-abp-properties(abc)", ["type=elemhid
eemulation", "text=Foo.com,~bAr.com#?#:-abp-properties(abc)", "selectorDomains=f
oo.com", "selector=:-abp-properties(abc)", "domains=foo.com|~bar.com"]); | |
| 405 compareFilter(test, "foo.com,~baR#?#:-abp-properties(abc)", ["type=elemhideemu
lation", "text=foo.com,~baR#?#:-abp-properties(abc)", "selectorDomains=foo.com",
"selector=:-abp-properties(abc)", "domains=foo.com|~bar"]); | |
| 406 compareFilter(test, "~foo.com,bar.com#?#:-abp-properties(abc)", ["type=elemhid
eemulation", "text=~foo.com,bar.com#?#:-abp-properties(abc)", "selectorDomains=b
ar.com", "selector=:-abp-properties(abc)", "domains=bar.com|~foo.com"]); | |
| 407 | |
| 408 // Check some special cases | |
| 409 compareFilter(test, "#?#:-abp-properties(abc)", ["type=invalid", "text=#?#:-ab
p-properties(abc)", "reason=filter_elemhideemulation_nodomain"]); | |
| 410 compareFilter(test, "foo.com#?#abc", ["type=elemhideemulation", "text=foo.com#
?#abc", "selectorDomains=foo.com", "selector=abc", "domains=foo.com"]); | |
| 411 compareFilter(test, "foo.com#?#:-abp-foobar(abc)", ["type=elemhideemulation",
"text=foo.com#?#:-abp-foobar(abc)", "selectorDomains=foo.com", "selector=:-abp-f
oobar(abc)", "domains=foo.com"]); | |
| 412 compareFilter(test, "foo.com#?#aaa :-abp-properties(abc) bbb", ["type=elemhide
emulation", "text=foo.com#?#aaa :-abp-properties(abc) bbb", "selectorDomains=foo
.com", "selector=aaa :-abp-properties(abc) bbb", "domains=foo.com"]); | |
| 413 compareFilter(test, "foo.com#?#:-abp-properties(|background-image: url(data:*)
)", ["type=elemhideemulation", "text=foo.com#?#:-abp-properties(|background-imag
e: url(data:*))", "selectorDomains=foo.com", "selector=:-abp-properties(|backgro
und-image: url(data:*))", "domains=foo.com"]); | |
| 414 | |
| 415 // Support element hiding emulation filters for localhost (#6931). | |
| 416 compareFilter(test, "localhost#?#:-abp-properties(abc)", ["type=elemhideemulat
ion", "text=localhost#?#:-abp-properties(abc)", "selectorDomains=localhost", "se
lector=:-abp-properties(abc)", "domains=localhost"]); | |
| 417 compareFilter(test, "localhost,~www.localhost#?#:-abp-properties(abc)", ["type
=elemhideemulation", "text=localhost,~www.localhost#?#:-abp-properties(abc)", "s
electorDomains=localhost", "selector=:-abp-properties(abc)", "domains=localhost|
~www.localhost"]); | |
| 418 compareFilter(test, "~www.localhost,localhost#?#:-abp-properties(abc)", ["type
=elemhideemulation", "text=~www.localhost,localhost#?#:-abp-properties(abc)", "s
electorDomains=localhost", "selector=:-abp-properties(abc)", "domains=localhost|
~www.localhost"]); | |
| 419 | |
| 420 test.done(); | |
| 421 }; | |
| 422 | |
| 423 exports.testEmptyElemHideDomains = function(test) | |
| 424 { | |
| 425 let emptyDomainFilters = [ | |
| 426 ",##selector", ",,,##selector", "~,foo.com##selector", "foo.com,##selector", | |
| 427 ",foo.com##selector", "foo.com,~##selector", | |
| 428 "foo.com,,bar.com##selector", "foo.com,~,bar.com##selector" | |
| 429 ]; | |
| 430 | |
| 431 for (let filterText of emptyDomainFilters) | |
| 432 { | |
| 433 let filter = Filter.fromText(filterText); | |
| 434 test.ok(filter instanceof InvalidFilter); | |
| 435 test.equal(filter.reason, "filter_invalid_domain"); | |
| 436 } | |
| 437 | |
| 438 test.done(); | |
| 439 }; | |
| 440 | |
| 441 exports.testElemHideRulesWithBraces = function(test) | |
| 442 { | |
| 443 compareFilter( | |
| 444 test, "###foo{color: red}", [ | |
| 445 "type=elemhide", | |
| 446 "text=###foo{color: red}", | |
| 447 "selectorDomains=", | |
| 448 "selector=#foo{color: red}", | |
| 449 "domains=" | |
| 450 ] | |
| 451 ); | |
| 452 compareFilter( | |
| 453 test, "foo.com#?#:-abp-properties(/margin: [3-4]{2}/)", [ | |
| 454 "type=elemhideemulation", | |
| 455 "text=foo.com#?#:-abp-properties(/margin: [3-4]{2}/)", | |
| 456 "selectorDomains=foo.com", | |
| 457 "selector=:-abp-properties(/margin: [3-4]{2}/)", | |
| 458 "domains=foo.com" | |
| 459 ] | |
| 460 ); | |
| 461 test.done(); | |
| 462 }; | |
| 463 | |
| 464 exports.testSnippetFilters = function(test) | |
| 465 { | |
| 466 compareFilter(test, "foo.com#$#abc", ["type=snippet", "text=foo.com#$#abc", "s
criptDomains=foo.com", "script=abc", "domains=foo.com"]); | |
| 467 compareFilter(test, "foo.com,~bar.com#$#abc", ["type=snippet", "text=foo.com,~
bar.com#$#abc", "scriptDomains=foo.com", "script=abc", "domains=foo.com|~bar.com
"]); | |
| 468 compareFilter(test, "foo.com,~bar#$#abc", ["type=snippet", "text=foo.com,~bar#
$#abc", "scriptDomains=foo.com", "script=abc", "domains=foo.com|~bar"]); | |
| 469 compareFilter(test, "~foo.com,bar.com#$#abc", ["type=snippet", "text=~foo.com,
bar.com#$#abc", "scriptDomains=bar.com", "script=abc", "domains=bar.com|~foo.com
"]); | |
| 470 | |
| 471 test.done(); | |
| 472 }; | |
| 473 | |
| 474 exports.testFilterNormalization = function(test) | |
| 475 { | |
| 476 // Line breaks etc | |
| 477 test.equal(Filter.normalize("\n\t\nad\ns"), | |
| 478 "ads"); | |
| 479 | |
| 480 // Comment filters | |
| 481 test.equal(Filter.normalize(" ! fo o## bar "), | |
| 482 "! fo o## bar"); | |
| 483 | |
| 484 // Element hiding filters | |
| 485 test.equal(Filter.normalize(" domain.c om## # sele ctor "), | |
| 486 "domain.com### sele ctor"); | |
| 487 | |
| 488 // Element hiding emulation filters | |
| 489 test.equal(Filter.normalize(" domain.c om#?# # sele ctor "), | |
| 490 "domain.com#?## sele ctor"); | |
| 491 | |
| 492 // Incorrect syntax: the separator "#?#" cannot contain spaces; treated as a | |
| 493 // regular filter instead | |
| 494 test.equal(Filter.normalize(" domain.c om# ?#. sele ctor "), | |
| 495 "domain.com#?#.selector"); | |
| 496 // Incorrect syntax: the separator "#?#" cannot contain spaces; treated as an | |
| 497 // element hiding filter instead, because the "##" following the "?" is taken | |
| 498 // to be the separator instead | |
| 499 test.equal(Filter.normalize(" domain.c om# ?##sele ctor "), | |
| 500 "domain.com#?##sele ctor"); | |
| 501 | |
| 502 // Element hiding exception filters | |
| 503 test.equal(Filter.normalize(" domain.c om#@# # sele ctor "), | |
| 504 "domain.com#@## sele ctor"); | |
| 505 | |
| 506 // Incorrect syntax: the separator "#@#" cannot contain spaces; treated as a | |
| 507 // regular filter instead (not an element hiding filter either!), because | |
| 508 // unlike the case with "# ?##" the "##" following the "@" is not considered | |
| 509 // to be a separator | |
| 510 test.equal(Filter.normalize(" domain.c om# @## sele ctor "), | |
| 511 "domain.com#@##selector"); | |
| 512 | |
| 513 // Snippet filters | |
| 514 test.equal(Filter.normalize(" domain.c om#$# sni pp et "), | |
| 515 "domain.com#$#sni pp et"); | |
| 516 | |
| 517 // Regular filters | |
| 518 let normalized = Filter.normalize( | |
| 519 " b$l a$sitekey= foo ,domain= do main.com |foo .com,c sp= c s p
" | |
| 520 ); | |
| 521 test.equal( | |
| 522 normalized, | |
| 523 "b$la$sitekey=foo,domain=domain.com|foo.com,csp=c s p" | |
| 524 ); | |
| 525 compareFilter( | |
| 526 test, normalized, [ | |
| 527 "type=filterlist", | |
| 528 "text=" + normalized, | |
| 529 "csp=c s p", | |
| 530 "domains=domain.com|foo.com", | |
| 531 "sitekeys=FOO", | |
| 532 "contentType=" + t.CSP | |
| 533 ] | |
| 534 ); | |
| 535 | |
| 536 // Some $csp edge cases | |
| 537 test.equal(Filter.normalize("$csp= "), | |
| 538 "$csp="); | |
| 539 test.equal(Filter.normalize("$csp= c s p"), | |
| 540 "$csp=c s p"); | |
| 541 test.equal(Filter.normalize("$$csp= c s p"), | |
| 542 "$$csp=c s p"); | |
| 543 test.equal(Filter.normalize("$$$csp= c s p"), | |
| 544 "$$$csp=c s p"); | |
| 545 test.equal(Filter.normalize("foo?csp=b a r$csp=script-src 'self'"), | |
| 546 "foo?csp=bar$csp=script-src 'self'"); | |
| 547 test.equal(Filter.normalize("foo$bar=c s p = ba z,cs p = script-src 'self'"), | |
| 548 "foo$bar=csp=baz,csp=script-src 'self'"); | |
| 549 test.equal(Filter.normalize("foo$csp=c s p csp= ba z,cs p = script-src 'self
'"), | |
| 550 "foo$csp=c s p csp= ba z,csp=script-src 'self'"); | |
| 551 test.equal(Filter.normalize("foo$csp=bar,$c sp=c s p"), | |
| 552 "foo$csp=bar,$csp=c s p"); | |
| 553 test.equal(Filter.normalize(" f o o $ bar $csp=ba r"), | |
| 554 "foo$bar$csp=ba r"); | |
| 555 test.equal(Filter.normalize("f $ o $ o $ csp=f o o "), | |
| 556 "f$o$o$csp=f o o"); | |
| 557 test.equal(Filter.normalize("/foo$/$ csp = script-src http://example.com/?$1=
1&$2=2&$3=3"), | |
| 558 "/foo$/$csp=script-src http://example.com/?$1=1&$2=2&$3=3"); | |
| 559 test.equal(Filter.normalize("||content.server.com/files/*.php$rewrite= $1"), | |
| 560 "||content.server.com/files/*.php$rewrite=$1"); | |
| 561 test.done(); | |
| 562 }; | |
| 563 | |
| 564 exports.testFilterRewriteOption = function(test) | |
| 565 { | |
| 566 let text = "/(content\\.server\\/file\\/.*\\.txt)\\?.*$/$rewrite=$1"; | |
| 567 | |
| 568 let filter = Filter.fromText(text); | |
| 569 | |
| 570 test.equal(filter.rewrite, "$1"); | |
| 571 // no rewrite occured: didn't match. | |
| 572 test.equal(filter.rewriteUrl("foo"), "foo"); | |
| 573 // rewrite occured: matched. | |
| 574 test.equal(filter.rewriteUrl("http://content.server/file/foo.txt?bar"), | |
| 575 "http://content.server/file/foo.txt"); | |
| 576 | |
| 577 // checking for same origin. | |
| 578 let rewriteDiffOrigin = | |
| 579 "/content\\.server(\\/file\\/.*\\.txt)\\?.*$/$rewrite=foo.com$1"; | 557 "/content\\.server(\\/file\\/.*\\.txt)\\?.*$/$rewrite=foo.com$1"; |
| 580 let filterDiffOrigin = Filter.fromText(rewriteDiffOrigin); | 558 let filterDiffOrigin = Filter.fromText(rewriteDiffOrigin); |
| 581 | 559 |
| 582 // no rewrite occured because of a different origin. | 560 // no rewrite occured because of a different origin. |
| 583 test.equal( | 561 assert.equal( |
| 584 filterDiffOrigin.rewriteUrl("http://content.server/file/foo.txt?bar"), | 562 filterDiffOrigin.rewriteUrl("http://content.server/file/foo.txt?bar"), |
| 585 "http://content.server/file/foo.txt?bar" | 563 "http://content.server/file/foo.txt?bar" |
| 586 ); | 564 ); |
| 587 | 565 |
| 588 // relative path. | 566 // relative path. |
| 589 let rewriteRelative = "/(\\/file\\/.*\\.txt)\\?.*$/$rewrite=$1/disable"; | 567 let rewriteRelative = "/(\\/file\\/.*\\.txt)\\?.*$/$rewrite=$1/disable"; |
| 590 let filterRelative = Filter.fromText(rewriteRelative); | 568 let filterRelative = Filter.fromText(rewriteRelative); |
| 591 | 569 |
| 592 test.equal( | 570 assert.equal( |
| 593 filterRelative.rewriteUrl("http://content.server/file/foo.txt?bar"), | 571 filterRelative.rewriteUrl("http://content.server/file/foo.txt?bar"), |
| 594 "http://content.server/file/foo.txt/disable" | 572 "http://content.server/file/foo.txt/disable" |
| 595 ); | 573 ); |
| 596 test.equal( | 574 assert.equal( |
| 597 filterRelative.rewriteUrl("http://example.com/file/foo.txt?bar"), | 575 filterRelative.rewriteUrl("http://example.com/file/foo.txt?bar"), |
| 598 "http://example.com/file/foo.txt/disable" | 576 "http://example.com/file/foo.txt/disable" |
| 599 ); | 577 ); |
| 600 | 578 |
| 601 // Example from https://github.com/uBlockOrigin/uBlock-issues/issues/46#issuec
omment-391190533 | 579 // Example from https://github.com/uBlockOrigin/uBlock-issues/issues/46#issu
ecomment-391190533 |
| 602 // The rewrite shouldn't happen. | 580 // The rewrite shouldn't happen. |
| 603 let rewriteEvil = "/(^https?:\\/\\/[^/])/$script,rewrite=$1.evil.com"; | 581 let rewriteEvil = "/(^https?:\\/\\/[^/])/$script,rewrite=$1.evil.com"; |
| 604 let filterEvil = Filter.fromText(rewriteEvil); | 582 let filterEvil = Filter.fromText(rewriteEvil); |
| 605 | 583 |
| 606 test.equal( | 584 assert.equal( |
| 607 filterEvil.rewriteUrl("https://www.adblockplus.org/script.js"), | 585 filterEvil.rewriteUrl("https://www.adblockplus.org/script.js"), |
| 608 "https://www.adblockplus.org/script.js" | 586 "https://www.adblockplus.org/script.js" |
| 609 ); | 587 ); |
| 610 | 588 |
| 611 // Strip. | 589 // Strip. |
| 612 let rewriteStrip = "tag$rewrite="; | 590 let rewriteStrip = "tag$rewrite="; |
| 613 let filterStrip = Filter.fromText(rewriteStrip); | 591 let filterStrip = Filter.fromText(rewriteStrip); |
| 614 | 592 |
| 615 test.equal(filterStrip.rewrite, ""); | 593 assert.equal(filterStrip.rewrite, ""); |
| 616 test.equal( | 594 assert.equal( |
| 617 filterStrip.rewriteUrl("http://example.com/?tag"), | 595 filterStrip.rewriteUrl("http://example.com/?tag"), |
| 618 "http://example.com/?" | 596 "http://example.com/?" |
| 619 ); | 597 ); |
| 620 | 598 }); |
| 621 test.done(); | 599 |
| 622 }; | 600 it("Domain map deduplication", () => |
| 623 | 601 { |
| 624 exports.testDomainMapDeduplication = function(test) | 602 let filter1 = Filter.fromText("foo$domain=blocking.example.com"); |
| 625 { | 603 let filter2 = Filter.fromText("bar$domain=blocking.example.com"); |
| 626 let filter1 = Filter.fromText("foo$domain=blocking.example.com"); | 604 let filter3 = Filter.fromText("elemhide.example.com##.foo"); |
| 627 let filter2 = Filter.fromText("bar$domain=blocking.example.com"); | 605 let filter4 = Filter.fromText("elemhide.example.com##.bar"); |
| 628 let filter3 = Filter.fromText("elemhide.example.com##.foo"); | 606 |
| 629 let filter4 = Filter.fromText("elemhide.example.com##.bar"); | 607 // This compares the references to make sure that both refer to the same |
| 630 | 608 // object (#6815). |
| 631 // This compares the references to make sure that both refer to the same | 609 |
| 632 // object (#6815). | 610 assert.equal(filter1.domains, filter2.domains); |
| 633 | 611 assert.equal(filter3.domains, filter4.domains); |
| 634 test.equal(filter1.domains, filter2.domains); | 612 |
| 635 test.equal(filter3.domains, filter4.domains); | 613 let filter5 = Filter.fromText("bar$domain=www.example.com"); |
| 636 | 614 let filter6 = Filter.fromText("www.example.com##.bar"); |
| 637 let filter5 = Filter.fromText("bar$domain=www.example.com"); | 615 |
| 638 let filter6 = Filter.fromText("www.example.com##.bar"); | 616 assert.notEqual(filter2.domains, filter5.domains); |
| 639 | 617 assert.notEqual(filter4.domains, filter6.domains); |
| 640 test.notEqual(filter2.domains, filter5.domains); | 618 }); |
| 641 test.notEqual(filter4.domains, filter6.domains); | 619 }); |
| 642 | |
| 643 test.done(); | |
| 644 }; | |
| OLD | NEW |