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

Side by Side Diff: lib/matcher.js

Issue 29990555: Issue 7179 - Add function to return all matching filters (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Fix typo Created Jan. 28, 2019, 5:35 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 | « no previous file | test/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 <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
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 293
294 /** 294 /**
295 * Checks whether the entries for a particular keyword match a URL 295 * Checks whether the entries for a particular keyword match a URL
296 * @param {string} keyword 296 * @param {string} keyword
297 * @param {string} location 297 * @param {string} location
298 * @param {number} typeMask 298 * @param {number} typeMask
299 * @param {string} [docDomain] 299 * @param {string} [docDomain]
300 * @param {boolean} [thirdParty] 300 * @param {boolean} [thirdParty]
301 * @param {string} [sitekey] 301 * @param {string} [sitekey]
302 * @param {boolean} [specificOnly] 302 * @param {boolean} [specificOnly]
303 * @param {?Array.<Filter>} [collection] An optional list of filters to which
304 * to append any results. If specified, the function adds <em>all</em>
305 * matching filters to the list; if omitted, the function directly returns
306 * the first matching filter.
303 * @returns {?Filter} 307 * @returns {?Filter}
304 * @protected 308 * @protected
305 */ 309 */
306 checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey, 310 checkEntryMatch(keyword, location, typeMask, docDomain, thirdParty, sitekey,
307 specificOnly) 311 specificOnly, collection)
308 { 312 {
309 // We need to skip the simple (location-only) filters if the type mask does 313 // We need to skip the simple (location-only) filters if the type mask does
310 // not contain any default content types. 314 // not contain any default content types.
311 if ((typeMask & DEFAULT_TYPES) != 0) 315 if ((typeMask & DEFAULT_TYPES) != 0)
312 { 316 {
313 let simpleSet = this._simpleFiltersByKeyword.get(keyword); 317 let simpleSet = this._simpleFiltersByKeyword.get(keyword);
314 if (simpleSet) 318 if (simpleSet)
315 { 319 {
316 for (let filter of simpleSet) 320 for (let filter of simpleSet)
317 { 321 {
318 if (specificOnly && !(filter instanceof WhitelistFilter)) 322 if (specificOnly && !(filter instanceof WhitelistFilter))
319 continue; 323 continue;
320 324
321 if (filter.matchesLocation(location)) 325 if (filter.matchesLocation(location))
322 return filter; 326 {
327 if (!collection)
328 return filter;
329
330 collection.push(filter);
331 }
323 } 332 }
324 } 333 }
325 } 334 }
326 335
327 let complexSet = null; 336 let complexSet = null;
328 337
329 // If the type mask contains a non-default type (first condition) and it is 338 // If the type mask contains a non-default type (first condition) and it is
330 // the only type in the mask (second condition), we can use the 339 // the only type in the mask (second condition), we can use the
331 // type-specific map, which typically contains a lot fewer filters. This 340 // type-specific map, which typically contains a lot fewer filters. This
332 // enables faster lookups for whitelisting types like $document, $elemhide, 341 // enables faster lookups for whitelisting types like $document, $elemhide,
(...skipping 11 matching lines...) Expand all
344 353
345 if (complexSet) 354 if (complexSet)
346 { 355 {
347 for (let filter of complexSet) 356 for (let filter of complexSet)
348 { 357 {
349 if (specificOnly && filter.isGeneric() && 358 if (specificOnly && filter.isGeneric() &&
350 !(filter instanceof WhitelistFilter)) 359 !(filter instanceof WhitelistFilter))
351 continue; 360 continue;
352 361
353 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey)) 362 if (filter.matches(location, typeMask, docDomain, thirdParty, sitekey))
354 return filter; 363 {
364 if (!collection)
365 return filter;
366
367 collection.push(filter);
368 }
355 } 369 }
356 } 370 }
357 371
358 return null; 372 return null;
359 } 373 }
360 374
361 /** 375 /**
362 * Tests whether the URL matches any of the known filters 376 * Tests whether the URL matches any of the known filters
363 * @param {string} location 377 * @param {string} location
364 * URL to be tested 378 * URL to be tested
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 { 537 {
524 whitelistHit = this._whitelist.checkEntryMatch(candidates[i], location, 538 whitelistHit = this._whitelist.checkEntryMatch(candidates[i], location,
525 typeMask, docDomain, 539 typeMask, docDomain,
526 thirdParty, sitekey); 540 thirdParty, sitekey);
527 } 541 }
528 } 542 }
529 543
530 return whitelistHit || blacklistHit; 544 return whitelistHit || blacklistHit;
531 } 545 }
532 546
547 _searchInternal(location, typeMask, docDomain, thirdParty, sitekey,
548 specificOnly, filterType)
549 {
550 let hits = {};
551
552 let searchBlocking = filterType == "blocking" || filterType == "all";
553 let searchWhitelist = filterType == "whitelist" || filterType == "all";
554
555 if (searchBlocking)
556 hits.blocking = [];
557
558 if (searchWhitelist)
559 hits.whitelist = [];
560
561 // If the type mask includes no types other than whitelist-only types, we
562 // can skip the blacklist.
563 if ((typeMask & ~WHITELIST_ONLY_TYPES) == 0)
564 searchBlocking = false;
565
566 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
567 if (candidates === null)
568 candidates = [];
569 candidates.push("");
570
571 for (let i = 0, l = candidates.length; i < l; i++)
572 {
573 if (searchBlocking)
574 {
575 this._blacklist.checkEntryMatch(candidates[i], location, typeMask,
576 docDomain, thirdParty, sitekey,
577 specificOnly, hits.blocking);
578 }
579
580 if (searchWhitelist)
581 {
582 this._whitelist.checkEntryMatch(candidates[i], location, typeMask,
583 docDomain, thirdParty, sitekey,
584 false, hits.whitelist);
585 }
586 }
587
588 return hits;
589 }
590
533 /** 591 /**
534 * @see Matcher#matchesAny 592 * @see Matcher#matchesAny
535 * @inheritdoc 593 * @inheritdoc
536 */ 594 */
537 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly) 595 matchesAny(location, typeMask, docDomain, thirdParty, sitekey, specificOnly)
538 { 596 {
539 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty + 597 let key = location + " " + typeMask + " " + docDomain + " " + thirdParty +
540 " " + sitekey + " " + specificOnly; 598 " " + sitekey + " " + specificOnly;
541 599
542 let result = this._resultCache.get(key); 600 let result = this._resultCache.get(key);
543 if (typeof result != "undefined") 601 if (typeof result != "undefined")
544 return result; 602 return result;
545 603
546 result = this._matchesAnyInternal(location, typeMask, docDomain, 604 result = this._matchesAnyInternal(location, typeMask, docDomain,
547 thirdParty, sitekey, specificOnly); 605 thirdParty, sitekey, specificOnly);
548 606
549 if (this._resultCache.size >= this.maxCacheEntries) 607 if (this._resultCache.size >= this.maxCacheEntries)
550 this._resultCache.clear(); 608 this._resultCache.clear();
551 609
552 this._resultCache.set(key, result); 610 this._resultCache.set(key, result);
553 611
554 return result; 612 return result;
555 } 613 }
556 614
557 /** 615 /**
616 * @typedef {object} MatcherSearchResults
617 * @property {Array.<BlockingFilter>} [blocking] List of blocking filters
618 * found.
619 * @property {Array.<WhitelistFilter>} [whitelist] List of whitelist filters
620 * found.
621 */
622
623 /**
624 * Searches all blocking and whitelist filters and returns results matching
625 * the given parameters.
626 *
627 * @param {string} location
628 * @param {number} typeMask
629 * @param {string} [docDomain]
630 * @param {boolean} [thirdParty]
631 * @param {string} [sitekey]
632 * @param {boolean} [specificOnly]
633 * @param {string} [filterType] The types of filters to look for. This can be
634 * <code>"blocking"</code>, <code>"whitelist"</code>, or
635 * <code>"all"</code> (default).
636 *
637 * @returns {MatcherSearchResults}
638 */
639 search(location, typeMask, docDomain, thirdParty, sitekey, specificOnly,
640 filterType = "all")
641 {
642 let key = "* " + location + " " + typeMask + " " + docDomain + " " +
643 thirdParty + " " + sitekey + " " + specificOnly + " " +
644 filterType;
645
646 let result = this._resultCache.get(key);
647 if (typeof result != "undefined")
648 return result;
649
650 result = this._searchInternal(location, typeMask, docDomain, thirdParty,
651 sitekey, specificOnly, filterType);
652
653 if (this._resultCache.size >= this.maxCacheEntries)
654 this._resultCache.clear();
655
656 this._resultCache.set(key, result);
657
658 return result;
659 }
660
661 /**
558 * Tests whether the URL is whitelisted 662 * Tests whether the URL is whitelisted
559 * @see Matcher#matchesAny 663 * @see Matcher#matchesAny
560 * @inheritdoc 664 * @inheritdoc
561 * @returns {boolean} 665 * @returns {boolean}
562 */ 666 */
563 isWhitelisted(location, typeMask, docDomain, thirdParty, sitekey, 667 isWhitelisted(location, typeMask, docDomain, thirdParty, sitekey,
564 specificOnly) 668 specificOnly)
565 { 669 {
566 return !!this._whitelist.matchesAny(location, typeMask, docDomain, 670 return !!this._whitelist.matchesAny(location, typeMask, docDomain,
567 thirdParty, sitekey, specificOnly); 671 thirdParty, sitekey, specificOnly);
568 } 672 }
569 } 673 }
570 674
571 exports.CombinedMatcher = CombinedMatcher; 675 exports.CombinedMatcher = CombinedMatcher;
572 676
573 /** 677 /**
574 * Shared {@link CombinedMatcher} instance that should usually be used. 678 * Shared {@link CombinedMatcher} instance that should usually be used.
575 * @type {CombinedMatcher} 679 * @type {CombinedMatcher}
576 */ 680 */
577 let defaultMatcher = new CombinedMatcher(); 681 let defaultMatcher = new CombinedMatcher();
578 682
579 exports.defaultMatcher = defaultMatcher; 683 exports.defaultMatcher = defaultMatcher;
OLDNEW
« no previous file with comments | « no previous file | test/matcher.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld