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

Side by Side Diff: lib/abp2blocklist.js

Issue 29473555: Issue 5345 - Whitelist $elemhide and $generichide domains where possible (Closed) Base URL: https://hg.adblockplus.org/abp2blocklist
Patch Set: Rebase Created July 11, 2017, 5:28 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 | « abp2blocklist.js ('k') | test/abp2blocklist.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 <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 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
71 71
72 for (let name of list) 72 for (let name of list)
73 { 73 {
74 if (name.length > suffixLength && name.slice(-suffixLength) == "." + domain) 74 if (name.length > suffixLength && name.slice(-suffixLength) == "." + domain)
75 subdomains.push(name.slice(0, -suffixLength)); 75 subdomains.push(name.slice(0, -suffixLength));
76 } 76 }
77 77
78 return subdomains; 78 return subdomains;
79 } 79 }
80 80
81 function extractFilterDomains(filters)
82 {
83 let domains = new Set();
84 for (let filter of filters)
85 {
86 let parsed = parseFilterRegexpSource(filter.regexpSource);
87 if (parsed.justHostname)
88 domains.add(parsed.hostname);
89 }
90 return domains;
91 }
92
81 function convertElemHideFilter(filter, elemhideSelectorExceptions) 93 function convertElemHideFilter(filter, elemhideSelectorExceptions)
82 { 94 {
83 let included = []; 95 let included = [];
84 let excluded = []; 96 let excluded = [];
85 let rules = []; 97 let rules = [];
86 98
87 parseDomains(filter.domains, included, excluded); 99 parseDomains(filter.domains, included, excluded);
88 100
89 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions)) 101 if (excluded.length == 0 && !(filter.selector in elemhideSelectorExceptions))
90 return {matchDomains: included.map(matchDomain), selector: filter.selector}; 102 return {matchDomains: included.map(matchDomain), selector: filter.selector};
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 // If we're currently inside the hostname we have to be careful not to 147 // If we're currently inside the hostname we have to be careful not to
136 // escape any characters until after we have converted it to punycode. 148 // escape any characters until after we have converted it to punycode.
137 if (hostnameStart != null && !hostnameFinished) 149 if (hostnameStart != null && !hostnameFinished)
138 { 150 {
139 let endingChar = (c == "*" || c == "^" || 151 let endingChar = (c == "*" || c == "^" ||
140 c == "?" || c == "/" || c == "|"); 152 c == "?" || c == "/" || c == "|");
141 if (!endingChar && i != lastIndex) 153 if (!endingChar && i != lastIndex)
142 continue; 154 continue;
143 155
144 hostname = punycode.toASCII( 156 hostname = punycode.toASCII(
145 characters.slice(hostnameStart, endingChar ? i : i + 1).join("") 157 characters.slice(hostnameStart, endingChar ? i : i + 1).join("")
Manish Jethani 2017/07/12 08:59:56 This was the only conflict during rebase, since te
158 .toLowerCase()
146 ); 159 );
147 hostnameFinished = justHostname = true; 160 hostnameFinished = justHostname = true;
148 regexp.push(escapeRegExp(hostname)); 161 regexp.push(escapeRegExp(hostname));
149 if (!endingChar) 162 if (!endingChar)
150 break; 163 break;
151 } 164 }
152 165
153 switch (c) 166 switch (c)
154 { 167 {
155 case "*": 168 case "*":
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 { 410 {
398 newSelector.push(selector.substring(i, pos.start)); 411 newSelector.push(selector.substring(i, pos.start));
399 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']'); 412 newSelector.push('[id=', selector.substring(pos.start + 1, pos.end), ']');
400 i = pos.end; 413 i = pos.end;
401 } 414 }
402 newSelector.push(selector.substring(i)); 415 newSelector.push(selector.substring(i));
403 416
404 return newSelector.join(""); 417 return newSelector.join("");
405 } 418 }
406 419
407 function addCSSRules(rules, selectors, matchDomain) 420 function addCSSRules(rules, selectors, matchDomain, exceptionDomains)
408 { 421 {
422 let unlessDomain = exceptionDomains.size > 0 ? [] : null;
423
424 exceptionDomains.forEach(name => unlessDomain.push("*" + name));
425
409 while (selectors.length) 426 while (selectors.length)
410 { 427 {
411 let selector = selectors.splice(0, selectorLimit).join(", "); 428 let selector = selectors.splice(0, selectorLimit).join(", ");
412 429
413 // As of Safari 9.0 element IDs are matched as lowercase. We work around 430 // As of Safari 9.0 element IDs are matched as lowercase. We work around
414 // this by converting to the attribute format [id="elementID"] 431 // this by converting to the attribute format [id="elementID"]
415 selector = convertIDSelectorsToAttributeSelectors(selector); 432 selector = convertIDSelectorsToAttributeSelectors(selector);
416 433
417 rules.push({ 434 let rule = {
418 trigger: {"url-filter": matchDomain, 435 trigger: {"url-filter": matchDomain,
419 "url-filter-is-case-sensitive": true}, 436 "url-filter-is-case-sensitive": true},
420 action: {type: "css-display-none", 437 action: {type: "css-display-none",
421 selector: selector} 438 selector: selector}
422 }); 439 };
440
441 if (unlessDomain)
442 rule.trigger["unless-domain"] = unlessDomain;
443
444 rules.push(rule);
423 } 445 }
424 } 446 }
425 447
426 let ContentBlockerList = 448 let ContentBlockerList =
427 /** 449 /**
428 * Create a new Adblock Plus filter to content blocker list converter 450 * Create a new Adblock Plus filter to content blocker list converter
429 * 451 *
430 * @constructor 452 * @constructor
431 */ 453 */
432 exports.ContentBlockerList = function () 454 exports.ContentBlockerList = function ()
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
509 { 531 {
510 for (let matchDomain of result.matchDomains) 532 for (let matchDomain of result.matchDomains)
511 { 533 {
512 let group = groupedElemhideFilters.get(matchDomain) || []; 534 let group = groupedElemhideFilters.get(matchDomain) || [];
513 group.push(result.selector); 535 group.push(result.selector);
514 groupedElemhideFilters.set(matchDomain, group); 536 groupedElemhideFilters.set(matchDomain, group);
515 } 537 }
516 } 538 }
517 } 539 }
518 540
519 addCSSRules(rules, genericSelectors, "^https?://"); 541 // Separate out the element hiding exceptions that have only a hostname part
542 // from the rest. This allows us to implement a workaround for issue #5345
543 // (WebKit bug #167423), but as a bonus it also reduces the number of
544 // generated rules. The downside is that the exception will only apply to the
545 // top-level document, not to iframes. We have to live with this until the
546 // WebKit bug is fixed in all supported versions of Safari.
547 // https://bugs.webkit.org/show_bug.cgi?id=167423
548 //
549 // Note that as a result of this workaround we end up with a huge rule set in
550 // terms of the amount of memory used. This can cause Node.js to throw
551 // "JavaScript heap out of memory". To avoid this, call Node.js with
552 // --max_old_space_size=4096
553 let elemhideExceptionDomains = extractFilterDomains(this.elemhideExceptions);
520 554
521 // Right after the generic element hiding filters, add the exceptions that 555 let genericSelectorExceptionDomains =
522 // should apply only to those filters. 556 extractFilterDomains(this.generichideExceptions);
523 for (let filter of this.generichideExceptions) 557 elemhideExceptionDomains.forEach(name =>
524 convertFilterAddRules(rules, filter, "ignore-previous-rules", false); 558 {
559 genericSelectorExceptionDomains.add(name);
560 });
561
562 addCSSRules(rules, genericSelectors, "^https?://",
563 genericSelectorExceptionDomains);
525 564
526 groupedElemhideFilters.forEach((selectors, matchDomain) => 565 groupedElemhideFilters.forEach((selectors, matchDomain) =>
527 { 566 {
528 addCSSRules(rules, selectors, matchDomain); 567 addCSSRules(rules, selectors, matchDomain, elemhideExceptionDomains);
529 }); 568 });
530 569
531 for (let filter of this.elemhideExceptions)
532 convertFilterAddRules(rules, filter, "ignore-previous-rules", false);
533
534 let requestFilterExceptionDomains = []; 570 let requestFilterExceptionDomains = [];
535 for (let filter of this.genericblockExceptions) 571 for (let filter of this.genericblockExceptions)
536 { 572 {
537 let parsed = parseFilterRegexpSource(filter.regexpSource); 573 let parsed = parseFilterRegexpSource(filter.regexpSource);
538 if (parsed.hostname) 574 if (parsed.hostname)
539 requestFilterExceptionDomains.push(parsed.hostname); 575 requestFilterExceptionDomains.push(parsed.hostname);
540 } 576 }
541 577
542 for (let filter of this.requestFilters) 578 for (let filter of this.requestFilters)
543 { 579 {
544 convertFilterAddRules(rules, filter, "block", true, 580 convertFilterAddRules(rules, filter, "block", true,
545 requestFilterExceptionDomains); 581 requestFilterExceptionDomains);
546 } 582 }
547 583
548 for (let filter of this.requestExceptions) 584 for (let filter of this.requestExceptions)
549 convertFilterAddRules(rules, filter, "ignore-previous-rules", true); 585 convertFilterAddRules(rules, filter, "ignore-previous-rules", true);
550 586
551 return rules; 587 return rules;
552 }; 588 };
OLDNEW
« no previous file with comments | « abp2blocklist.js ('k') | test/abp2blocklist.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld