| Left: | ||
| Right: |
| 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-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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 }); | |
| OLD | NEW |