| 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-2017 eyeo GmbH | 3 * Copyright (C) 2006-2017 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 64 } | 64 } |
| 65 } | 65 } |
| 66 | 66 |
| 67 function escapeRegExp(s) | 67 function escapeRegExp(s) |
| 68 { | 68 { |
| 69 return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); | 69 return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); |
| 70 } | 70 } |
| 71 | 71 |
| 72 function matchDomain(domain) | 72 function matchDomain(domain) |
| 73 { | 73 { |
| 74 if (!domain) |
| 75 return "^https?://"; |
| 76 |
| 74 return "^https?://([^/:]*\\.)?" + escapeRegExp(domain).toLowerCase() + "[/:]"; | 77 return "^https?://([^/:]*\\.)?" + escapeRegExp(domain).toLowerCase() + "[/:]"; |
| 75 } | 78 } |
| 76 | 79 |
| 77 function getURLSchemes(contentType) | 80 function getURLSchemes(contentType) |
| 78 { | 81 { |
| 79 // If the given content type includes all supported URL schemes, simply | 82 // If the given content type includes all supported URL schemes, simply |
| 80 // return a single generic URL scheme pattern. This minimizes the size of the | 83 // return a single generic URL scheme pattern. This minimizes the size of the |
| 81 // generated rule set. The downside to this is that it will also match | 84 // generated rule set. The downside to this is that it will also match |
| 82 // schemes that we do not want to match (e.g. "ftp://"), but this can be | 85 // schemes that we do not want to match (e.g. "ftp://"), but this can be |
| 83 // mitigated by adding exceptions for those schemes. | 86 // mitigated by adding exceptions for those schemes. |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 if (parsed.justHostname) | 125 if (parsed.justHostname) |
| 123 domains.add(parsed.hostname); | 126 domains.add(parsed.hostname); |
| 124 } | 127 } |
| 125 return domains; | 128 return domains; |
| 126 } | 129 } |
| 127 | 130 |
| 128 function convertElemHideFilter(filter, elemhideSelectorExceptions) | 131 function convertElemHideFilter(filter, elemhideSelectorExceptions) |
| 129 { | 132 { |
| 130 let included = []; | 133 let included = []; |
| 131 let excluded = []; | 134 let excluded = []; |
| 132 let rules = []; | |
| 133 | 135 |
| 134 parseDomains(filter.domains, included, excluded); | 136 parseDomains(filter.domains, included, excluded); |
| 135 | 137 |
| 136 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions)) | 138 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions)) |
| 137 return {matchDomains: included.map(matchDomain), selector: filter.selector}; | 139 return {matchDomains: included, selector: filter.selector}; |
| 138 } | 140 } |
| 139 | 141 |
| 140 /** | 142 /** |
| 141 * Parse the given filter "regexpSource" string. Producing a regular expression, | 143 * Parse the given filter "regexpSource" string. Producing a regular expression, |
| 142 * extracting the hostname (if any), deciding if the regular expression is safe | 144 * extracting the hostname (if any), deciding if the regular expression is safe |
| 143 * to be converted + matched as lower case and noting if the source contains | 145 * to be converted + matched as lower case and noting if the source contains |
| 144 * anything after the hostname.) | 146 * anything after the hostname.) |
| 145 * | 147 * |
| 146 * @param {string} text regexpSource property of a filter | 148 * @param {string} text regexpSource property of a filter |
| 147 * @param {string} urlScheme The URL scheme to use in the regular expression | 149 * @param {string} urlScheme The URL scheme to use in the regular expression |
| (...skipping 431 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 579 { | 581 { |
| 580 newSelector.push(selector.substring(i, pos.start)); | 582 newSelector.push(selector.substring(i, pos.start)); |
| 581 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']'); | 583 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']'); |
| 582 i = pos.end; | 584 i = pos.end; |
| 583 } | 585 } |
| 584 newSelector.push(selector.substring(i)); | 586 newSelector.push(selector.substring(i)); |
| 585 | 587 |
| 586 return newSelector.join(""); | 588 return newSelector.join(""); |
| 587 } | 589 } |
| 588 | 590 |
| 589 function addCSSRules(rules, selectors, matchDomain, exceptionDomains) | 591 function addCSSRules(rules, selectors, domain, exceptionDomains) |
| 590 { | 592 { |
| 591 let unlessDomain = exceptionDomains.size > 0 ? [] : null; | 593 let unlessDomain = exceptionDomains.size > 0 ? [] : null; |
| 592 | 594 |
| 593 exceptionDomains.forEach(name => unlessDomain.push("*" + name)); | 595 exceptionDomains.forEach(name => |
| 596 { |
| 597 // For domain-specific filters, include the exception domains only if |
| 598 // they're subdomains of the given domain. |
| 599 if (!domain || name.substr(-domain.length - 1) == "." + domain) |
| 600 unlessDomain.push("*" + name); |
| 601 }); |
| 594 | 602 |
| 595 while (selectors.length) | 603 while (selectors.length) |
| 596 { | 604 { |
| 597 let selector = selectors.splice(0, selectorLimit).join(", "); | 605 let selector = selectors.splice(0, selectorLimit).join(", "); |
| 598 | 606 |
| 599 // As of Safari 9.0 element IDs are matched as lowercase. We work around | 607 // As of Safari 9.0 element IDs are matched as lowercase. We work around |
| 600 // this by converting to the attribute format [id="elementID"] | 608 // this by converting to the attribute format [id="elementID"] |
| 601 selector = convertIDSelectorsToAttributeSelectors(selector); | 609 selector = convertIDSelectorsToAttributeSelectors(selector); |
| 602 | 610 |
| 603 let rule = { | 611 let rule = { |
| 604 trigger: {"url-filter": matchDomain, | 612 trigger: {"url-filter": matchDomain(domain), |
| 605 "url-filter-is-case-sensitive": true}, | 613 "url-filter-is-case-sensitive": true}, |
| 606 action: {type: "css-display-none", | 614 action: {type: "css-display-none", |
| 607 selector: selector} | 615 selector: selector} |
| 608 }; | 616 }; |
| 609 | 617 |
| 610 if (unlessDomain) | 618 if (unlessDomain) |
| 611 rule.trigger["unless-domain"] = unlessDomain; | 619 rule.trigger["unless-domain"] = unlessDomain; |
| 612 | 620 |
| 613 rules.push(rule); | 621 rules.push(rule); |
| 614 } | 622 } |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 721 // --max_old_space_size=4096 | 729 // --max_old_space_size=4096 |
| 722 let elemhideExceptionDomains = extractFilterDomains(this.elemhideExceptions); | 730 let elemhideExceptionDomains = extractFilterDomains(this.elemhideExceptions); |
| 723 | 731 |
| 724 let genericSelectorExceptionDomains = | 732 let genericSelectorExceptionDomains = |
| 725 extractFilterDomains(this.generichideExceptions); | 733 extractFilterDomains(this.generichideExceptions); |
| 726 elemhideExceptionDomains.forEach(name => | 734 elemhideExceptionDomains.forEach(name => |
| 727 { | 735 { |
| 728 genericSelectorExceptionDomains.add(name); | 736 genericSelectorExceptionDomains.add(name); |
| 729 }); | 737 }); |
| 730 | 738 |
| 731 addCSSRules(rules, genericSelectors, "^https?://", | 739 addCSSRules(rules, genericSelectors, null, genericSelectorExceptionDomains); |
| 732 genericSelectorExceptionDomains); | 740 |
| 741 // Filter out whitelisted domains. |
| 742 elemhideExceptionDomains.forEach(domain => |
| 743 groupedElemhideFilters.delete(domain)); |
| 733 | 744 |
| 734 groupedElemhideFilters.forEach((selectors, matchDomain) => | 745 groupedElemhideFilters.forEach((selectors, matchDomain) => |
| 735 { | 746 { |
| 736 addCSSRules(rules, selectors, matchDomain, elemhideExceptionDomains); | 747 addCSSRules(rules, selectors, matchDomain, elemhideExceptionDomains); |
| 737 }); | 748 }); |
| 738 | 749 |
| 739 let requestFilterExceptionDomains = []; | 750 let requestFilterExceptionDomains = []; |
| 740 for (let filter of this.genericblockExceptions) | 751 for (let filter of this.genericblockExceptions) |
| 741 { | 752 { |
| 742 let parsed = parseFilterRegexpSource(filter.regexpSource); | 753 let parsed = parseFilterRegexpSource(filter.regexpSource); |
| 743 if (parsed.hostname) | 754 if (parsed.hostname) |
| 744 requestFilterExceptionDomains.push(parsed.hostname); | 755 requestFilterExceptionDomains.push(parsed.hostname); |
| 745 } | 756 } |
| 746 | 757 |
| 747 for (let filter of this.requestFilters) | 758 for (let filter of this.requestFilters) |
| 748 { | 759 { |
| 749 convertFilterAddRules(rules, filter, "block", true, | 760 convertFilterAddRules(rules, filter, "block", true, |
| 750 requestFilterExceptionDomains); | 761 requestFilterExceptionDomains); |
| 751 } | 762 } |
| 752 | 763 |
| 753 for (let filter of this.requestExceptions) | 764 for (let filter of this.requestExceptions) |
| 754 convertFilterAddRules(rules, filter, "ignore-previous-rules", true); | 765 convertFilterAddRules(rules, filter, "ignore-previous-rules", true); |
| 755 | 766 |
| 756 return rules; | 767 return rules; |
| 757 }; | 768 }; |
| OLD | NEW |