Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: lib/filterClasses.js

Issue 5730585574113280: Issue 2390 - Created filter class for CSS property filters (Closed)
Left Patch Set: Created May 4, 2015, 6:05 p.m.
Right Patch Set: Modified constructor signature Created June 8, 2015, 2:25 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « chrome/locale/en-US/global.properties ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 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
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 * @type RegExp 81 * @type RegExp
82 */ 82 */
83 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[ ^,\s]+)?)*)?$/; 83 Filter.regexpRegExp = /^(@@)?\/.*\/(?:\$~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[ ^,\s]+)?)*)?$/;
84 /** 84 /**
85 * Regular expression that options on a RegExp filter should match 85 * Regular expression that options on a RegExp filter should match
86 * @type RegExp 86 * @type RegExp
87 */ 87 */
88 Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/ ; 88 Filter.optionsRegExp = /\$(~?[\w\-]+(?:=[^,\s]+)?(?:,~?[\w\-]+(?:=[^,\s]+)?)*)$/ ;
89 /** 89 /**
90 * Regular expression that CSS property filters should match 90 * Regular expression that CSS property filters should match
91 * Properties must not contain " or '
91 * @type RegExp 92 * @type RegExp
92 */ 93 */
93 Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/; 94 Filter.csspropertyRegExp = /\[\-abp\-properties=(["'])([^"']+)\1\]/;
Sebastian Noack 2015/05/05 15:47:02 So we don't allow quotes in the value here. Should
Thomas Greiner 2015/05/06 12:08:32 Done, I added a comment as suggested. We could cha
Thomas Greiner 2015/05/06 15:33:07 Yes, there's currently no negative lookbehind in J
Sebastian Noack 2015/05/06 15:42:29 Yeah, let's stick to not allowing any quotes for n
94 95
95 /** 96 /**
96 * Creates a filter of correct type from its text representation - does the basi c parsing and 97 * Creates a filter of correct type from its text representation - does the basi c parsing and
97 * calls the right constructor then. 98 * calls the right constructor then.
98 * 99 *
99 * @param {String} text as in Filter() 100 * @param {String} text as in Filter()
100 * @return {Filter} 101 * @return {Filter}
101 */ 102 */
102 Filter.fromText = function(text) 103 Filter.fromText = function(text)
103 { 104 {
(...skipping 607 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 collapse = true; 712 collapse = true;
712 else if (option == "~COLLAPSE") 713 else if (option == "~COLLAPSE")
713 collapse = false; 714 collapse = false;
714 else if (option == "SITEKEY" && typeof value != "undefined") 715 else if (option == "SITEKEY" && typeof value != "undefined")
715 sitekeys = value; 716 sitekeys = value;
716 else 717 else
717 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e()); 718 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e());
718 } 719 }
719 } 720 }
720 721
721 if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.D OCUMENT)) &&
722 (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text ))
723 {
724 // Exception filters shouldn't apply to pages by default unless they start w ith a protocol name
725 if (contentType == null)
726 contentType = RegExpFilter.prototype.contentType;
727 contentType &= ~RegExpFilter.typeMap.DOCUMENT;
728 }
729
730 try 722 try
731 { 723 {
732 if (blocking) 724 if (blocking)
733 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys, collapse); 725 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys, collapse);
734 else 726 else
735 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, sitekeys); 727 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, sitekeys);
736 } 728 }
737 catch (e) 729 catch (e)
738 { 730 {
739 return new InvalidFilter(origText, e); 731 return new InvalidFilter(origText, e);
(...skipping 18 matching lines...) Expand all
758 DTD: 1, 750 DTD: 1,
759 MEDIA: 16384, 751 MEDIA: 16384,
760 FONT: 32768, 752 FONT: 32768,
761 753
762 BACKGROUND: 4, // Backwards compat, same as IMAGE 754 BACKGROUND: 4, // Backwards compat, same as IMAGE
763 755
764 POPUP: 0x10000000, 756 POPUP: 0x10000000,
765 ELEMHIDE: 0x40000000 757 ELEMHIDE: 0x40000000
766 }; 758 };
767 759
768 // ELEMHIDE, POPUP option shouldn't be there by default 760 // DOCUMENT, ELEMHIDE, POPUP options shouldn't be there by default
769 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFi lter.typeMap.POPUP); 761 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.DOCUMENT | RegExpFi lter.typeMap.ELEMHIDE | RegExpFilter.typeMap.POPUP);
770 762
771 /** 763 /**
772 * Class for blocking filters 764 * Class for blocking filters
773 * @param {String} text see Filter() 765 * @param {String} text see Filter()
774 * @param {String} regexpSource see RegExpFilter() 766 * @param {String} regexpSource see RegExpFilter()
775 * @param {Number} contentType see RegExpFilter() 767 * @param {Number} contentType see RegExpFilter()
776 * @param {Boolean} matchCase see RegExpFilter() 768 * @param {Boolean} matchCase see RegExpFilter()
777 * @param {String} domains see RegExpFilter() 769 * @param {String} domains see RegExpFilter()
778 * @param {Boolean} thirdParty see RegExpFilter() 770 * @param {Boolean} thirdParty see RegExpFilter()
779 * @param {String} sitekeys see RegExpFilter() 771 * @param {String} sitekeys see RegExpFilter()
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 */ 871 */
880 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector) 872 ElemHideBase.fromText = function(text, domain, isException, tagName, attrRules, selector)
881 { 873 {
882 if (!selector) 874 if (!selector)
883 { 875 {
884 if (tagName == "*") 876 if (tagName == "*")
885 tagName = ""; 877 tagName = "";
886 878
887 let id = null; 879 let id = null;
888 let additional = ""; 880 let additional = "";
889 if (attrRules) { 881 if (attrRules)
882 {
890 attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g); 883 attrRules = attrRules.match(/\([\w\-]+(?:[$^*]?=[^\(\)"]*)?\)/g);
891 for (let rule of attrRules) { 884 for (let rule of attrRules)
885 {
892 rule = rule.substr(1, rule.length - 2); 886 rule = rule.substr(1, rule.length - 2);
893 let separatorPos = rule.indexOf("="); 887 let separatorPos = rule.indexOf("=");
894 if (separatorPos > 0) { 888 if (separatorPos > 0)
889 {
895 rule = rule.replace(/=/, '="') + '"'; 890 rule = rule.replace(/=/, '="') + '"';
896 additional += "[" + rule + "]"; 891 additional += "[" + rule + "]";
897 } 892 }
898 else { 893 else
894 {
899 if (id) 895 if (id)
900 return new InvalidFilter(text, Utils.getString("filter_elemhide_dupl icate_id")); 896 return new InvalidFilter(text, Utils.getString("filter_elemhide_dupl icate_id"));
901 else 897
902 id = rule; 898 id = rule;
903 } 899 }
904 } 900 }
905 } 901 }
906 902
907 if (id) 903 if (id)
908 selector = tagName + "." + id + additional + "," + tagName + "#" + id + ad ditional; 904 selector = tagName + "." + id + additional + "," + tagName + "#" + id + ad ditional;
909 else if (tagName || additional) 905 else if (tagName || additional)
910 selector = tagName + additional; 906 selector = tagName + additional;
911 else 907 else
912 return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriteria ")); 908 return new InvalidFilter(text, Utils.getString("filter_elemhide_nocriteria "));
913 } 909 }
910
914 if (isException) 911 if (isException)
915 return new ElemHideException(text, domain, selector); 912 return new ElemHideException(text, domain, selector);
916 else 913
917 { 914 let match = Filter.csspropertyRegExp.exec(selector);
918 if (Filter.csspropertyRegExp.test(selector)) 915 if (match)
919 { 916 {
920 // CSS property filters are inefficient so we need to make sure that 917 // CSS property filters are inefficient so we need to make sure that
921 // they're only applied if they specify active domains 918 // they're only applied if they specify active domains
922 if (/,[^~]/.test("," + domain)) 919 if (!/,[^~][^,.]*\.[^,]/.test("," + domain))
Sebastian Noack 2015/05/05 15:47:02 I wonder whether we should also look for at least
Thomas Greiner 2015/05/06 12:08:32 Good point but note that this still doesn't cover
Sebastian Noack 2015/05/06 13:07:48 Hmm, if we want to do it properly, I suppose we ha
923 return new CSSPropertyFilter(text, domain, selector); 920 return new InvalidFilter(text, Utils.getString("filter_cssproperty_nodomai n"));
924 else 921
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
925 return new InvalidFilter(text, Utils.getString("filter_cssproperty_nodom ain")); 922 return new CSSPropertyFilter(text, domain, selector, match[2],
926 } 923 selector.substr(0, match.index),
927 else 924 selector.substr(match.index + match[0].length));
Sebastian Noack 2015/05/05 15:47:02 Nit: Redundant else statement.
Thomas Greiner 2015/05/06 12:08:32 Done.
928 return new ElemHideFilter(text, domain, selector); 925 }
929 } 926
927 return new ElemHideFilter(text, domain, selector);
930 }; 928 };
931 929
932 /** 930 /**
933 * Class for element hiding filters 931 * Class for element hiding filters
934 * @param {String} text see Filter() 932 * @param {String} text see Filter()
935 * @param {String} domains see ElemHideBase() 933 * @param {String} domains see ElemHideBase()
936 * @param {String} selector see ElemHideBase() 934 * @param {String} selector see ElemHideBase()
937 * @constructor 935 * @constructor
938 * @augments ElemHideBase 936 * @augments ElemHideBase
939 */ 937 */
(...skipping 22 matching lines...) Expand all
962 } 960 }
963 exports.ElemHideException = ElemHideException; 961 exports.ElemHideException = ElemHideException;
964 962
965 ElemHideException.prototype = 963 ElemHideException.prototype =
966 { 964 {
967 __proto__: ElemHideBase.prototype 965 __proto__: ElemHideBase.prototype
968 }; 966 };
969 967
970 /** 968 /**
971 * Class for CSS property filters 969 * Class for CSS property filters
972 * @param {String} text see Filter() 970 * @param {String} text see Filter()
973 * @param {String} domains see ElemHideBase() 971 * @param {String} domains see ElemHideBase()
974 * @param {String} selector see ElemHideBase() 972 * @param {String} selector see ElemHideBase()
973 * @param {String} regexpSource see CSSPropertyFilter.regexpSource
974 * @param {String} selectorPrefix see CSSPropertyFilter.selectorPrefix
975 * @param {String} selectorSuffix see CSSPropertyFilter.selectorSuffix
975 * @constructor 976 * @constructor
976 * @augments ElemHideBase 977 * @augments ElemHideBase
977 */ 978 */
978 function CSSPropertyFilter(text, domains, selector) 979 function CSSPropertyFilter(text, domains, selector, regexpSource,
980 selectorPrefix, selectorSuffix)
979 { 981 {
980 ElemHideBase.call(this, text, domains, selector); 982 ElemHideBase.call(this, text, domains, selector);
981 983
982 let properties; 984 this.regexpSource = regexpSource;
983 [properties, , this.regexpSource] = selector.match(Filter.csspropertyRegExp); 985 this.selectorPrefix = selectorPrefix;
984 [this.selectorPrefix, this.selectorSuffix] = selector.split(properties); 986 this.selectorSuffix = selectorSuffix;
985 } 987 }
986 exports.CSSPropertyFilter = CSSPropertyFilter; 988 exports.CSSPropertyFilter = CSSPropertyFilter;
987 989
988 CSSPropertyFilter.prototype = 990 CSSPropertyFilter.prototype =
989 { 991 {
990 __proto__: ElemHideBase.prototype, 992 __proto__: ElemHideBase.prototype,
991 993
992 /** 994 /**
993 * Expression from which a regular expression should be generated for matching 995 * Expression from which a regular expression should be generated for matching
994 * CSS properties - for delayed creation of the regexp property 996 * CSS properties - for delayed creation of the regexpString property
995 * @type String 997 * @type String
996 */ 998 */
997 regexpSource: null, 999 regexpSource: null,
998 /** 1000 /**
999 * Substring of CSS selector before properties for the HTML elements that 1001 * Substring of CSS selector before properties for the HTML elements that
1000 * should be hidden 1002 * should be hidden
1001 * @type String 1003 * @type String
1002 */ 1004 */
1003 selectorPrefix: null, 1005 selectorPrefix: null,
1004 /** 1006 /**
1005 * Substring of CSS selector after properties for the HTML elements that 1007 * Substring of CSS selector after properties for the HTML elements that
1006 * should be hidden 1008 * should be hidden
1007 * @type String 1009 * @type String
1008 */ 1010 */
1009 selectorSuffix: null, 1011 selectorSuffix: null,
1010 1012
1011 /** 1013 /**
1012 * Regular expression to be used when testing CSS properties against 1014 * Raw regular expression string to be used when testing CSS properties
1013 * this filter 1015 * against this filter
1014 * @type RegExp 1016 * @type String
1015 */ 1017 */
1016 get regexp() 1018 get regexpString()
Sebastian Noack 2015/05/05 15:47:02 Hmm, this is almost the same code we already have
Thomas Greiner 2015/05/06 12:08:32 You're right, the issue description doesn't explic
Sebastian Noack 2015/05/06 13:07:48 Well, objects get serialized when passed to conten
1017 { 1019 {
1018 // Despite this property being cached, the getter is called 1020 // Despite this property being cached, the getter is called
1019 // several times on Safari, due to WebKit bug 132872 1021 // several times on Safari, due to WebKit bug 132872
1020 let prop = Object.getOwnPropertyDescriptor(this, "regexp"); 1022 let prop = Object.getOwnPropertyDescriptor(this, "regexpString");
1021 if (prop) 1023 if (prop)
1022 return prop.value; 1024 return prop.value;
1023 1025
1024 let source = Filter.toRegExp(this.regexpSource); 1026 let regexp = Filter.toRegExp(this.regexpSource);
1025 let regexp = new RegExp(source, ""); 1027 Object.defineProperty(this, "regexpString", {value: regexp});
1026 Object.defineProperty(this, "regexp", {value: regexp});
1027 return regexp; 1028 return regexp;
1028 } 1029 }
1029 }; 1030 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld