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

Side by Side Diff: lib/filterClasses.js

Issue 29803559: Issue 6741 - Use ES2015 classes in lib/filterClasses.js (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Created June 9, 2018, 12:51 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 | no next file » | 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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 "use strict"; 18 "use strict";
19 19
20 /** 20 /**
21 * @fileOverview Definition of Filter class and its subclasses. 21 * @fileOverview Definition of Filter class and its subclasses.
22 */ 22 */
23 23
24 const {FilterNotifier} = require("./filterNotifier"); 24 const {FilterNotifier} = require("./filterNotifier");
25 const {extend} = require("./coreUtils");
26 const {filterToRegExp} = require("./common"); 25 const {filterToRegExp} = require("./common");
27 26
28 /** 27 /**
29 * Abstract base class for filters 28 * Abstract base class for filters
30 *
31 * @param {string} text string representation of the filter
32 * @constructor
33 */ 29 */
34 function Filter(text) 30 class Filter
35 {
36 this.text = text;
37 this.subscriptions = [];
38 }
39 exports.Filter = Filter;
40
41 Filter.prototype =
42 { 31 {
43 /** 32 /**
44 * String representation of the filter 33 * @param {string} text string representation of the filter
45 * @type {string}
46 */ 34 */
47 text: null, 35 constructor(text)
36 {
37 /**
Manish Jethani 2018/06/09 13:03:32 For instance properties that are always assigned i
38 * String representation of the filter
39 * @type {string}
40 */
41 this.text = text;
48 42
49 /** 43 /**
50 * Filter subscriptions the filter belongs to 44 * Filter subscriptions the filter belongs to
51 * @type {Subscription[]} 45 * @type {Subscription[]}
52 */ 46 */
53 subscriptions: null, 47 this.subscriptions = [];
48 }
54 49
55 /** 50 /**
56 * Filter type as a string, e.g. "blocking". 51 * Filter type as a string, e.g. "blocking".
57 * @type {string} 52 * @type {string}
58 */ 53 */
59 get type() 54 get type()
60 { 55 {
61 throw new Error("Please define filter type in the subclass"); 56 throw new Error("Please define filter type in the subclass");
62 }, 57 }
63 58
64 /** 59 /**
65 * Serializes the filter to an array of strings for writing out on the disk. 60 * Serializes the filter to an array of strings for writing out on the disk.
66 * @param {string[]} buffer buffer to push the serialization results into 61 * @param {string[]} buffer buffer to push the serialization results into
67 */ 62 */
68 serialize(buffer) 63 serialize(buffer)
69 { 64 {
70 buffer.push("[Filter]"); 65 buffer.push("[Filter]");
71 buffer.push("text=" + this.text); 66 buffer.push("text=" + this.text);
72 }, 67 }
73 68
74 toString() 69 toString()
75 { 70 {
76 return this.text; 71 return this.text;
77 } 72 }
78 }; 73 }
74
75 exports.Filter = Filter;
79 76
80 /** 77 /**
81 * Cache for known filters, maps string representation to filter objects. 78 * Cache for known filters, maps string representation to filter objects.
82 * @type {Map.<string,Filter>} 79 * @type {Map.<string,Filter>}
83 */ 80 */
84 Filter.knownFilters = new Map(); 81 Filter.knownFilters = new Map();
85 82
86 /** 83 /**
87 * Regular expression that element hiding filters should match 84 * Regular expression that element hiding filters should match
88 * @type {RegExp} 85 * @type {RegExp}
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
233 return beforeOptions + "$" + options.join(); 230 return beforeOptions + "$" + options.join();
234 }; 231 };
235 232
236 /** 233 /**
237 * @see filterToRegExp 234 * @see filterToRegExp
238 */ 235 */
239 Filter.toRegExp = filterToRegExp; 236 Filter.toRegExp = filterToRegExp;
240 237
241 /** 238 /**
242 * Class for invalid filters 239 * Class for invalid filters
243 * @param {string} text see Filter()
244 * @param {string} reason Reason why this filter is invalid
245 * @constructor
246 * @augments Filter
247 */ 240 */
248 function InvalidFilter(text, reason) 241 class InvalidFilter extends Filter
249 { 242 {
250 Filter.call(this, text); 243 /**
244 * @param {string} text see Filter()
245 * @param {string} reason Reason why this filter is invalid
246 */
247 constructor(text, reason)
248 {
249 super(text);
251 250
252 this.reason = reason; 251 /**
253 } 252 * Reason why this filter is invalid
254 exports.InvalidFilter = InvalidFilter; 253 * @type {string}
254 */
255 this.reason = reason;
256 }
255 257
256 InvalidFilter.prototype = extend(Filter, { 258 get type()
Manish Jethani 2018/06/09 13:03:32 This needs to be a getter now.
257 type: "invalid", 259 {
258 260 return "invalid";
259 /** 261 }
260 * Reason why this filter is invalid
261 * @type {string}
262 */
263 reason: null,
264 262
265 /** 263 /**
266 * See Filter.serialize() 264 * See Filter.serialize()
267 * @inheritdoc 265 * @inheritdoc
268 */ 266 */
269 serialize(buffer) {} 267 serialize(buffer) {}
270 }); 268 }
269
270 exports.InvalidFilter = InvalidFilter;
271 271
272 /** 272 /**
273 * Class for comments 273 * Class for comments
274 * @param {string} text see Filter()
275 * @constructor
276 * @augments Filter
277 */ 274 */
278 function CommentFilter(text) 275 class CommentFilter extends Filter
279 { 276 {
280 Filter.call(this, text); 277 /**
281 } 278 * @param {string} text see Filter()
282 exports.CommentFilter = CommentFilter; 279 */
280 constructor(text)
281 {
282 super(text);
283 }
283 284
284 CommentFilter.prototype = extend(Filter, { 285 get type()
285 type: "comment", 286 {
287 return "comment";
288 }
286 289
287 /** 290 /**
288 * See Filter.serialize() 291 * See Filter.serialize()
289 * @inheritdoc 292 * @inheritdoc
290 */ 293 */
291 serialize(buffer) {} 294 serialize(buffer) {}
292 }); 295 }
296
297 exports.CommentFilter = CommentFilter;
293 298
294 /** 299 /**
295 * Abstract base class for filters that can get hits 300 * Abstract base class for filters that can get hits
296 * @param {string} text
297 * see Filter()
298 * @param {string} [domains]
299 * Domains that the filter is restricted to separated by domainSeparator
300 * e.g. "foo.com|bar.com|~baz.com"
301 * @constructor
302 * @augments Filter
303 */ 301 */
304 function ActiveFilter(text, domains) 302 class ActiveFilter extends Filter
305 { 303 {
306 Filter.call(this, text); 304 /**
305 * @param {string} text
306 * see Filter()
307 * @param {string} [domains]
308 * Domains that the filter is restricted to separated by domainSeparator
309 * e.g. "foo.com|bar.com|~baz.com"
310 */
311 constructor(text, domains)
312 {
313 super(text);
307 314
308 if (domains) 315 if (domains)
309 this.domainSource = domains; 316 this.domainSource = domains;
310 } 317 }
311 exports.ActiveFilter = ActiveFilter;
312
313 ActiveFilter.prototype = extend(Filter, {
314 _disabled: false,
315 _hitCount: 0,
316 _lastHit: 0,
317 318
318 /** 319 /**
319 * Defines whether the filter is disabled 320 * Defines whether the filter is disabled
320 * @type {boolean} 321 * @type {boolean}
321 */ 322 */
322 get disabled() 323 get disabled()
323 { 324 {
324 return this._disabled; 325 return this._disabled;
325 }, 326 }
326 set disabled(value) 327 set disabled(value)
327 { 328 {
328 if (value != this._disabled) 329 if (value != this._disabled)
329 { 330 {
330 let oldValue = this._disabled; 331 let oldValue = this._disabled;
331 this._disabled = value; 332 this._disabled = value;
332 FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue); 333 FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue);
333 } 334 }
334 return this._disabled; 335 return this._disabled;
335 }, 336 }
336 337
337 /** 338 /**
338 * Number of hits on the filter since the last reset 339 * Number of hits on the filter since the last reset
339 * @type {number} 340 * @type {number}
340 */ 341 */
341 get hitCount() 342 get hitCount()
342 { 343 {
343 return this._hitCount; 344 return this._hitCount;
344 }, 345 }
345 set hitCount(value) 346 set hitCount(value)
346 { 347 {
347 if (value != this._hitCount) 348 if (value != this._hitCount)
348 { 349 {
349 let oldValue = this._hitCount; 350 let oldValue = this._hitCount;
350 this._hitCount = value; 351 this._hitCount = value;
351 FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue); 352 FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue);
352 } 353 }
353 return this._hitCount; 354 return this._hitCount;
354 }, 355 }
355 356
356 /** 357 /**
357 * Last time the filter had a hit (in milliseconds since the beginning of the 358 * Last time the filter had a hit (in milliseconds since the beginning of the
358 * epoch) 359 * epoch)
359 * @type {number} 360 * @type {number}
360 */ 361 */
361 get lastHit() 362 get lastHit()
362 { 363 {
363 return this._lastHit; 364 return this._lastHit;
364 }, 365 }
365 set lastHit(value) 366 set lastHit(value)
366 { 367 {
367 if (value != this._lastHit) 368 if (value != this._lastHit)
368 { 369 {
369 let oldValue = this._lastHit; 370 let oldValue = this._lastHit;
370 this._lastHit = value; 371 this._lastHit = value;
371 FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue); 372 FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue);
372 } 373 }
373 return this._lastHit; 374 return this._lastHit;
374 }, 375 }
375
376 /**
377 * String that the domains property should be generated from
378 * @type {?string}
379 */
380 domainSource: null,
381
382 /**
383 * Separator character used in domainSource property, must be
384 * overridden by subclasses
385 * @type {string}
386 */
387 domainSeparator: null,
388
389 /**
390 * Determines whether domainSource is already upper-case,
391 * can be overridden by subclasses.
392 * @type {boolean}
393 */
394 domainSourceIsUpperCase: false,
395 376
396 /** 377 /**
397 * Map containing domains that this filter should match on/not match 378 * Map containing domains that this filter should match on/not match
398 * on or null if the filter should match on all domains 379 * on or null if the filter should match on all domains
399 * @type {?Map.<string,boolean>} 380 * @type {?Map.<string,boolean>}
400 */ 381 */
401 get domains() 382 get domains()
402 { 383 {
403 let domains = null; 384 let domains = null;
404 385
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 } 425 }
445 if (domains) 426 if (domains)
446 domains.set("", !hasIncludes); 427 domains.set("", !hasIncludes);
447 } 428 }
448 429
449 this.domainSource = null; 430 this.domainSource = null;
450 } 431 }
451 432
452 Object.defineProperty(this, "domains", {value: domains, enumerable: true}); 433 Object.defineProperty(this, "domains", {value: domains, enumerable: true});
453 return this.domains; 434 return this.domains;
454 }, 435 }
455
456 /**
457 * Array containing public keys of websites that this filter should apply to
458 * @type {?string[]}
459 */
460 sitekeys: null,
461 436
462 /** 437 /**
463 * Checks whether this filter is active on a domain. 438 * Checks whether this filter is active on a domain.
464 * @param {string} [docDomain] domain name of the document that loads the URL 439 * @param {string} [docDomain] domain name of the document that loads the URL
465 * @param {string} [sitekey] public key provided by the document 440 * @param {string} [sitekey] public key provided by the document
466 * @return {boolean} true in case of the filter being active 441 * @return {boolean} true in case of the filter being active
467 */ 442 */
468 isActiveOnDomain(docDomain, sitekey) 443 isActiveOnDomain(docDomain, sitekey)
469 { 444 {
470 // Sitekeys are case-sensitive so we shouldn't convert them to 445 // Sitekeys are case-sensitive so we shouldn't convert them to
(...skipping 21 matching lines...) Expand all
492 let isDomainIncluded = this.domains.get(docDomain); 467 let isDomainIncluded = this.domains.get(docDomain);
493 if (typeof isDomainIncluded != "undefined") 468 if (typeof isDomainIncluded != "undefined")
494 return isDomainIncluded; 469 return isDomainIncluded;
495 470
496 let nextDot = docDomain.indexOf("."); 471 let nextDot = docDomain.indexOf(".");
497 if (nextDot < 0) 472 if (nextDot < 0)
498 break; 473 break;
499 docDomain = docDomain.substr(nextDot + 1); 474 docDomain = docDomain.substr(nextDot + 1);
500 } 475 }
501 return this.domains.get(""); 476 return this.domains.get("");
502 }, 477 }
503 478
504 /** 479 /**
505 * Checks whether this filter is active only on a domain and its subdomains. 480 * Checks whether this filter is active only on a domain and its subdomains.
506 * @param {string} docDomain 481 * @param {string} docDomain
507 * @return {boolean} 482 * @return {boolean}
508 */ 483 */
509 isActiveOnlyOnDomain(docDomain) 484 isActiveOnlyOnDomain(docDomain)
510 { 485 {
511 if (!docDomain || !this.domains || this.domains.get("")) 486 if (!docDomain || !this.domains || this.domains.get(""))
512 return false; 487 return false;
513 488
514 docDomain = docDomain.replace(/\.+$/, "").toUpperCase(); 489 docDomain = docDomain.replace(/\.+$/, "").toUpperCase();
515 490
516 for (let [domain, isIncluded] of this.domains) 491 for (let [domain, isIncluded] of this.domains)
517 { 492 {
518 if (isIncluded && domain != docDomain) 493 if (isIncluded && domain != docDomain)
519 { 494 {
520 if (domain.length <= docDomain.length) 495 if (domain.length <= docDomain.length)
521 return false; 496 return false;
522 497
523 if (!domain.endsWith("." + docDomain)) 498 if (!domain.endsWith("." + docDomain))
524 return false; 499 return false;
525 } 500 }
526 } 501 }
527 502
528 return true; 503 return true;
529 }, 504 }
530 505
531 /** 506 /**
532 * Checks whether this filter is generic or specific 507 * Checks whether this filter is generic or specific
533 * @return {boolean} 508 * @return {boolean}
534 */ 509 */
535 isGeneric() 510 isGeneric()
536 { 511 {
537 return !(this.sitekeys && this.sitekeys.length) && 512 return !(this.sitekeys && this.sitekeys.length) &&
538 (!this.domains || this.domains.get("")); 513 (!this.domains || this.domains.get(""));
539 }, 514 }
540 515
541 /** 516 /**
542 * See Filter.serialize() 517 * See Filter.serialize()
543 * @inheritdoc 518 * @inheritdoc
544 */ 519 */
545 serialize(buffer) 520 serialize(buffer)
546 { 521 {
547 if (this._disabled || this._hitCount || this._lastHit) 522 if (this._disabled || this._hitCount || this._lastHit)
548 { 523 {
549 Filter.prototype.serialize.call(this, buffer); 524 Filter.prototype.serialize.call(this, buffer);
550 if (this._disabled) 525 if (this._disabled)
551 buffer.push("disabled=true"); 526 buffer.push("disabled=true");
552 if (this._hitCount) 527 if (this._hitCount)
553 buffer.push("hitCount=" + this._hitCount); 528 buffer.push("hitCount=" + this._hitCount);
554 if (this._lastHit) 529 if (this._lastHit)
555 buffer.push("lastHit=" + this._lastHit); 530 buffer.push("lastHit=" + this._lastHit);
556 } 531 }
557 } 532 }
533 }
534
535 exports.ActiveFilter = ActiveFilter;
536
537 Object.assign(ActiveFilter.prototype, {
538 _disabled: false,
539 _hitCount: 0,
540 _lastHit: 0
558 }); 541 });
559 542
560 /** 543 /**
544 * String that the domains property should be generated from
545 * @type {?string}
546 */
547 ActiveFilter.prototype.domainSource = null;
Manish Jethani 2018/06/09 13:03:32 Where the instance property is not always assigned
548
549 /**
550 * Separator character used in domainSource property, must be
551 * overridden by subclasses
552 * @type {string}
553 */
554 ActiveFilter.prototype.domainSeparator = null;
555
556 /**
557 * Determines whether domainSource is already upper-case,
558 * can be overridden by subclasses.
559 * @type {boolean}
560 */
561 ActiveFilter.prototype.domainSourceIsUpperCase = false;
562
563 /**
564 * Array containing public keys of websites that this filter should apply to
565 * @type {?string[]}
566 */
567 ActiveFilter.prototype.sitekeys = null;
568
569 /**
561 * Abstract base class for RegExp-based filters 570 * Abstract base class for RegExp-based filters
562 * @param {string} text see Filter()
563 * @param {string} regexpSource
564 * filter part that the regular expression should be build from
565 * @param {number} [contentType]
566 * Content types the filter applies to, combination of values from
567 * RegExpFilter.typeMap
568 * @param {boolean} [matchCase]
569 * Defines whether the filter should distinguish between lower and upper case
570 * letters
571 * @param {string} [domains]
572 * Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
573 * @param {boolean} [thirdParty]
574 * Defines whether the filter should apply to third-party or first-party
575 * content only
576 * @param {string} [sitekeys]
577 * Public keys of websites that this filter should apply to
578 * @constructor
579 * @augments ActiveFilter
580 */ 571 */
581 function RegExpFilter(text, regexpSource, contentType, matchCase, domains, 572 class RegExpFilter extends ActiveFilter
582 thirdParty, sitekeys)
583 { 573 {
584 ActiveFilter.call(this, text, domains, sitekeys); 574 /**
575 * @param {string} text see Filter()
576 * @param {string} regexpSource
577 * filter part that the regular expression should be build from
578 * @param {number} [contentType]
579 * Content types the filter applies to, combination of values from
580 * RegExpFilter.typeMap
581 * @param {boolean} [matchCase]
582 * Defines whether the filter should distinguish between lower and upper
583 * case letters
584 * @param {string} [domains]
585 * Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
586 * @param {boolean} [thirdParty]
587 * Defines whether the filter should apply to third-party or first-party
588 * content only
589 * @param {string} [sitekeys]
590 * Public keys of websites that this filter should apply to
591 */
592 constructor(text, regexpSource, contentType, matchCase, domains, thirdParty,
593 sitekeys)
594 {
595 super(text, domains, sitekeys);
585 596
586 if (contentType != null) 597 if (contentType != null)
587 this.contentType = contentType; 598 this.contentType = contentType;
588 if (matchCase) 599 if (matchCase)
589 this.matchCase = matchCase; 600 this.matchCase = matchCase;
590 if (thirdParty != null) 601 if (thirdParty != null)
591 this.thirdParty = thirdParty; 602 this.thirdParty = thirdParty;
592 if (sitekeys != null) 603 if (sitekeys != null)
593 this.sitekeySource = sitekeys; 604 this.sitekeySource = sitekeys;
594 605
595 if (regexpSource.length >= 2 && 606 if (regexpSource.length >= 2 &&
596 regexpSource[0] == "/" && 607 regexpSource[0] == "/" &&
597 regexpSource[regexpSource.length - 1] == "/") 608 regexpSource[regexpSource.length - 1] == "/")
598 { 609 {
599 // The filter is a regular expression - convert it immediately to 610 // The filter is a regular expression - convert it immediately to
600 // catch syntax errors 611 // catch syntax errors
601 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2), 612 let regexp = new RegExp(regexpSource.substr(1, regexpSource.length - 2),
602 this.matchCase ? "" : "i"); 613 this.matchCase ? "" : "i");
603 Object.defineProperty(this, "regexp", {value: regexp}); 614 Object.defineProperty(this, "regexp", {value: regexp});
615 }
616 else
617 {
618 // No need to convert this filter to regular expression yet, do it on
619 // demand
620 this.regexpSource = regexpSource;
621 }
604 } 622 }
605 else
606 {
607 // No need to convert this filter to regular expression yet, do it on demand
608 this.regexpSource = regexpSource;
609 }
610 }
611 exports.RegExpFilter = RegExpFilter;
612 623
613 RegExpFilter.prototype = extend(ActiveFilter, {
614 /**
615 * @see ActiveFilter.domainSourceIsUpperCase
616 */
617 domainSourceIsUpperCase: true,
618
619 /**
620 * Number of filters contained, will always be 1 (required to
621 * optimize Matcher).
622 * @type {number}
623 */
624 length: 1,
625
626 /**
627 * @see ActiveFilter.domainSeparator
628 */
629 domainSeparator: "|",
630
631 /**
632 * Expression from which a regular expression should be generated -
633 * for delayed creation of the regexp property
634 * @type {string}
635 */
636 regexpSource: null,
637 /** 624 /**
638 * Regular expression to be used when testing against this filter 625 * Regular expression to be used when testing against this filter
639 * @type {RegExp} 626 * @type {RegExp}
640 */ 627 */
641 get regexp() 628 get regexp()
642 { 629 {
643 let source = Filter.toRegExp(this.regexpSource); 630 let source = Filter.toRegExp(this.regexpSource);
644 let regexp = new RegExp(source, this.matchCase ? "" : "i"); 631 let regexp = new RegExp(source, this.matchCase ? "" : "i");
645 Object.defineProperty(this, "regexp", {value: regexp}); 632 Object.defineProperty(this, "regexp", {value: regexp});
646 this.regexpSource = null; 633 this.regexpSource = null;
647 return regexp; 634 return regexp;
648 }, 635 }
649 /**
650 * Content types the filter applies to, combination of values from
651 * RegExpFilter.typeMap
652 * @type {number}
653 */
654 contentType: 0x7FFFFFFF,
655 /**
656 * Defines whether the filter should distinguish between lower and
657 * upper case letters
658 * @type {boolean}
659 */
660 matchCase: false,
661 /**
662 * Defines whether the filter should apply to third-party or
663 * first-party content only. Can be null (apply to all content).
664 * @type {?boolean}
665 */
666 thirdParty: null,
667 636
668 /**
669 * String that the sitekey property should be generated from
670 * @type {?string}
671 */
672 sitekeySource: null,
673
674 /**
675 * @see ActiveFilter.sitekeys
676 */
677 get sitekeys() 637 get sitekeys()
678 { 638 {
679 let sitekeys = null; 639 let sitekeys = null;
680 640
681 if (this.sitekeySource) 641 if (this.sitekeySource)
682 { 642 {
683 sitekeys = this.sitekeySource.split("|"); 643 sitekeys = this.sitekeySource.split("|");
684 this.sitekeySource = null; 644 this.sitekeySource = null;
685 } 645 }
686 646
687 Object.defineProperty( 647 Object.defineProperty(
688 this, "sitekeys", {value: sitekeys, enumerable: true} 648 this, "sitekeys", {value: sitekeys, enumerable: true}
689 ); 649 );
690 return this.sitekeys; 650 return this.sitekeys;
691 }, 651 }
692 652
693 /** 653 /**
694 * Tests whether the URL matches this filter 654 * Tests whether the URL matches this filter
695 * @param {string} location URL to be tested 655 * @param {string} location URL to be tested
696 * @param {number} typeMask bitmask of content / request types to match 656 * @param {number} typeMask bitmask of content / request types to match
697 * @param {string} [docDomain] domain name of the document that loads the URL 657 * @param {string} [docDomain] domain name of the document that loads the URL
698 * @param {boolean} [thirdParty] should be true if the URL is a third-party 658 * @param {boolean} [thirdParty] should be true if the URL is a third-party
699 * request 659 * request
700 * @param {string} [sitekey] public key provided by the document 660 * @param {string} [sitekey] public key provided by the document
701 * @return {boolean} true in case of a match 661 * @return {boolean} true in case of a match
702 */ 662 */
703 matches(location, typeMask, docDomain, thirdParty, sitekey) 663 matches(location, typeMask, docDomain, thirdParty, sitekey)
704 { 664 {
705 if (this.contentType & typeMask && 665 if (this.contentType & typeMask &&
706 (this.thirdParty == null || this.thirdParty == thirdParty) && 666 (this.thirdParty == null || this.thirdParty == thirdParty) &&
707 this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location)) 667 this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location))
708 { 668 {
709 return true; 669 return true;
710 } 670 }
711 return false; 671 return false;
712 } 672 }
713 }); 673 }
674
675 exports.RegExpFilter = RegExpFilter;
676
677 /**
678 * @see ActiveFilter.domainSourceIsUpperCase
679 */
680 RegExpFilter.prototype.domainSourceIsUpperCase = true;
681
682 /**
683 * Number of filters contained, will always be 1 (required to
684 * optimize Matcher).
685 * @type {number}
686 */
687 RegExpFilter.prototype.length = 1;
688
689 /**
690 * @see ActiveFilter.domainSeparator
691 */
692 RegExpFilter.prototype.domainSeparator = "|";
693
694 /**
695 * Expression from which a regular expression should be generated -
696 * for delayed creation of the regexp property
697 * @type {string}
698 */
699 RegExpFilter.prototype.regexpSource = null;
700
701 /**
702 * Content types the filter applies to, combination of values from
703 * RegExpFilter.typeMap
704 * @type {number}
705 */
706 RegExpFilter.prototype.contentType = 0x7FFFFFFF;
707
708 /**
709 * Defines whether the filter should distinguish between lower and
710 * upper case letters
711 * @type {boolean}
712 */
713 RegExpFilter.prototype.matchCase = false;
714
715 /**
716 * Defines whether the filter should apply to third-party or
717 * first-party content only. Can be null (apply to all content).
718 * @type {?boolean}
719 */
720 RegExpFilter.prototype.thirdParty = null;
721
722 /**
723 * String that the sitekey property should be generated from
724 * @type {?string}
725 */
726 RegExpFilter.prototype.sitekeySource = null;
714 727
715 // Required to optimize Matcher, see also RegExpFilter.prototype.length 728 // Required to optimize Matcher, see also RegExpFilter.prototype.length
716 Object.defineProperty(RegExpFilter.prototype, "0", { 729 Object.defineProperty(RegExpFilter.prototype, "0", {
717 get() { return this; } 730 get() { return this; }
718 }); 731 });
719 732
720 /** 733 /**
721 * Creates a RegExp filter from its text representation 734 * Creates a RegExp filter from its text representation
722 * @param {string} text same as in Filter() 735 * @param {string} text same as in Filter()
723 * @return {Filter} 736 * @return {Filter}
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
857 // shouldn't be there by default 870 // shouldn't be there by default
858 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.CSP | 871 RegExpFilter.prototype.contentType &= ~(RegExpFilter.typeMap.CSP |
859 RegExpFilter.typeMap.DOCUMENT | 872 RegExpFilter.typeMap.DOCUMENT |
860 RegExpFilter.typeMap.ELEMHIDE | 873 RegExpFilter.typeMap.ELEMHIDE |
861 RegExpFilter.typeMap.POPUP | 874 RegExpFilter.typeMap.POPUP |
862 RegExpFilter.typeMap.GENERICHIDE | 875 RegExpFilter.typeMap.GENERICHIDE |
863 RegExpFilter.typeMap.GENERICBLOCK); 876 RegExpFilter.typeMap.GENERICBLOCK);
864 877
865 /** 878 /**
866 * Class for blocking filters 879 * Class for blocking filters
867 * @param {string} text see Filter()
868 * @param {string} regexpSource see RegExpFilter()
869 * @param {number} [contentType] see RegExpFilter()
870 * @param {boolean} [matchCase] see RegExpFilter()
871 * @param {string} [domains] see RegExpFilter()
872 * @param {boolean} [thirdParty] see RegExpFilter()
873 * @param {string} [sitekeys] see RegExpFilter()
874 * @param {boolean} [collapse]
875 * defines whether the filter should collapse blocked content, can be null
876 * @param {string} [csp]
877 * Content Security Policy to inject when the filter matches
878 * @param {?string} [rewrite]
879 * The (optional) rule specifying how to rewrite the URL. See
880 * BlockingFilter.prototype.rewrite.
881 * @constructor
882 * @augments RegExpFilter
883 */ 880 */
884 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, 881 class BlockingFilter extends RegExpFilter
885 thirdParty, sitekeys, collapse, csp, rewrite)
886 { 882 {
887 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, 883 /**
888 thirdParty, sitekeys); 884 * @param {string} text see Filter()
885 * @param {string} regexpSource see RegExpFilter()
886 * @param {number} [contentType] see RegExpFilter()
887 * @param {boolean} [matchCase] see RegExpFilter()
888 * @param {string} [domains] see RegExpFilter()
889 * @param {boolean} [thirdParty] see RegExpFilter()
890 * @param {string} [sitekeys] see RegExpFilter()
891 * @param {boolean} [collapse]
892 * defines whether the filter should collapse blocked content, can be null
893 * @param {string} [csp]
894 * Content Security Policy to inject when the filter matches
895 * @param {?string} [rewrite]
896 * The (optional) rule specifying how to rewrite the URL. See
897 * BlockingFilter.prototype.rewrite.
898 */
899 constructor(text, regexpSource, contentType, matchCase, domains, thirdParty,
900 sitekeys, collapse, csp, rewrite)
901 {
902 super(text, regexpSource, contentType, matchCase, domains, thirdParty,
903 sitekeys);
889 904
890 if (collapse != null) 905 if (collapse != null)
891 this.collapse = collapse; 906 this.collapse = collapse;
892 907
893 if (csp != null) 908 if (csp != null)
894 this.csp = csp; 909 this.csp = csp;
895 910
896 if (rewrite != null) 911 if (rewrite != null)
897 this.rewrite = rewrite; 912 this.rewrite = rewrite;
898 } 913 }
899 exports.BlockingFilter = BlockingFilter;
900 914
901 BlockingFilter.prototype = extend(RegExpFilter, { 915 get type()
902 type: "blocking", 916 {
903 917 return "blocking";
904 /** 918 }
905 * Defines whether the filter should collapse blocked content.
906 * Can be null (use the global preference).
907 * @type {?boolean}
908 */
909 collapse: null,
910
911 /**
912 * Content Security Policy to inject for matching requests.
913 * @type {?string}
914 */
915 csp: null,
916
917 /**
918 * The rule specifying how to rewrite the URL.
919 * The syntax is similar to the one of String.prototype.replace().
920 * @type {?string}
921 */
922 rewrite: null,
923 919
924 /** 920 /**
925 * Rewrites an URL. 921 * Rewrites an URL.
926 * @param {string} url the URL to rewrite 922 * @param {string} url the URL to rewrite
927 * @return {string} the rewritten URL, or the original in case of failure 923 * @return {string} the rewritten URL, or the original in case of failure
928 */ 924 */
929 rewriteUrl(url) 925 rewriteUrl(url)
930 { 926 {
931 try 927 try
932 { 928 {
933 let rewrittenUrl = new URL(url.replace(this.regexp, this.rewrite), url); 929 let rewrittenUrl = new URL(url.replace(this.regexp, this.rewrite), url);
934 if (rewrittenUrl.origin == new URL(url).origin) 930 if (rewrittenUrl.origin == new URL(url).origin)
935 return rewrittenUrl.href; 931 return rewrittenUrl.href;
936 } 932 }
937 catch (e) 933 catch (e)
938 { 934 {
939 } 935 }
940 936
941 return url; 937 return url;
942 } 938 }
943 }); 939 }
940
941 exports.BlockingFilter = BlockingFilter;
942
943 /**
944 * Defines whether the filter should collapse blocked content.
945 * Can be null (use the global preference).
946 * @type {?boolean}
947 */
948 BlockingFilter.prototype.collapse = null;
949
950 /**
951 * Content Security Policy to inject for matching requests.
952 * @type {?string}
953 */
954 BlockingFilter.prototype.csp = null;
955
956 /**
957 * The rule specifying how to rewrite the URL.
958 * The syntax is similar to the one of String.prototype.replace().
959 * @type {?string}
960 */
961 BlockingFilter.prototype.rewrite = null;
944 962
945 /** 963 /**
946 * Class for whitelist filters 964 * Class for whitelist filters
947 * @param {string} text see Filter()
948 * @param {string} regexpSource see RegExpFilter()
949 * @param {number} [contentType] see RegExpFilter()
950 * @param {boolean} [matchCase] see RegExpFilter()
951 * @param {string} [domains] see RegExpFilter()
952 * @param {boolean} [thirdParty] see RegExpFilter()
953 * @param {string} [sitekeys] see RegExpFilter()
954 * @constructor
955 * @augments RegExpFilter
956 */ 965 */
957 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, 966 class WhitelistFilter extends RegExpFilter
958 thirdParty, sitekeys)
959 { 967 {
960 RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, 968 /**
961 thirdParty, sitekeys); 969 * @param {string} text see Filter()
970 * @param {string} regexpSource see RegExpFilter()
971 * @param {number} [contentType] see RegExpFilter()
972 * @param {boolean} [matchCase] see RegExpFilter()
973 * @param {string} [domains] see RegExpFilter()
974 * @param {boolean} [thirdParty] see RegExpFilter()
975 * @param {string} [sitekeys] see RegExpFilter()
976 */
977 constructor(text, regexpSource, contentType, matchCase, domains, thirdParty,
978 sitekeys)
979 {
980 super(text, regexpSource, contentType, matchCase, domains, thirdParty,
981 sitekeys);
982 }
983
984 get type()
985 {
986 return "whitelist";
987 }
962 } 988 }
989
963 exports.WhitelistFilter = WhitelistFilter; 990 exports.WhitelistFilter = WhitelistFilter;
964 991
965 WhitelistFilter.prototype = extend(RegExpFilter, {
966 type: "whitelist"
967 });
968
969 /** 992 /**
970 * Base class for element hiding filters 993 * Base class for element hiding filters
971 * @param {string} text see Filter()
972 * @param {string} [domains] Host names or domains the filter should be
973 * restricted to
974 * @param {string} selector CSS selector for the HTML elements that should be
975 * hidden
976 * @constructor
977 * @augments ActiveFilter
978 */ 994 */
979 function ElemHideBase(text, domains, selector) 995 class ElemHideBase extends ActiveFilter
980 { 996 {
981 ActiveFilter.call(this, text, domains || null); 997 /**
998 * @param {string} text see Filter()
999 * @param {string} [domains] Host names or domains the filter should be
1000 * restricted to
1001 * @param {string} selector CSS selector for the HTML elements that should
1002 * be hidden
1003 */
1004 constructor(text, domains, selector)
1005 {
1006 super(text, domains || null);
982 1007
983 // Braces are being escaped to prevent CSS rule injection. 1008 /**
984 this.selector = selector.replace("{", "\\7B ").replace("}", "\\7D "); 1009 * CSS selector for the HTML elements that should be hidden
1010 * @type {string}
1011 */
1012 // Braces are being escaped to prevent CSS rule injection.
1013 this.selector = selector.replace("{", "\\7B ").replace("}", "\\7D ");
1014 }
985 } 1015 }
1016
986 exports.ElemHideBase = ElemHideBase; 1017 exports.ElemHideBase = ElemHideBase;
987 1018
988 ElemHideBase.prototype = extend(ActiveFilter, { 1019 /**
989 /** 1020 * @see ActiveFilter.domainSeparator
990 * @see ActiveFilter.domainSeparator 1021 */
991 */ 1022 ElemHideBase.prototype.domainSeparator = ",";
992 domainSeparator: ",",
993
994 /**
995 * CSS selector for the HTML elements that should be hidden
996 * @type {string}
997 */
998 selector: null
999 });
1000 1023
1001 /** 1024 /**
1002 * Creates an element hiding filter from a pre-parsed text representation 1025 * Creates an element hiding filter from a pre-parsed text representation
1003 * 1026 *
1004 * @param {string} text same as in Filter() 1027 * @param {string} text same as in Filter()
1005 * @param {string} [domains] 1028 * @param {string} [domains]
1006 * domains part of the text representation 1029 * domains part of the text representation
1007 * @param {string} [type] 1030 * @param {string} [type]
1008 * rule type, either empty or @ (exception) or ? (emulation rule) 1031 * rule type, either empty or @ (exception) or ? (emulation rule)
1009 * @param {string} selector raw CSS selector 1032 * @param {string} selector raw CSS selector
(...skipping 19 matching lines...) Expand all
1029 return new InvalidFilter(text, "filter_elemhideemulation_nodomain"); 1052 return new InvalidFilter(text, "filter_elemhideemulation_nodomain");
1030 1053
1031 return new ElemHideEmulationFilter(text, domains, selector); 1054 return new ElemHideEmulationFilter(text, domains, selector);
1032 } 1055 }
1033 1056
1034 return new ElemHideFilter(text, domains, selector); 1057 return new ElemHideFilter(text, domains, selector);
1035 }; 1058 };
1036 1059
1037 /** 1060 /**
1038 * Class for element hiding filters 1061 * Class for element hiding filters
1039 * @param {string} text see Filter()
1040 * @param {string} [domains] see ElemHideBase()
1041 * @param {string} selector see ElemHideBase()
1042 * @constructor
1043 * @augments ElemHideBase
1044 */ 1062 */
1045 function ElemHideFilter(text, domains, selector) 1063 class ElemHideFilter extends ElemHideBase
1046 { 1064 {
1047 ElemHideBase.call(this, text, domains, selector); 1065 /**
1066 * @param {string} text see Filter()
1067 * @param {string} [domains] see ElemHideBase()
1068 * @param {string} selector see ElemHideBase()
1069 */
1070 constructor(text, domains, selector)
1071 {
1072 super(text, domains, selector);
1073 }
1074
1075 get type()
1076 {
1077 return "elemhide";
1078 }
1048 } 1079 }
1080
1049 exports.ElemHideFilter = ElemHideFilter; 1081 exports.ElemHideFilter = ElemHideFilter;
1050 1082
1051 ElemHideFilter.prototype = extend(ElemHideBase, {
1052 type: "elemhide"
1053 });
1054
1055 /** 1083 /**
1056 * Class for element hiding exceptions 1084 * Class for element hiding exceptions
1057 * @param {string} text see Filter()
1058 * @param {string} [domains] see ElemHideBase()
1059 * @param {string} selector see ElemHideBase()
1060 * @constructor
1061 * @augments ElemHideBase
1062 */ 1085 */
1063 function ElemHideException(text, domains, selector) 1086 class ElemHideException extends ElemHideBase
1064 { 1087 {
1065 ElemHideBase.call(this, text, domains, selector); 1088 /**
1089 * @param {string} text see Filter()
1090 * @param {string} [domains] see ElemHideBase()
1091 * @param {string} selector see ElemHideBase()
1092 */
1093 constructor(text, domains, selector)
1094 {
1095 super(text, domains, selector);
1096 }
1097
1098 get type()
1099 {
1100 return "elemhideexception";
1101 }
1066 } 1102 }
1103
1067 exports.ElemHideException = ElemHideException; 1104 exports.ElemHideException = ElemHideException;
1068 1105
1069 ElemHideException.prototype = extend(ElemHideBase, {
1070 type: "elemhideexception"
1071 });
1072
1073 /** 1106 /**
1074 * Class for element hiding emulation filters 1107 * Class for element hiding emulation filters
1075 * @param {string} text see Filter()
1076 * @param {string} domains see ElemHideBase()
1077 * @param {string} selector see ElemHideBase()
1078 * @constructor
1079 * @augments ElemHideBase
1080 */ 1108 */
1081 function ElemHideEmulationFilter(text, domains, selector) 1109 class ElemHideEmulationFilter extends ElemHideBase
1082 { 1110 {
1083 ElemHideBase.call(this, text, domains, selector); 1111 /**
1112 * @param {string} text see Filter()
1113 * @param {string} domains see ElemHideBase()
1114 * @param {string} selector see ElemHideBase()
1115 */
1116 constructor(text, domains, selector)
1117 {
1118 super(text, domains, selector);
1119 }
1120
1121 get type()
1122 {
1123 return "elemhideemulation";
1124 }
1084 } 1125 }
1126
1085 exports.ElemHideEmulationFilter = ElemHideEmulationFilter; 1127 exports.ElemHideEmulationFilter = ElemHideEmulationFilter;
1086
1087 ElemHideEmulationFilter.prototype = extend(ElemHideBase, {
1088 type: "elemhideemulation"
1089 });
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld