| 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 |