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

Side by Side Diff: lib/filterClasses.js

Issue 4559243822759936: Issue 431/432 - Remove special handling for the $sitekey option (Closed)
Patch Set: Made changes for WebKit bug 132872 Created Sept. 1, 2014, 3:27 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/contentPolicy.js ('k') | lib/matcher.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 208
209 /** 209 /**
210 * See Filter.serialize() 210 * See Filter.serialize()
211 */ 211 */
212 serialize: function(buffer) {} 212 serialize: function(buffer) {}
213 }; 213 };
214 214
215 /** 215 /**
216 * Abstract base class for filters that can get hits 216 * Abstract base class for filters that can get hits
217 * @param {String} text see Filter() 217 * @param {String} text see Filter()
218 * @param {String} domains (optional) Domains that the filter is restricted to separated by domainSeparator e.g. "foo.com|bar.com|~baz.com" 218 * @param {String} [domains] Domains that the filter is restricted to separated by domainSeparator e.g. "foo.com|bar.com|~baz.com"
219 * @constructor 219 * @constructor
220 * @augments Filter 220 * @augments Filter
221 */ 221 */
222 function ActiveFilter(text, domains) 222 function ActiveFilter(text, domains)
223 { 223 {
224 Filter.call(this, text); 224 Filter.call(this, text);
225 225
226 this.domainSource = domains; 226 this.domainSource = domains;
227 } 227 }
228 exports.ActiveFilter = ActiveFilter; 228 exports.ActiveFilter = ActiveFilter;
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 } 380 }
381 381
382 this.domainSource = null; 382 this.domainSource = null;
383 } 383 }
384 384
385 Object.defineProperty(this, "domains", {value: domains, enumerable: true}); 385 Object.defineProperty(this, "domains", {value: domains, enumerable: true});
386 return this.domains; 386 return this.domains;
387 }, 387 },
388 388
389 /** 389 /**
390 * Array containing public keys of websites that this filter should apply to
391 * @type Array of String
392 */
393 sitekeys: null,
394
395 /**
390 * Checks whether this filter is active on a domain. 396 * Checks whether this filter is active on a domain.
397 * @param {String} docDomain domain name of the document that loads the URL
398 * @param {String} [sitekey] public key provided by the document
399 * @return {Boolean} true in case of the filter being active
391 */ 400 */
392 isActiveOnDomain: function(/**String*/ docDomain) /**Boolean*/ 401 isActiveOnDomain: function(docDomain, sitekey)
393 { 402 {
403 // Sitekeys are case-sensitive so we shouldn't convert them to upper-case to avoid false
404 // positives here. Instead we need to change the way filter options are pars ed.
405 if (this.sitekeys && (!sitekey || this.sitekeys.indexOf(sitekey.toUpperCase( )) < 0))
406 return false;
407
394 // If no domains are set the rule matches everywhere 408 // If no domains are set the rule matches everywhere
395 if (!this.domains) 409 if (!this.domains)
396 return true; 410 return true;
397 411
398 // If the document has no host name, match only if the filter isn't restrict ed to specific domains 412 // If the document has no host name, match only if the filter isn't restrict ed to specific domains
399 if (!docDomain) 413 if (!docDomain)
400 return this.domains[""]; 414 return this.domains[""];
401 415
402 if (this.ignoreTrailingDot) 416 if (this.ignoreTrailingDot)
403 docDomain = docDomain.replace(/\.+$/, ""); 417 docDomain = docDomain.replace(/\.+$/, "");
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 if (this._lastHit) 464 if (this._lastHit)
451 buffer.push("lastHit=" + this._lastHit); 465 buffer.push("lastHit=" + this._lastHit);
452 } 466 }
453 } 467 }
454 }; 468 };
455 469
456 /** 470 /**
457 * Abstract base class for RegExp-based filters 471 * Abstract base class for RegExp-based filters
458 * @param {String} text see Filter() 472 * @param {String} text see Filter()
459 * @param {String} regexpSource filter part that the regular expression should b e build from 473 * @param {String} regexpSource filter part that the regular expression should b e build from
460 * @param {Number} contentType (optional) Content types the filter applies to, combination of values from RegExpFilter.typeMap 474 * @param {Number} [contentType] Content types the filter applies to, combinatio n of values from RegExpFilter.typeMap
461 * @param {Boolean} matchCase (optional) Defines whether the filter should dis tinguish between lower and upper case letters 475 * @param {Boolean} [matchCase] Defines whether the filter should distinguish be tween lower and upper case letters
462 * @param {String} domains (optional) Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com" 476 * @param {String} [domains] Domains that the filter is restricted to, e.g. "foo .com|bar.com|~baz.com"
463 * @param {Boolean} thirdParty (optional) Defines whether the filter should app ly to third-party or first-party content only 477 * @param {Boolean} [thirdParty] Defines whether the filter should apply to thir d-party or first-party content only
478 * @param {String} [sitekeys] Public keys of websites that this filter should ap ply to
464 * @constructor 479 * @constructor
465 * @augments ActiveFilter 480 * @augments ActiveFilter
466 */ 481 */
467 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, third Party) 482 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, third Party, sitekeys)
468 { 483 {
469 ActiveFilter.call(this, text, domains); 484 ActiveFilter.call(this, text, domains, sitekeys);
470 485
471 if (contentType != null) 486 if (contentType != null)
472 this.contentType = contentType; 487 this.contentType = contentType;
473 if (matchCase) 488 if (matchCase)
474 this.matchCase = matchCase; 489 this.matchCase = matchCase;
475 if (thirdParty != null) 490 if (thirdParty != null)
476 this.thirdParty = thirdParty; 491 this.thirdParty = thirdParty;
492 if (sitekeys != null)
493 this.sitekeySource = sitekeys;
477 494
478 if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpS ource.length - 1] == "/") 495 if (regexpSource.length >= 2 && regexpSource[0] == "/" && regexpSource[regexpS ource.length - 1] == "/")
479 { 496 {
480 // The filter is a regular expression - convert it immediately to catch synt ax errors 497 // The filter is a regular expression - convert it immediately to catch synt ax errors
481 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), thi s.matchCase ? "" : "i"); 498 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), thi s.matchCase ? "" : "i");
482 Object.defineProperty(this, "regexp", {value: regexp}); 499 Object.defineProperty(this, "regexp", {value: regexp});
483 } 500 }
484 else 501 else
485 { 502 {
486 // No need to convert this filter to regular expression yet, do it on demand 503 // No need to convert this filter to regular expression yet, do it on demand
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 * @type Boolean 571 * @type Boolean
555 */ 572 */
556 matchCase: false, 573 matchCase: false,
557 /** 574 /**
558 * Defines whether the filter should apply to third-party or first-party conte nt only. Can be null (apply to all content). 575 * Defines whether the filter should apply to third-party or first-party conte nt only. Can be null (apply to all content).
559 * @type Boolean 576 * @type Boolean
560 */ 577 */
561 thirdParty: null, 578 thirdParty: null,
562 579
563 /** 580 /**
581 * String that the sitekey property should be generated from
582 * @type String
583 */
584 sitekeySource: null,
585
586 /**
587 * Array containing public keys of websites that this filter should apply to
588 * @type Array of String
589 */
590 get sitekeys()
591 {
592 // Despite this property being cached, the getter is called
593 // several times on Safari, due to WebKit bug 132872
594 let prop = Object.getOwnPropertyDescriptor(this, "sitekeys");
595 if (prop)
596 return prop.value;
597
598 let sitekeys = null;
599
600 if (this.sitekeySource)
601 {
602 sitekeys = this.sitekeySource.split("|");
603 this.sitekeySource = null;
604 }
605
606 Object.defineProperty(this, "sitekeys", {value: sitekeys, enumerable: true}) ;
607 return this.sitekeys;
608 },
609
610 /**
564 * Tests whether the URL matches this filter 611 * Tests whether the URL matches this filter
565 * @param {String} location URL to be tested 612 * @param {String} location URL to be tested
566 * @param {String} contentType content type identifier of the URL 613 * @param {String} contentType content type identifier of the URL
567 * @param {String} docDomain domain name of the document that loads the URL 614 * @param {String} docDomain domain name of the document that loads the URL
568 * @param {Boolean} thirdParty should be true if the URL is a third-party requ est 615 * @param {Boolean} thirdParty should be true if the URL is a third-party requ est
616 * @param {String} sitekey public key provided by the document
569 * @return {Boolean} true in case of a match 617 * @return {Boolean} true in case of a match
570 */ 618 */
571 matches: function(location, contentType, docDomain, thirdParty) 619 matches: function(location, contentType, docDomain, thirdParty, sitekey)
572 { 620 {
573 if (this.regexp.test(location) && 621 if (this.regexp.test(location) &&
574 (RegExpFilter.typeMap[contentType] & this.contentType) != 0 && 622 (RegExpFilter.typeMap[contentType] & this.contentType) != 0 &&
575 (this.thirdParty == null || this.thirdParty == thirdParty) && 623 (this.thirdParty == null || this.thirdParty == thirdParty) &&
576 this.isActiveOnDomain(docDomain)) 624 this.isActiveOnDomain(docDomain, sitekey))
577 { 625 {
578 return true; 626 return true;
579 } 627 }
580 628
581 return false; 629 return false;
582 } 630 }
583 }; 631 };
584 632
585 // Required to optimize Matcher, see also RegExpFilter.prototype.length 633 // Required to optimize Matcher, see also RegExpFilter.prototype.length
586 Object.defineProperty(RegExpFilter.prototype, "0", 634 Object.defineProperty(RegExpFilter.prototype, "0",
(...skipping 11 matching lines...) Expand all
598 let origText = text; 646 let origText = text;
599 if (text.indexOf("@@") == 0) 647 if (text.indexOf("@@") == 0)
600 { 648 {
601 blocking = false; 649 blocking = false;
602 text = text.substr(2); 650 text = text.substr(2);
603 } 651 }
604 652
605 let contentType = null; 653 let contentType = null;
606 let matchCase = null; 654 let matchCase = null;
607 let domains = null; 655 let domains = null;
608 let siteKeys = null; 656 let sitekeys = null;
609 let thirdParty = null; 657 let thirdParty = null;
610 let collapse = null; 658 let collapse = null;
611 let options; 659 let options;
612 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null); 660 let match = (text.indexOf("$") >= 0 ? Filter.optionsRegExp.exec(text) : null);
613 if (match) 661 if (match)
614 { 662 {
615 options = match[1].toUpperCase().split(","); 663 options = match[1].toUpperCase().split(",");
616 text = match.input.substr(0, match.index); 664 text = match.input.substr(0, match.index);
617 for (let option of options) 665 for (let option of options)
618 { 666 {
(...skipping 25 matching lines...) Expand all
644 domains = value; 692 domains = value;
645 else if (option == "THIRD_PARTY") 693 else if (option == "THIRD_PARTY")
646 thirdParty = true; 694 thirdParty = true;
647 else if (option == "~THIRD_PARTY") 695 else if (option == "~THIRD_PARTY")
648 thirdParty = false; 696 thirdParty = false;
649 else if (option == "COLLAPSE") 697 else if (option == "COLLAPSE")
650 collapse = true; 698 collapse = true;
651 else if (option == "~COLLAPSE") 699 else if (option == "~COLLAPSE")
652 collapse = false; 700 collapse = false;
653 else if (option == "SITEKEY" && typeof value != "undefined") 701 else if (option == "SITEKEY" && typeof value != "undefined")
654 siteKeys = value.split(/\|/); 702 sitekeys = value;
655 else 703 else
656 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e()); 704 return new InvalidFilter(origText, "Unknown option " + option.toLowerCas e());
657 } 705 }
658 } 706 }
659 707
660 if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.D OCUMENT)) && 708 if (!blocking && (contentType == null || (contentType & RegExpFilter.typeMap.D OCUMENT)) &&
661 (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text )) 709 (!options || options.indexOf("DOCUMENT") < 0) && !/^\|?[\w\-]+:/.test(text ))
662 { 710 {
663 // Exception filters shouldn't apply to pages by default unless they start w ith a protocol name 711 // Exception filters shouldn't apply to pages by default unless they start w ith a protocol name
664 if (contentType == null) 712 if (contentType == null)
665 contentType = RegExpFilter.prototype.contentType; 713 contentType = RegExpFilter.prototype.contentType;
666 contentType &= ~RegExpFilter.typeMap.DOCUMENT; 714 contentType &= ~RegExpFilter.typeMap.DOCUMENT;
667 } 715 }
668 if (!blocking && siteKeys)
669 contentType = RegExpFilter.typeMap.DOCUMENT;
670 716
671 try 717 try
672 { 718 {
673 if (blocking) 719 if (blocking)
674 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, collapse); 720 return new BlockingFilter(origText, text, contentType, matchCase, domains, thirdParty, sitekeys, collapse);
675 else 721 else
676 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, siteKeys); 722 return new WhitelistFilter(origText, text, contentType, matchCase, domains , thirdParty, sitekeys);
677 } 723 }
678 catch (e) 724 catch (e)
679 { 725 {
680 return new InvalidFilter(origText, e); 726 return new InvalidFilter(origText, e);
681 } 727 }
682 } 728 }
683 729
684 /** 730 /**
685 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks 731 * Maps type strings like "SCRIPT" or "OBJECT" to bit masks
686 */ 732 */
(...skipping 23 matching lines...) Expand all
710 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFi lter.typeMap.POPUP); 756 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.ELEMHIDE | RegExpFi lter.typeMap.POPUP);
711 757
712 /** 758 /**
713 * Class for blocking filters 759 * Class for blocking filters
714 * @param {String} text see Filter() 760 * @param {String} text see Filter()
715 * @param {String} regexpSource see RegExpFilter() 761 * @param {String} regexpSource see RegExpFilter()
716 * @param {Number} contentType see RegExpFilter() 762 * @param {Number} contentType see RegExpFilter()
717 * @param {Boolean} matchCase see RegExpFilter() 763 * @param {Boolean} matchCase see RegExpFilter()
718 * @param {String} domains see RegExpFilter() 764 * @param {String} domains see RegExpFilter()
719 * @param {Boolean} thirdParty see RegExpFilter() 765 * @param {Boolean} thirdParty see RegExpFilter()
766 * @param {String} sitekeys see RegExpFilter()
720 * @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null 767 * @param {Boolean} collapse defines whether the filter should collapse blocked content, can be null
721 * @constructor 768 * @constructor
722 * @augments RegExpFilter 769 * @augments RegExpFilter
723 */ 770 */
724 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi rdParty, collapse) 771 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi rdParty, sitekeys, collapse)
725 { 772 {
726 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty); 773 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, sitekeys);
727 774
728 this.collapse = collapse; 775 this.collapse = collapse;
729 } 776 }
730 exports.BlockingFilter = BlockingFilter; 777 exports.BlockingFilter = BlockingFilter;
731 778
732 BlockingFilter.prototype = 779 BlockingFilter.prototype =
733 { 780 {
734 __proto__: RegExpFilter.prototype, 781 __proto__: RegExpFilter.prototype,
735 782
736 /** 783 /**
737 * Defines whether the filter should collapse blocked content. Can be null (us e the global preference). 784 * Defines whether the filter should collapse blocked content. Can be null (us e the global preference).
738 * @type Boolean 785 * @type Boolean
739 */ 786 */
740 collapse: null 787 collapse: null
741 }; 788 };
742 789
743 /** 790 /**
744 * Class for whitelist filters 791 * Class for whitelist filters
745 * @param {String} text see Filter() 792 * @param {String} text see Filter()
746 * @param {String} regexpSource see RegExpFilter() 793 * @param {String} regexpSource see RegExpFilter()
747 * @param {Number} contentType see RegExpFilter() 794 * @param {Number} contentType see RegExpFilter()
748 * @param {Boolean} matchCase see RegExpFilter() 795 * @param {Boolean} matchCase see RegExpFilter()
749 * @param {String} domains see RegExpFilter() 796 * @param {String} domains see RegExpFilter()
750 * @param {Boolean} thirdParty see RegExpFilter() 797 * @param {Boolean} thirdParty see RegExpFilter()
751 * @param {String[]} siteKeys public keys of websites that this filter should ap ply to 798 * @param {String} sitekeys see RegExpFilter()
752 * @constructor 799 * @constructor
753 * @augments RegExpFilter 800 * @augments RegExpFilter
754 */ 801 */
755 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th irdParty, siteKeys) 802 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th irdParty, sitekeys)
756 { 803 {
757 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty); 804 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t hirdParty, sitekeys);
758
759 if (siteKeys != null)
760 this.siteKeys = siteKeys;
761 } 805 }
762 exports.WhitelistFilter = WhitelistFilter; 806 exports.WhitelistFilter = WhitelistFilter;
763 807
764 WhitelistFilter.prototype = 808 WhitelistFilter.prototype =
765 { 809 {
766 __proto__: RegExpFilter.prototype, 810 __proto__: RegExpFilter.prototype
767
768 /**
769 * List of public keys of websites that this filter should apply to
770 * @type String[]
771 */
772 siteKeys: null
773 } 811 }
774 812
775 /** 813 /**
776 * Base class for element hiding filters 814 * Base class for element hiding filters
777 * @param {String} text see Filter() 815 * @param {String} text see Filter()
778 * @param {String} domains (optional) Host names or domains the filter should be restricted to 816 * @param {String} [domains] Host names or domains the filter should be restrict ed to
779 * @param {String} selector CSS selector for the HTML elements that should be hidden 817 * @param {String} selector CSS selector for the HTML elements that should be hidden
780 * @constructor 818 * @constructor
781 * @augments ActiveFilter 819 * @augments ActiveFilter
782 */ 820 */
783 function ElemHideBase(text, domains, selector) 821 function ElemHideBase(text, domains, selector)
784 { 822 {
785 ActiveFilter.call(this, text, domains || null); 823 ActiveFilter.call(this, text, domains || null);
786 824
787 if (domains) 825 if (domains)
788 this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, " ").toLowerCase(); 826 this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, " ").toLowerCase();
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
902 function ElemHideException(text, domains, selector) 940 function ElemHideException(text, domains, selector)
903 { 941 {
904 ElemHideBase.call(this, text, domains, selector); 942 ElemHideBase.call(this, text, domains, selector);
905 } 943 }
906 exports.ElemHideException = ElemHideException; 944 exports.ElemHideException = ElemHideException;
907 945
908 ElemHideException.prototype = 946 ElemHideException.prototype =
909 { 947 {
910 __proto__: ElemHideBase.prototype 948 __proto__: ElemHideBase.prototype
911 }; 949 };
OLDNEW
« no previous file with comments | « lib/contentPolicy.js ('k') | lib/matcher.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld