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 /** | 20 /** |
21 * @fileOverview Definition of Filter class and its subclasses. | 21 * @fileOverview Definition of Filter class and its subclasses. |
22 */ | 22 */ |
23 | 23 |
24 const {FilterNotifier} = require("./filterNotifier"); | 24 const {FilterNotifier} = require("./filterNotifier"); |
25 const {extend} = require("./coreUtils"); | |
26 const {filterToRegExp} = require("./common"); | 25 const {filterToRegExp} = require("./common"); |
27 | 26 |
28 /** | 27 /** |
29 * Abstract base class for filters | 28 * Abstract base class for filters |
30 * | 29 * |
31 * @param {string} text string representation of the filter | 30 * @param {string} text string representation of the filter |
32 * @constructor | 31 * @constructor |
33 */ | 32 */ |
34 function Filter(text) | 33 function Filter(text) |
35 { | 34 { |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 * @augments Filter | 245 * @augments Filter |
247 */ | 246 */ |
248 function InvalidFilter(text, reason) | 247 function InvalidFilter(text, reason) |
249 { | 248 { |
250 Filter.call(this, text); | 249 Filter.call(this, text); |
251 | 250 |
252 this.reason = reason; | 251 this.reason = reason; |
253 } | 252 } |
254 exports.InvalidFilter = InvalidFilter; | 253 exports.InvalidFilter = InvalidFilter; |
255 | 254 |
256 InvalidFilter.prototype = extend(Filter, { | 255 InvalidFilter.prototype = { |
| 256 __proto__: Filter.prototype, |
| 257 |
257 type: "invalid", | 258 type: "invalid", |
258 | 259 |
259 /** | 260 /** |
260 * Reason why this filter is invalid | 261 * Reason why this filter is invalid |
261 * @type {string} | 262 * @type {string} |
262 */ | 263 */ |
263 reason: null, | 264 reason: null, |
264 | 265 |
265 /** | 266 /** |
266 * See Filter.serialize() | 267 * See Filter.serialize() |
267 * @inheritdoc | 268 * @inheritdoc |
268 */ | 269 */ |
269 serialize(buffer) {} | 270 serialize(buffer) {} |
270 }); | 271 }; |
271 | 272 |
272 /** | 273 /** |
273 * Class for comments | 274 * Class for comments |
274 * @param {string} text see Filter() | 275 * @param {string} text see Filter() |
275 * @constructor | 276 * @constructor |
276 * @augments Filter | 277 * @augments Filter |
277 */ | 278 */ |
278 function CommentFilter(text) | 279 function CommentFilter(text) |
279 { | 280 { |
280 Filter.call(this, text); | 281 Filter.call(this, text); |
281 } | 282 } |
282 exports.CommentFilter = CommentFilter; | 283 exports.CommentFilter = CommentFilter; |
283 | 284 |
284 CommentFilter.prototype = extend(Filter, { | 285 CommentFilter.prototype = { |
| 286 __proto__: Filter.prototype, |
| 287 |
285 type: "comment", | 288 type: "comment", |
286 | 289 |
287 /** | 290 /** |
288 * See Filter.serialize() | 291 * See Filter.serialize() |
289 * @inheritdoc | 292 * @inheritdoc |
290 */ | 293 */ |
291 serialize(buffer) {} | 294 serialize(buffer) {} |
292 }); | 295 }; |
293 | 296 |
294 /** | 297 /** |
295 * Abstract base class for filters that can get hits | 298 * Abstract base class for filters that can get hits |
296 * @param {string} text | 299 * @param {string} text |
297 * see Filter() | 300 * see Filter() |
298 * @param {string} [domains] | 301 * @param {string} [domains] |
299 * Domains that the filter is restricted to separated by domainSeparator | 302 * Domains that the filter is restricted to separated by domainSeparator |
300 * e.g. "foo.com|bar.com|~baz.com" | 303 * e.g. "foo.com|bar.com|~baz.com" |
301 * @constructor | 304 * @constructor |
302 * @augments Filter | 305 * @augments Filter |
303 */ | 306 */ |
304 function ActiveFilter(text, domains) | 307 function ActiveFilter(text, domains) |
305 { | 308 { |
306 Filter.call(this, text); | 309 Filter.call(this, text); |
307 | 310 |
308 this.domainSource = domains; | 311 this.domainSource = domains; |
309 } | 312 } |
310 exports.ActiveFilter = ActiveFilter; | 313 exports.ActiveFilter = ActiveFilter; |
311 | 314 |
312 ActiveFilter.prototype = extend(Filter, { | 315 ActiveFilter.prototype = { |
| 316 __proto__: Filter.prototype, |
| 317 |
313 _disabled: false, | 318 _disabled: false, |
314 _hitCount: 0, | 319 _hitCount: 0, |
315 _lastHit: 0, | 320 _lastHit: 0, |
316 | 321 |
317 /** | 322 /** |
318 * Defines whether the filter is disabled | 323 * Defines whether the filter is disabled |
319 * @type {boolean} | 324 * @type {boolean} |
320 */ | 325 */ |
321 get disabled() | 326 get disabled() |
322 { | 327 { |
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
568 { | 573 { |
569 Filter.prototype.serialize.call(this, buffer); | 574 Filter.prototype.serialize.call(this, buffer); |
570 if (this._disabled) | 575 if (this._disabled) |
571 buffer.push("disabled=true"); | 576 buffer.push("disabled=true"); |
572 if (this._hitCount) | 577 if (this._hitCount) |
573 buffer.push("hitCount=" + this._hitCount); | 578 buffer.push("hitCount=" + this._hitCount); |
574 if (this._lastHit) | 579 if (this._lastHit) |
575 buffer.push("lastHit=" + this._lastHit); | 580 buffer.push("lastHit=" + this._lastHit); |
576 } | 581 } |
577 } | 582 } |
578 }); | 583 }; |
579 | 584 |
580 /** | 585 /** |
581 * Abstract base class for RegExp-based filters | 586 * Abstract base class for RegExp-based filters |
582 * @param {string} text see Filter() | 587 * @param {string} text see Filter() |
583 * @param {string} regexpSource | 588 * @param {string} regexpSource |
584 * filter part that the regular expression should be build from | 589 * filter part that the regular expression should be build from |
585 * @param {number} [contentType] | 590 * @param {number} [contentType] |
586 * Content types the filter applies to, combination of values from | 591 * Content types the filter applies to, combination of values from |
587 * RegExpFilter.typeMap | 592 * RegExpFilter.typeMap |
588 * @param {boolean} [matchCase] | 593 * @param {boolean} [matchCase] |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 Object.defineProperty(this, "regexp", {value: regexp}); | 628 Object.defineProperty(this, "regexp", {value: regexp}); |
624 } | 629 } |
625 else | 630 else |
626 { | 631 { |
627 // No need to convert this filter to regular expression yet, do it on demand | 632 // No need to convert this filter to regular expression yet, do it on demand |
628 this.regexpSource = regexpSource; | 633 this.regexpSource = regexpSource; |
629 } | 634 } |
630 } | 635 } |
631 exports.RegExpFilter = RegExpFilter; | 636 exports.RegExpFilter = RegExpFilter; |
632 | 637 |
633 RegExpFilter.prototype = extend(ActiveFilter, { | 638 RegExpFilter.prototype = { |
| 639 __proto__: ActiveFilter.prototype, |
| 640 |
634 /** | 641 /** |
635 * @see ActiveFilter.domainSourceIsUpperCase | 642 * @see ActiveFilter.domainSourceIsUpperCase |
636 */ | 643 */ |
637 domainSourceIsUpperCase: true, | 644 domainSourceIsUpperCase: true, |
638 | 645 |
639 /** | 646 /** |
640 * Number of filters contained, will always be 1 (required to | 647 * Number of filters contained, will always be 1 (required to |
641 * optimize Matcher). | 648 * optimize Matcher). |
642 * @type {number} | 649 * @type {number} |
643 */ | 650 */ |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
735 matches(location, typeMask, docDomain, thirdParty, sitekey) | 742 matches(location, typeMask, docDomain, thirdParty, sitekey) |
736 { | 743 { |
737 if (this.contentType & typeMask && | 744 if (this.contentType & typeMask && |
738 (this.thirdParty == null || this.thirdParty == thirdParty) && | 745 (this.thirdParty == null || this.thirdParty == thirdParty) && |
739 this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location)) | 746 this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location)) |
740 { | 747 { |
741 return true; | 748 return true; |
742 } | 749 } |
743 return false; | 750 return false; |
744 } | 751 } |
745 }); | 752 }; |
746 | 753 |
747 // Required to optimize Matcher, see also RegExpFilter.prototype.length | 754 // Required to optimize Matcher, see also RegExpFilter.prototype.length |
748 Object.defineProperty(RegExpFilter.prototype, "0", { | 755 Object.defineProperty(RegExpFilter.prototype, "0", { |
749 get() { return this; } | 756 get() { return this; } |
750 }); | 757 }); |
751 | 758 |
752 /** | 759 /** |
753 * Creates a RegExp filter from its text representation | 760 * Creates a RegExp filter from its text representation |
754 * @param {string} text same as in Filter() | 761 * @param {string} text same as in Filter() |
755 * @return {Filter} | 762 * @return {Filter} |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
901 thirdParty, sitekeys, collapse, csp) | 908 thirdParty, sitekeys, collapse, csp) |
902 { | 909 { |
903 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, | 910 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, |
904 thirdParty, sitekeys); | 911 thirdParty, sitekeys); |
905 | 912 |
906 this.collapse = collapse; | 913 this.collapse = collapse; |
907 this.csp = csp; | 914 this.csp = csp; |
908 } | 915 } |
909 exports.BlockingFilter = BlockingFilter; | 916 exports.BlockingFilter = BlockingFilter; |
910 | 917 |
911 BlockingFilter.prototype = extend(RegExpFilter, { | 918 BlockingFilter.prototype = { |
| 919 __proto__: RegExpFilter.prototype, |
| 920 |
912 type: "blocking", | 921 type: "blocking", |
913 | 922 |
914 /** | 923 /** |
915 * Defines whether the filter should collapse blocked content. | 924 * Defines whether the filter should collapse blocked content. |
916 * Can be null (use the global preference). | 925 * Can be null (use the global preference). |
917 * @type {boolean} | 926 * @type {boolean} |
918 */ | 927 */ |
919 collapse: null, | 928 collapse: null, |
920 | 929 |
921 /** | 930 /** |
922 * Content Security Policy to inject for matching requests. | 931 * Content Security Policy to inject for matching requests. |
923 * @type {string} | 932 * @type {string} |
924 */ | 933 */ |
925 csp: null | 934 csp: null |
926 }); | 935 }; |
927 | 936 |
928 /** | 937 /** |
929 * Class for whitelist filters | 938 * Class for whitelist filters |
930 * @param {string} text see Filter() | 939 * @param {string} text see Filter() |
931 * @param {string} regexpSource see RegExpFilter() | 940 * @param {string} regexpSource see RegExpFilter() |
932 * @param {number} contentType see RegExpFilter() | 941 * @param {number} contentType see RegExpFilter() |
933 * @param {boolean} matchCase see RegExpFilter() | 942 * @param {boolean} matchCase see RegExpFilter() |
934 * @param {string} domains see RegExpFilter() | 943 * @param {string} domains see RegExpFilter() |
935 * @param {boolean} thirdParty see RegExpFilter() | 944 * @param {boolean} thirdParty see RegExpFilter() |
936 * @param {string} sitekeys see RegExpFilter() | 945 * @param {string} sitekeys see RegExpFilter() |
937 * @constructor | 946 * @constructor |
938 * @augments RegExpFilter | 947 * @augments RegExpFilter |
939 */ | 948 */ |
940 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, | 949 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, |
941 thirdParty, sitekeys) | 950 thirdParty, sitekeys) |
942 { | 951 { |
943 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, | 952 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, |
944 thirdParty, sitekeys); | 953 thirdParty, sitekeys); |
945 } | 954 } |
946 exports.WhitelistFilter = WhitelistFilter; | 955 exports.WhitelistFilter = WhitelistFilter; |
947 | 956 |
948 WhitelistFilter.prototype = extend(RegExpFilter, { | 957 WhitelistFilter.prototype = { |
| 958 __proto__: RegExpFilter.prototype, |
949 type: "whitelist" | 959 type: "whitelist" |
950 }); | 960 }; |
951 | 961 |
952 /** | 962 /** |
953 * Base class for element hiding filters | 963 * Base class for element hiding filters |
954 * @param {string} text see Filter() | 964 * @param {string} text see Filter() |
955 * @param {string} [domains] Host names or domains the filter should be | 965 * @param {string} [domains] Host names or domains the filter should be |
956 * restricted to | 966 * restricted to |
957 * @param {string} selector CSS selector for the HTML elements that should be | 967 * @param {string} selector CSS selector for the HTML elements that should be |
958 * hidden | 968 * hidden |
959 * @constructor | 969 * @constructor |
960 * @augments ActiveFilter | 970 * @augments ActiveFilter |
961 */ | 971 */ |
962 function ElemHideBase(text, domains, selector) | 972 function ElemHideBase(text, domains, selector) |
963 { | 973 { |
964 ActiveFilter.call(this, text, domains || null); | 974 ActiveFilter.call(this, text, domains || null); |
965 | 975 |
966 if (domains) | 976 if (domains) |
967 { | 977 { |
968 this.selectorDomain = domains.replace(/,~[^,]+/g, "") | 978 this.selectorDomain = domains.replace(/,~[^,]+/g, "") |
969 .replace(/^~[^,]+,?/, "").toLowerCase(); | 979 .replace(/^~[^,]+,?/, "").toLowerCase(); |
970 } | 980 } |
971 | 981 |
972 // Braces are being escaped to prevent CSS rule injection. | 982 // Braces are being escaped to prevent CSS rule injection. |
973 this.selector = selector.replace("{", "\\7B ").replace("}", "\\7D "); | 983 this.selector = selector.replace("{", "\\7B ").replace("}", "\\7D "); |
974 } | 984 } |
975 exports.ElemHideBase = ElemHideBase; | 985 exports.ElemHideBase = ElemHideBase; |
976 | 986 |
977 ElemHideBase.prototype = extend(ActiveFilter, { | 987 ElemHideBase.prototype = { |
| 988 __proto__: ActiveFilter.prototype, |
| 989 |
978 /** | 990 /** |
979 * @see ActiveFilter.domainSeparator | 991 * @see ActiveFilter.domainSeparator |
980 */ | 992 */ |
981 domainSeparator: ",", | 993 domainSeparator: ",", |
982 | 994 |
983 /** | 995 /** |
984 * @see ActiveFilter.ignoreTrailingDot | 996 * @see ActiveFilter.ignoreTrailingDot |
985 */ | 997 */ |
986 ignoreTrailingDot: false, | 998 ignoreTrailingDot: false, |
987 | 999 |
988 /** | 1000 /** |
989 * Host name or domain the filter should be restricted to (can be null for | 1001 * Host name or domain the filter should be restricted to (can be null for |
990 * no restriction) | 1002 * no restriction) |
991 * @type {string} | 1003 * @type {string} |
992 */ | 1004 */ |
993 selectorDomain: null, | 1005 selectorDomain: null, |
994 /** | 1006 /** |
995 * CSS selector for the HTML elements that should be hidden | 1007 * CSS selector for the HTML elements that should be hidden |
996 * @type {string} | 1008 * @type {string} |
997 */ | 1009 */ |
998 selector: null | 1010 selector: null |
999 }); | 1011 }; |
1000 | 1012 |
1001 /** | 1013 /** |
1002 * Creates an element hiding filter from a pre-parsed text representation | 1014 * Creates an element hiding filter from a pre-parsed text representation |
1003 * | 1015 * |
1004 * @param {string} text same as in Filter() | 1016 * @param {string} text same as in Filter() |
1005 * @param {string?} domain | 1017 * @param {string?} domain |
1006 * domain part of the text representation | 1018 * domain part of the text representation |
1007 * @param {string?} type | 1019 * @param {string?} type |
1008 * rule type, either empty or @ (exception) or ? (emulation rule) | 1020 * rule type, either empty or @ (exception) or ? (emulation rule) |
1009 * @param {string} selector raw CSS selector | 1021 * @param {string} selector raw CSS selector |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1041 * @param {string} selector see ElemHideBase() | 1053 * @param {string} selector see ElemHideBase() |
1042 * @constructor | 1054 * @constructor |
1043 * @augments ElemHideBase | 1055 * @augments ElemHideBase |
1044 */ | 1056 */ |
1045 function ElemHideFilter(text, domains, selector) | 1057 function ElemHideFilter(text, domains, selector) |
1046 { | 1058 { |
1047 ElemHideBase.call(this, text, domains, selector); | 1059 ElemHideBase.call(this, text, domains, selector); |
1048 } | 1060 } |
1049 exports.ElemHideFilter = ElemHideFilter; | 1061 exports.ElemHideFilter = ElemHideFilter; |
1050 | 1062 |
1051 ElemHideFilter.prototype = extend(ElemHideBase, { | 1063 ElemHideFilter.prototype = { |
| 1064 __proto__: ElemHideBase.prototype, |
1052 type: "elemhide" | 1065 type: "elemhide" |
1053 }); | 1066 }; |
1054 | 1067 |
1055 /** | 1068 /** |
1056 * Class for element hiding exceptions | 1069 * Class for element hiding exceptions |
1057 * @param {string} text see Filter() | 1070 * @param {string} text see Filter() |
1058 * @param {string} domains see ElemHideBase() | 1071 * @param {string} domains see ElemHideBase() |
1059 * @param {string} selector see ElemHideBase() | 1072 * @param {string} selector see ElemHideBase() |
1060 * @constructor | 1073 * @constructor |
1061 * @augments ElemHideBase | 1074 * @augments ElemHideBase |
1062 */ | 1075 */ |
1063 function ElemHideException(text, domains, selector) | 1076 function ElemHideException(text, domains, selector) |
1064 { | 1077 { |
1065 ElemHideBase.call(this, text, domains, selector); | 1078 ElemHideBase.call(this, text, domains, selector); |
1066 } | 1079 } |
1067 exports.ElemHideException = ElemHideException; | 1080 exports.ElemHideException = ElemHideException; |
1068 | 1081 |
1069 ElemHideException.prototype = extend(ElemHideBase, { | 1082 ElemHideException.prototype = { |
| 1083 __proto__: ElemHideBase.prototype, |
1070 type: "elemhideexception" | 1084 type: "elemhideexception" |
1071 }); | 1085 }; |
1072 | 1086 |
1073 /** | 1087 /** |
1074 * Class for element hiding emulation filters | 1088 * Class for element hiding emulation filters |
1075 * @param {string} text see Filter() | 1089 * @param {string} text see Filter() |
1076 * @param {string} domains see ElemHideBase() | 1090 * @param {string} domains see ElemHideBase() |
1077 * @param {string} selector see ElemHideBase() | 1091 * @param {string} selector see ElemHideBase() |
1078 * @constructor | 1092 * @constructor |
1079 * @augments ElemHideBase | 1093 * @augments ElemHideBase |
1080 */ | 1094 */ |
1081 function ElemHideEmulationFilter(text, domains, selector) | 1095 function ElemHideEmulationFilter(text, domains, selector) |
1082 { | 1096 { |
1083 ElemHideBase.call(this, text, domains, selector); | 1097 ElemHideBase.call(this, text, domains, selector); |
1084 } | 1098 } |
1085 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; | 1099 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; |
1086 | 1100 |
1087 ElemHideEmulationFilter.prototype = extend(ElemHideBase, { | 1101 ElemHideEmulationFilter.prototype = { |
| 1102 __proto__: ElemHideBase.prototype, |
1088 type: "elemhideemulation" | 1103 type: "elemhideemulation" |
1089 }); | 1104 }; |
OLD | NEW |