| LEFT | RIGHT | 
|---|
| 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-2016 Eyeo GmbH | 3  * Copyright (C) 2006-2016 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 /** | 18 /** | 
| 19  * @fileOverview Definition of Filter class and its subclasses. | 19  * @fileOverview Definition of Filter class and its subclasses. | 
| 20  */ | 20  */ | 
| 21 | 21 | 
| 22 let {FilterNotifier} = require("filterNotifier"); | 22 let {FilterNotifier} = require("filterNotifier"); | 
| 23 let {desc} = require("coreUtils"); | 23 let {extend} = require("coreUtils"); | 
| 24 | 24 | 
| 25 /** | 25 /** | 
| 26  * Abstract base class for filters | 26  * Abstract base class for filters | 
| 27  * | 27  * | 
| 28  * @param {String} text   string representation of the filter | 28  * @param {String} text   string representation of the filter | 
| 29  * @constructor | 29  * @constructor | 
| 30  */ | 30  */ | 
| 31 function Filter(text) | 31 function Filter(text) | 
| 32 { | 32 { | 
| 33   this.text = text; | 33   this.text = text; | 
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 204  * @augments Filter | 204  * @augments Filter | 
| 205  */ | 205  */ | 
| 206 function InvalidFilter(text, reason) | 206 function InvalidFilter(text, reason) | 
| 207 { | 207 { | 
| 208   Filter.call(this, text); | 208   Filter.call(this, text); | 
| 209 | 209 | 
| 210   this.reason = reason; | 210   this.reason = reason; | 
| 211 } | 211 } | 
| 212 exports.InvalidFilter = InvalidFilter; | 212 exports.InvalidFilter = InvalidFilter; | 
| 213 | 213 | 
| 214 InvalidFilter.prototype = Object.create(Filter.prototype, desc({ | 214 InvalidFilter.prototype = extend(Filter, { | 
| 215   type: "invalid", | 215   type: "invalid", | 
| 216 | 216 | 
| 217   /** | 217   /** | 
| 218    * Reason why this filter is invalid | 218    * Reason why this filter is invalid | 
| 219    * @type String | 219    * @type String | 
| 220    */ | 220    */ | 
| 221   reason: null, | 221   reason: null, | 
| 222 | 222 | 
| 223   /** | 223   /** | 
| 224    * See Filter.serialize() | 224    * See Filter.serialize() | 
| 225    */ | 225    */ | 
| 226   serialize: function(buffer) {} | 226   serialize: function(buffer) {} | 
| 227 })); | 227 }); | 
| 228 | 228 | 
| 229 /** | 229 /** | 
| 230  * Class for comments | 230  * Class for comments | 
| 231  * @param {String} text see Filter() | 231  * @param {String} text see Filter() | 
| 232  * @constructor | 232  * @constructor | 
| 233  * @augments Filter | 233  * @augments Filter | 
| 234  */ | 234  */ | 
| 235 function CommentFilter(text) | 235 function CommentFilter(text) | 
| 236 { | 236 { | 
| 237   Filter.call(this, text); | 237   Filter.call(this, text); | 
| 238 } | 238 } | 
| 239 exports.CommentFilter = CommentFilter; | 239 exports.CommentFilter = CommentFilter; | 
| 240 | 240 | 
| 241 CommentFilter.prototype = Object.create(Filter.prototype, desc({ | 241 CommentFilter.prototype = extend(Filter, { | 
| 242   type: "comment", | 242   type: "comment", | 
| 243 | 243 | 
| 244   /** | 244   /** | 
| 245    * See Filter.serialize() | 245    * See Filter.serialize() | 
| 246    */ | 246    */ | 
| 247   serialize: function(buffer) {} | 247   serialize: function(buffer) {} | 
| 248 })); | 248 }); | 
| 249 | 249 | 
| 250 /** | 250 /** | 
| 251  * Abstract base class for filters that can get hits | 251  * Abstract base class for filters that can get hits | 
| 252  * @param {String} text see Filter() | 252  * @param {String} text see Filter() | 
| 253  * @param {String} [domains] Domains that the filter is restricted to separated 
      by domainSeparator e.g. "foo.com|bar.com|~baz.com" | 253  * @param {String} [domains] Domains that the filter is restricted to separated 
      by domainSeparator e.g. "foo.com|bar.com|~baz.com" | 
| 254  * @constructor | 254  * @constructor | 
| 255  * @augments Filter | 255  * @augments Filter | 
| 256  */ | 256  */ | 
| 257 function ActiveFilter(text, domains) | 257 function ActiveFilter(text, domains) | 
| 258 { | 258 { | 
| 259   Filter.call(this, text); | 259   Filter.call(this, text); | 
| 260 | 260 | 
| 261   this.domainSource = domains; | 261   this.domainSource = domains; | 
| 262 } | 262 } | 
| 263 exports.ActiveFilter = ActiveFilter; | 263 exports.ActiveFilter = ActiveFilter; | 
| 264 | 264 | 
| 265 ActiveFilter.prototype = Object.create(Filter.prototype, desc({ | 265 ActiveFilter.prototype = extend(Filter, { | 
| 266   _disabled: false, | 266   _disabled: false, | 
| 267   _hitCount: 0, | 267   _hitCount: 0, | 
| 268   _lastHit: 0, | 268   _lastHit: 0, | 
| 269 | 269 | 
| 270   /** | 270   /** | 
| 271    * Defines whether the filter is disabled | 271    * Defines whether the filter is disabled | 
| 272    * @type Boolean | 272    * @type Boolean | 
| 273    */ | 273    */ | 
| 274   disabled: { | 274   get disabled() | 
| 275     get: function() | 275   { | 
|  | 276     return this._disabled; | 
|  | 277   }, | 
|  | 278   set disabled(value) | 
|  | 279   { | 
|  | 280     if (value != this._disabled) | 
| 276     { | 281     { | 
| 277       return this._disabled; | 282       let oldValue = this._disabled; | 
| 278     }, | 283       this._disabled = value; | 
| 279     set: function(value) | 284       FilterNotifier.triggerListeners("filter.disabled", this, value, oldValue); | 
| 280     { |  | 
| 281       if (value != this._disabled) |  | 
| 282       { |  | 
| 283         let oldValue = this._disabled; |  | 
| 284         this._disabled = value; |  | 
| 285         FilterNotifier.triggerListeners("filter.disabled", this, |  | 
| 286         value, oldValue); |  | 
| 287       } |  | 
| 288       return this._disabled; |  | 
| 289     } | 285     } | 
|  | 286     return this._disabled; | 
| 290   }, | 287   }, | 
| 291 | 288 | 
| 292   /** | 289   /** | 
| 293    * Number of hits on the filter since the last reset | 290    * Number of hits on the filter since the last reset | 
| 294    * @type Number | 291    * @type Number | 
| 295    */ | 292    */ | 
| 296   hitCount: { | 293   get hitCount() | 
| 297     get: function() | 294   { | 
|  | 295     return this._hitCount; | 
|  | 296   }, | 
|  | 297   set hitCount(value) | 
|  | 298   { | 
|  | 299     if (value != this._hitCount) | 
| 298     { | 300     { | 
| 299       return this._hitCount; | 301       let oldValue = this._hitCount; | 
| 300     }, | 302       this._hitCount = value; | 
| 301     set: function(value) | 303       FilterNotifier.triggerListeners("filter.hitCount", this, value, oldValue); | 
| 302     { |  | 
| 303       if (value != this._hitCount) |  | 
| 304       { |  | 
| 305         let oldValue = this._hitCount; |  | 
| 306         this._hitCount = value; |  | 
| 307         FilterNotifier.triggerListeners("filter.hitCount", this, |  | 
| 308         value, oldValue); |  | 
| 309       } |  | 
| 310       return this._hitCount; |  | 
| 311     } | 304     } | 
|  | 305     return this._hitCount; | 
| 312   }, | 306   }, | 
| 313 | 307 | 
| 314   /** | 308   /** | 
| 315    * Last time the filter had a hit (in milliseconds since the beginning of the 
      epoch) | 309    * Last time the filter had a hit (in milliseconds since the beginning of the 
      epoch) | 
| 316    * @type Number | 310    * @type Number | 
| 317    */ | 311    */ | 
| 318   lastHit: { | 312   get lastHit() | 
| 319     get: function() | 313   { | 
|  | 314     return this._lastHit; | 
|  | 315   }, | 
|  | 316   set lastHit(value) | 
|  | 317   { | 
|  | 318     if (value != this._lastHit) | 
| 320     { | 319     { | 
| 321       return this._lastHit; | 320       let oldValue = this._lastHit; | 
| 322     }, | 321       this._lastHit = value; | 
| 323     set: function(value) | 322       FilterNotifier.triggerListeners("filter.lastHit", this, value, oldValue); | 
| 324     { |  | 
| 325       if (value != this._lastHit) |  | 
| 326       { |  | 
| 327         let oldValue = this._lastHit; |  | 
| 328         this._lastHit = value; |  | 
| 329         FilterNotifier.triggerListeners("filter.lastHit", this, |  | 
| 330         value, oldValue); |  | 
| 331       } |  | 
| 332       return this._lastHit; |  | 
| 333     } | 323     } | 
|  | 324     return this._lastHit; | 
| 334   }, | 325   }, | 
| 335 | 326 | 
| 336   /** | 327   /** | 
| 337    * String that the domains property should be generated from | 328    * String that the domains property should be generated from | 
| 338    * @type String | 329    * @type String | 
| 339    */ | 330    */ | 
| 340   domainSource: null, | 331   domainSource: null, | 
| 341 | 332 | 
| 342   /** | 333   /** | 
| 343    * Separator character used in domainSource property, must be overridden by su
      bclasses | 334    * Separator character used in domainSource property, must be overridden by su
      bclasses | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
| 356    * Determines whether domainSource is already upper-case, | 347    * Determines whether domainSource is already upper-case, | 
| 357    * can be overridden by subclasses. | 348    * can be overridden by subclasses. | 
| 358    * @type Boolean | 349    * @type Boolean | 
| 359    */ | 350    */ | 
| 360   domainSourceIsUpperCase: false, | 351   domainSourceIsUpperCase: false, | 
| 361 | 352 | 
| 362   /** | 353   /** | 
| 363    * Map containing domains that this filter should match on/not match on or nul
      l if the filter should match on all domains | 354    * Map containing domains that this filter should match on/not match on or nul
      l if the filter should match on all domains | 
| 364    * @type Object | 355    * @type Object | 
| 365    */ | 356    */ | 
| 366   domains: { | 357   get domains() | 
| 367     get: function() | 358   { | 
|  | 359     // Despite this property being cached, the getter is called | 
|  | 360     // several times on Safari, due to WebKit bug 132872 | 
|  | 361     let prop = Object.getOwnPropertyDescriptor(this, "domains"); | 
|  | 362     if (prop) | 
|  | 363       return prop.value; | 
|  | 364 | 
|  | 365     let domains = null; | 
|  | 366 | 
|  | 367     if (this.domainSource) | 
| 368     { | 368     { | 
| 369       // Despite this property being cached, the getter is called | 369       let source = this.domainSource; | 
| 370       // several times on Safari, due to WebKit bug 132872 | 370       if (!this.domainSourceIsUpperCase) { | 
| 371       let prop = Object.getOwnPropertyDescriptor(this, "domains"); | 371         // RegExpFilter already have uppercase domains | 
| 372       if (prop) | 372         source = source.toUpperCase(); | 
| 373         return prop.value; | 373       } | 
| 374 | 374       let list = source.split(this.domainSeparator); | 
| 375       let domains = null; | 375       if (list.length == 1 && list[0][0] != "~") | 
| 376 |  | 
| 377       if (this.domainSource) |  | 
| 378       { | 376       { | 
| 379         let source = this.domainSource; | 377         // Fast track for the common one-domain scenario | 
| 380         if (!this.domainSourceIsUpperCase) { | 378         domains = Object.create(null); | 
| 381           // RegExpFilter already have uppercase domains | 379         domains[""] = false; | 
| 382           source = source.toUpperCase(); | 380         if (this.ignoreTrailingDot) | 
|  | 381           list[0] = list[0].replace(/\.+$/, ""); | 
|  | 382         domains[list[0]] = true; | 
|  | 383       } | 
|  | 384       else | 
|  | 385       { | 
|  | 386         let hasIncludes = false; | 
|  | 387         for (let i = 0; i < list.length; i++) | 
|  | 388         { | 
|  | 389           let domain = list[i]; | 
|  | 390           if (this.ignoreTrailingDot) | 
|  | 391             domain = domain.replace(/\.+$/, ""); | 
|  | 392           if (domain == "") | 
|  | 393             continue; | 
|  | 394 | 
|  | 395           let include; | 
|  | 396           if (domain[0] == "~") | 
|  | 397           { | 
|  | 398             include = false; | 
|  | 399             domain = domain.substr(1); | 
|  | 400           } | 
|  | 401           else | 
|  | 402           { | 
|  | 403             include = true; | 
|  | 404             hasIncludes = true; | 
|  | 405           } | 
|  | 406 | 
|  | 407           if (!domains) | 
|  | 408             domains = Object.create(null); | 
|  | 409 | 
|  | 410           domains[domain] = include; | 
| 383         } | 411         } | 
| 384         let list = source.split(this.domainSeparator); | 412         domains[""] = !hasIncludes; | 
| 385         if (list.length == 1 && list[0][0] != "~") |  | 
| 386         { |  | 
| 387           // Fast track for the common one-domain scenario |  | 
| 388           domains = Object.create(null); |  | 
| 389           domains[""] = false; |  | 
| 390           if (this.ignoreTrailingDot) |  | 
| 391             list[0] = list[0].replace(/\.+$/, ""); |  | 
| 392           domains[list[0]] = true; |  | 
| 393         } |  | 
| 394         else |  | 
| 395         { |  | 
| 396           let hasIncludes = false; |  | 
| 397           for (let i = 0; i < list.length; i++) |  | 
| 398           { |  | 
| 399             let domain = list[i]; |  | 
| 400             if (this.ignoreTrailingDot) |  | 
| 401               domain = domain.replace(/\.+$/, ""); |  | 
| 402             if (domain == "") |  | 
| 403               continue; |  | 
| 404 |  | 
| 405             let include; |  | 
| 406             if (domain[0] == "~") |  | 
| 407             { |  | 
| 408               include = false; |  | 
| 409               domain = domain.substr(1); |  | 
| 410             } |  | 
| 411             else |  | 
| 412             { |  | 
| 413               include = true; |  | 
| 414               hasIncludes = true; |  | 
| 415             } |  | 
| 416 |  | 
| 417             if (!domains) |  | 
| 418               domains = Object.create(null); |  | 
| 419 |  | 
| 420             domains[domain] = include; |  | 
| 421           } |  | 
| 422           domains[""] = !hasIncludes; |  | 
| 423         } |  | 
| 424 |  | 
| 425         this.domainSource = null; |  | 
| 426       } | 413       } | 
| 427 | 414 | 
| 428       Object.defineProperty(this, "domains", {value: domains, enumerable: true})
      ; | 415       this.domainSource = null; | 
| 429       return this.domains; |  | 
| 430     } | 416     } | 
|  | 417 | 
|  | 418     Object.defineProperty(this, "domains", {value: domains, enumerable: true}); | 
|  | 419     return this.domains; | 
| 431   }, | 420   }, | 
| 432 | 421 | 
| 433   /** | 422   /** | 
| 434    * Array containing public keys of websites that this filter should apply to | 423    * Array containing public keys of websites that this filter should apply to | 
| 435    * @type string[] | 424    * @type string[] | 
| 436    */ | 425    */ | 
| 437   sitekeys: null, | 426   sitekeys: null, | 
| 438 | 427 | 
| 439   /** | 428   /** | 
| 440    * Checks whether this filter is active on a domain. | 429    * Checks whether this filter is active on a domain. | 
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 511     { | 500     { | 
| 512       Filter.prototype.serialize.call(this, buffer); | 501       Filter.prototype.serialize.call(this, buffer); | 
| 513       if (this._disabled) | 502       if (this._disabled) | 
| 514         buffer.push("disabled=true"); | 503         buffer.push("disabled=true"); | 
| 515       if (this._hitCount) | 504       if (this._hitCount) | 
| 516         buffer.push("hitCount=" + this._hitCount); | 505         buffer.push("hitCount=" + this._hitCount); | 
| 517       if (this._lastHit) | 506       if (this._lastHit) | 
| 518         buffer.push("lastHit=" + this._lastHit); | 507         buffer.push("lastHit=" + this._lastHit); | 
| 519     } | 508     } | 
| 520   } | 509   } | 
| 521 })); | 510 }); | 
| 522 | 511 | 
| 523 /** | 512 /** | 
| 524  * Abstract base class for RegExp-based filters | 513  * Abstract base class for RegExp-based filters | 
| 525  * @param {String} text see Filter() | 514  * @param {String} text see Filter() | 
| 526  * @param {String} regexpSource filter part that the regular expression should b
      e build from | 515  * @param {String} regexpSource filter part that the regular expression should b
      e build from | 
| 527  * @param {Number} [contentType] Content types the filter applies to, combinatio
      n of values from RegExpFilter.typeMap | 516  * @param {Number} [contentType] Content types the filter applies to, combinatio
      n of values from RegExpFilter.typeMap | 
| 528  * @param {Boolean} [matchCase] Defines whether the filter should distinguish be
      tween lower and upper case letters | 517  * @param {Boolean} [matchCase] Defines whether the filter should distinguish be
      tween lower and upper case letters | 
| 529  * @param {String} [domains] Domains that the filter is restricted to, e.g. "foo
      .com|bar.com|~baz.com" | 518  * @param {String} [domains] Domains that the filter is restricted to, e.g. "foo
      .com|bar.com|~baz.com" | 
| 530  * @param {Boolean} [thirdParty] Defines whether the filter should apply to thir
      d-party or first-party content only | 519  * @param {Boolean} [thirdParty] Defines whether the filter should apply to thir
      d-party or first-party content only | 
| 531  * @param {String} [sitekeys] Public keys of websites that this filter should ap
      ply to | 520  * @param {String} [sitekeys] Public keys of websites that this filter should ap
      ply to | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
| 552     Object.defineProperty(this, "regexp", {value: regexp}); | 541     Object.defineProperty(this, "regexp", {value: regexp}); | 
| 553   } | 542   } | 
| 554   else | 543   else | 
| 555   { | 544   { | 
| 556     // No need to convert this filter to regular expression yet, do it on demand | 545     // No need to convert this filter to regular expression yet, do it on demand | 
| 557     this.regexpSource = regexpSource; | 546     this.regexpSource = regexpSource; | 
| 558   } | 547   } | 
| 559 } | 548 } | 
| 560 exports.RegExpFilter = RegExpFilter; | 549 exports.RegExpFilter = RegExpFilter; | 
| 561 | 550 | 
| 562 RegExpFilter.prototype = Object.create(ActiveFilter.prototype, desc({ | 551 RegExpFilter.prototype = extend(ActiveFilter, { | 
| 563   /** | 552   /** | 
| 564    * @see ActiveFilter.domainSourceIsUpperCase | 553    * @see ActiveFilter.domainSourceIsUpperCase | 
| 565    */ | 554    */ | 
| 566   domainSourceIsUpperCase: true, | 555   domainSourceIsUpperCase: true, | 
| 567 | 556 | 
| 568   /** | 557   /** | 
| 569    * Number of filters contained, will always be 1 (required to optimize Matcher
      ). | 558    * Number of filters contained, will always be 1 (required to optimize Matcher
      ). | 
| 570    * @type Integer | 559    * @type Integer | 
| 571    */ | 560    */ | 
| 572   length: 1, | 561   length: 1, | 
| 573 | 562 | 
| 574   /** | 563   /** | 
| 575    * @see ActiveFilter.domainSeparator | 564    * @see ActiveFilter.domainSeparator | 
| 576    */ | 565    */ | 
| 577   domainSeparator: "|", | 566   domainSeparator: "|", | 
| 578 | 567 | 
| 579   /** | 568   /** | 
| 580    * Expression from which a regular expression should be generated - for delaye
      d creation of the regexp property | 569    * Expression from which a regular expression should be generated - for delaye
      d creation of the regexp property | 
| 581    * @type String | 570    * @type String | 
| 582    */ | 571    */ | 
| 583   regexpSource: null, | 572   regexpSource: null, | 
| 584   /** | 573   /** | 
| 585    * Regular expression to be used when testing against this filter | 574    * Regular expression to be used when testing against this filter | 
| 586    * @type RegExp | 575    * @type RegExp | 
| 587    */ | 576    */ | 
| 588   regexp: { | 577   get regexp() | 
| 589     get: function() | 578   { | 
| 590     { | 579     // Despite this property being cached, the getter is called | 
| 591       // Despite this property being cached, the getter is called | 580     // several times on Safari, due to WebKit bug 132872 | 
| 592       // several times on Safari, due to WebKit bug 132872 | 581     let prop = Object.getOwnPropertyDescriptor(this, "regexp"); | 
| 593       let prop = Object.getOwnPropertyDescriptor(this, "regexp"); | 582     if (prop) | 
| 594       if (prop) | 583       return prop.value; | 
| 595         return prop.value; | 584 | 
| 596 | 585     let source = Filter.toRegExp(this.regexpSource); | 
| 597       let source = Filter.toRegExp(this.regexpSource); | 586     let regexp = new RegExp(source, this.matchCase ? "" : "i"); | 
| 598       let regexp = new RegExp(source, this.matchCase ? "" : "i"); | 587     Object.defineProperty(this, "regexp", {value: regexp}); | 
| 599       Object.defineProperty(this, "regexp", {value: regexp}); | 588     return regexp; | 
| 600       return regexp; | 589   }, | 
| 601     } |  | 
| 602   }, |  | 
| 603 |  | 
| 604   /** | 590   /** | 
| 605    * Content types the filter applies to, combination of values from RegExpFilte
      r.typeMap | 591    * Content types the filter applies to, combination of values from RegExpFilte
      r.typeMap | 
| 606    * @type Number | 592    * @type Number | 
| 607    */ | 593    */ | 
| 608   contentType: 0x7FFFFFFF, | 594   contentType: 0x7FFFFFFF, | 
| 609   /** | 595   /** | 
| 610    * Defines whether the filter should distinguish between lower and upper case 
      letters | 596    * Defines whether the filter should distinguish between lower and upper case 
      letters | 
| 611    * @type Boolean | 597    * @type Boolean | 
| 612    */ | 598    */ | 
| 613   matchCase: false, | 599   matchCase: false, | 
| 614   /** | 600   /** | 
| 615    * Defines whether the filter should apply to third-party or first-party conte
      nt only. Can be null (apply to all content). | 601    * Defines whether the filter should apply to third-party or first-party conte
      nt only. Can be null (apply to all content). | 
| 616    * @type Boolean | 602    * @type Boolean | 
| 617    */ | 603    */ | 
| 618   thirdParty: null, | 604   thirdParty: null, | 
| 619 | 605 | 
| 620   /** | 606   /** | 
| 621    * String that the sitekey property should be generated from | 607    * String that the sitekey property should be generated from | 
| 622    * @type String | 608    * @type String | 
| 623    */ | 609    */ | 
| 624   sitekeySource: null, | 610   sitekeySource: null, | 
| 625 | 611 | 
| 626   /** | 612   /** | 
| 627    * Array containing public keys of websites that this filter should apply to | 613    * Array containing public keys of websites that this filter should apply to | 
| 628    * @type string[] | 614    * @type string[] | 
| 629    */ | 615    */ | 
| 630   sitekeys: { | 616   get sitekeys() | 
| 631     get: function() | 617   { | 
|  | 618     // Despite this property being cached, the getter is called | 
|  | 619     // several times on Safari, due to WebKit bug 132872 | 
|  | 620     let prop = Object.getOwnPropertyDescriptor(this, "sitekeys"); | 
|  | 621     if (prop) | 
|  | 622       return prop.value; | 
|  | 623 | 
|  | 624     let sitekeys = null; | 
|  | 625 | 
|  | 626     if (this.sitekeySource) | 
| 632     { | 627     { | 
| 633       // Despite this property being cached, the getter is called | 628       sitekeys = this.sitekeySource.split("|"); | 
| 634       // several times on Safari, due to WebKit bug 132872 | 629       this.sitekeySource = null; | 
| 635       let prop = Object.getOwnPropertyDescriptor(this, "sitekeys"); |  | 
| 636       if (prop) |  | 
| 637         return prop.value; |  | 
| 638 |  | 
| 639       let sitekeys = null; |  | 
| 640 |  | 
| 641       if (this.sitekeySource) |  | 
| 642       { |  | 
| 643         sitekeys = this.sitekeySource.split("|"); |  | 
| 644         this.sitekeySource = null; |  | 
| 645       } |  | 
| 646 |  | 
| 647       Object.defineProperty(this, "sitekeys", {value: sitekeys, enumerable: true
      }); |  | 
| 648       return this.sitekeys; |  | 
| 649     } | 630     } | 
|  | 631 | 
|  | 632     Object.defineProperty(this, "sitekeys", {value: sitekeys, enumerable: true})
      ; | 
|  | 633     return this.sitekeys; | 
| 650   }, | 634   }, | 
| 651 | 635 | 
| 652   /** | 636   /** | 
| 653    * Tests whether the URL matches this filter | 637    * Tests whether the URL matches this filter | 
| 654    * @param {String} location URL to be tested | 638    * @param {String} location URL to be tested | 
| 655    * @param {number} typeMask bitmask of content / request types to match | 639    * @param {number} typeMask bitmask of content / request types to match | 
| 656    * @param {String} docDomain domain name of the document that loads the URL | 640    * @param {String} docDomain domain name of the document that loads the URL | 
| 657    * @param {Boolean} thirdParty should be true if the URL is a third-party requ
      est | 641    * @param {Boolean} thirdParty should be true if the URL is a third-party requ
      est | 
| 658    * @param {String} sitekey public key provided by the document | 642    * @param {String} sitekey public key provided by the document | 
| 659    * @return {Boolean} true in case of a match | 643    * @return {Boolean} true in case of a match | 
| 660    */ | 644    */ | 
| 661   matches: function(location, typeMask, docDomain, thirdParty, sitekey) | 645   matches: function(location, typeMask, docDomain, thirdParty, sitekey) | 
| 662   { | 646   { | 
| 663     if (this.contentType & typeMask && | 647     if (this.contentType & typeMask && | 
| 664         (this.thirdParty == null || this.thirdParty == thirdParty) && | 648         (this.thirdParty == null || this.thirdParty == thirdParty) && | 
| 665         this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location)) | 649         this.isActiveOnDomain(docDomain, sitekey) && this.regexp.test(location)) | 
| 666     { | 650     { | 
| 667       return true; | 651       return true; | 
| 668     } | 652     } | 
| 669 | 653 | 
| 670     return false; | 654     return false; | 
| 671   }, | 655   } | 
| 672 | 656 }); | 
| 673   // Required to optimize Matcher, see also RegExpFilter.prototype.length | 657 | 
| 674   0: { | 658 // Required to optimize Matcher, see also RegExpFilter.prototype.length | 
| 675     get: function() { return this; } | 659 Object.defineProperty(RegExpFilter.prototype, "0", | 
| 676   } | 660 { | 
| 677 })); | 661   get: function() { return this; } | 
|  | 662 }); | 
| 678 | 663 | 
| 679 /** | 664 /** | 
| 680  * Creates a RegExp filter from its text representation | 665  * Creates a RegExp filter from its text representation | 
| 681  * @param {String} text   same as in Filter() | 666  * @param {String} text   same as in Filter() | 
| 682  */ | 667  */ | 
| 683 RegExpFilter.fromText = function(text) | 668 RegExpFilter.fromText = function(text) | 
| 684 { | 669 { | 
| 685   let blocking = true; | 670   let blocking = true; | 
| 686   let origText = text; | 671   let origText = text; | 
| 687   if (text.indexOf("@@") == 0) | 672   if (text.indexOf("@@") == 0) | 
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 807  * @augments RegExpFilter | 792  * @augments RegExpFilter | 
| 808  */ | 793  */ | 
| 809 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi
      rdParty, sitekeys, collapse) | 794 function BlockingFilter(text, regexpSource, contentType, matchCase, domains, thi
      rdParty, sitekeys, collapse) | 
| 810 { | 795 { | 
| 811   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t
      hirdParty, sitekeys); | 796   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t
      hirdParty, sitekeys); | 
| 812 | 797 | 
| 813   this.collapse = collapse; | 798   this.collapse = collapse; | 
| 814 } | 799 } | 
| 815 exports.BlockingFilter = BlockingFilter; | 800 exports.BlockingFilter = BlockingFilter; | 
| 816 | 801 | 
| 817 BlockingFilter.prototype = Object.create(RegExpFilter.prototype, desc({ | 802 BlockingFilter.prototype = extend(RegExpFilter, { | 
| 818   type: "blocking", | 803   type: "blocking", | 
| 819 | 804 | 
| 820   /** | 805   /** | 
| 821    * Defines whether the filter should collapse blocked content. Can be null (us
      e the global preference). | 806    * Defines whether the filter should collapse blocked content. Can be null (us
      e the global preference). | 
| 822    * @type Boolean | 807    * @type Boolean | 
| 823    */ | 808    */ | 
| 824   collapse: null | 809   collapse: null | 
| 825 })); | 810 }); | 
| 826 | 811 | 
| 827 /** | 812 /** | 
| 828  * Class for whitelist filters | 813  * Class for whitelist filters | 
| 829  * @param {String} text see Filter() | 814  * @param {String} text see Filter() | 
| 830  * @param {String} regexpSource see RegExpFilter() | 815  * @param {String} regexpSource see RegExpFilter() | 
| 831  * @param {Number} contentType see RegExpFilter() | 816  * @param {Number} contentType see RegExpFilter() | 
| 832  * @param {Boolean} matchCase see RegExpFilter() | 817  * @param {Boolean} matchCase see RegExpFilter() | 
| 833  * @param {String} domains see RegExpFilter() | 818  * @param {String} domains see RegExpFilter() | 
| 834  * @param {Boolean} thirdParty see RegExpFilter() | 819  * @param {Boolean} thirdParty see RegExpFilter() | 
| 835  * @param {String} sitekeys see RegExpFilter() | 820  * @param {String} sitekeys see RegExpFilter() | 
| 836  * @constructor | 821  * @constructor | 
| 837  * @augments RegExpFilter | 822  * @augments RegExpFilter | 
| 838  */ | 823  */ | 
| 839 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th
      irdParty, sitekeys) | 824 function WhitelistFilter(text, regexpSource, contentType, matchCase, domains, th
      irdParty, sitekeys) | 
| 840 { | 825 { | 
| 841   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t
      hirdParty, sitekeys); | 826   RegExpFilter.call(this, text, regexpSource, contentType, matchCase, domains, t
      hirdParty, sitekeys); | 
| 842 } | 827 } | 
| 843 exports.WhitelistFilter = WhitelistFilter; | 828 exports.WhitelistFilter = WhitelistFilter; | 
| 844 | 829 | 
| 845 WhitelistFilter.prototype = Object.create(RegExpFilter.prototype, desc({ | 830 WhitelistFilter.prototype = extend(RegExpFilter, { | 
| 846   type: "whitelist" | 831   type: "whitelist" | 
| 847 })); | 832 }); | 
| 848 | 833 | 
| 849 /** | 834 /** | 
| 850  * Base class for element hiding filters | 835  * Base class for element hiding filters | 
| 851  * @param {String} text see Filter() | 836  * @param {String} text see Filter() | 
| 852  * @param {String} [domains] Host names or domains the filter should be restrict
      ed to | 837  * @param {String} [domains] Host names or domains the filter should be restrict
      ed to | 
| 853  * @param {String} selector   CSS selector for the HTML elements that should be 
      hidden | 838  * @param {String} selector   CSS selector for the HTML elements that should be 
      hidden | 
| 854  * @constructor | 839  * @constructor | 
| 855  * @augments ActiveFilter | 840  * @augments ActiveFilter | 
| 856  */ | 841  */ | 
| 857 function ElemHideBase(text, domains, selector) | 842 function ElemHideBase(text, domains, selector) | 
| 858 { | 843 { | 
| 859   ActiveFilter.call(this, text, domains || null); | 844   ActiveFilter.call(this, text, domains || null); | 
| 860 | 845 | 
| 861   if (domains) | 846   if (domains) | 
| 862     this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, "
      ").toLowerCase(); | 847     this.selectorDomain = domains.replace(/,~[^,]+/g, "").replace(/^~[^,]+,?/, "
      ").toLowerCase(); | 
| 863   this.selector = selector; | 848   this.selector = selector; | 
| 864 } | 849 } | 
| 865 exports.ElemHideBase = ElemHideBase; | 850 exports.ElemHideBase = ElemHideBase; | 
| 866 | 851 | 
| 867 ElemHideBase.prototype = Object.create(ActiveFilter.prototype, desc({ | 852 ElemHideBase.prototype = extend(ActiveFilter, { | 
| 868   /** | 853   /** | 
| 869    * @see ActiveFilter.domainSeparator | 854    * @see ActiveFilter.domainSeparator | 
| 870    */ | 855    */ | 
| 871   domainSeparator: ",", | 856   domainSeparator: ",", | 
| 872 | 857 | 
| 873   /** | 858   /** | 
| 874    * @see ActiveFilter.ignoreTrailingDot | 859    * @see ActiveFilter.ignoreTrailingDot | 
| 875    */ | 860    */ | 
| 876   ignoreTrailingDot: false, | 861   ignoreTrailingDot: false, | 
| 877 | 862 | 
| 878   /** | 863   /** | 
| 879    * Host name or domain the filter should be restricted to (can be null for no 
      restriction) | 864    * Host name or domain the filter should be restricted to (can be null for no 
      restriction) | 
| 880    * @type String | 865    * @type String | 
| 881    */ | 866    */ | 
| 882   selectorDomain: null, | 867   selectorDomain: null, | 
| 883   /** | 868   /** | 
| 884    * CSS selector for the HTML elements that should be hidden | 869    * CSS selector for the HTML elements that should be hidden | 
| 885    * @type String | 870    * @type String | 
| 886    */ | 871    */ | 
| 887   selector: null | 872   selector: null | 
| 888 })); | 873 }); | 
| 889 | 874 | 
| 890 /** | 875 /** | 
| 891  * Creates an element hiding filter from a pre-parsed text representation | 876  * Creates an element hiding filter from a pre-parsed text representation | 
| 892  * | 877  * | 
| 893  * @param {String} text         same as in Filter() | 878  * @param {String} text         same as in Filter() | 
| 894  * @param {String} domain       domain part of the text representation (can be e
      mpty) | 879  * @param {String} domain       domain part of the text representation (can be e
      mpty) | 
| 895  * @param {Boolean} isException exception rule indicator | 880  * @param {Boolean} isException exception rule indicator | 
| 896  * @param {String} tagName      tag name part (can be empty) | 881  * @param {String} tagName      tag name part (can be empty) | 
| 897  * @param {String} attrRules    attribute matching rules (can be empty) | 882  * @param {String} attrRules    attribute matching rules (can be empty) | 
| 898  * @param {String} selector     raw CSS selector (can be empty) | 883  * @param {String} selector     raw CSS selector (can be empty) | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 963  * @param {String} selector see ElemHideBase() | 948  * @param {String} selector see ElemHideBase() | 
| 964  * @constructor | 949  * @constructor | 
| 965  * @augments ElemHideBase | 950  * @augments ElemHideBase | 
| 966  */ | 951  */ | 
| 967 function ElemHideFilter(text, domains, selector) | 952 function ElemHideFilter(text, domains, selector) | 
| 968 { | 953 { | 
| 969   ElemHideBase.call(this, text, domains, selector); | 954   ElemHideBase.call(this, text, domains, selector); | 
| 970 } | 955 } | 
| 971 exports.ElemHideFilter = ElemHideFilter; | 956 exports.ElemHideFilter = ElemHideFilter; | 
| 972 | 957 | 
| 973 ElemHideFilter.prototype = Object.create(ElemHideBase.prototype, desc({ | 958 ElemHideFilter.prototype = extend(ElemHideBase, { | 
| 974   type: "elemhide" | 959   type: "elemhide" | 
| 975 })); | 960 }); | 
| 976 | 961 | 
| 977 /** | 962 /** | 
| 978  * Class for element hiding exceptions | 963  * Class for element hiding exceptions | 
| 979  * @param {String} text see Filter() | 964  * @param {String} text see Filter() | 
| 980  * @param {String} domains  see ElemHideBase() | 965  * @param {String} domains  see ElemHideBase() | 
| 981  * @param {String} selector see ElemHideBase() | 966  * @param {String} selector see ElemHideBase() | 
| 982  * @constructor | 967  * @constructor | 
| 983  * @augments ElemHideBase | 968  * @augments ElemHideBase | 
| 984  */ | 969  */ | 
| 985 function ElemHideException(text, domains, selector) | 970 function ElemHideException(text, domains, selector) | 
| 986 { | 971 { | 
| 987   ElemHideBase.call(this, text, domains, selector); | 972   ElemHideBase.call(this, text, domains, selector); | 
| 988 } | 973 } | 
| 989 exports.ElemHideException = ElemHideException; | 974 exports.ElemHideException = ElemHideException; | 
| 990 | 975 | 
| 991 ElemHideException.prototype = Object.create(ElemHideBase.prototype, desc({ | 976 ElemHideException.prototype = extend(ElemHideBase, { | 
| 992   type: "elemhideexception" | 977   type: "elemhideexception" | 
| 993 })); | 978 }); | 
| 994 | 979 | 
| 995 /** | 980 /** | 
| 996  * Class for CSS property filters | 981  * Class for CSS property filters | 
| 997  * @param {String} text           see Filter() | 982  * @param {String} text           see Filter() | 
| 998  * @param {String} domains        see ElemHideBase() | 983  * @param {String} domains        see ElemHideBase() | 
| 999  * @param {String} selector       see ElemHideBase() | 984  * @param {String} selector       see ElemHideBase() | 
| 1000  * @param {String} regexpSource   see CSSPropertyFilter.regexpSource | 985  * @param {String} regexpSource   see CSSPropertyFilter.regexpSource | 
| 1001  * @param {String} selectorPrefix see CSSPropertyFilter.selectorPrefix | 986  * @param {String} selectorPrefix see CSSPropertyFilter.selectorPrefix | 
| 1002  * @param {String} selectorSuffix see CSSPropertyFilter.selectorSuffix | 987  * @param {String} selectorSuffix see CSSPropertyFilter.selectorSuffix | 
| 1003  * @constructor | 988  * @constructor | 
| 1004  * @augments ElemHideBase | 989  * @augments ElemHideBase | 
| 1005  */ | 990  */ | 
| 1006 function CSSPropertyFilter(text, domains, selector, regexpSource, | 991 function CSSPropertyFilter(text, domains, selector, regexpSource, | 
| 1007   selectorPrefix, selectorSuffix) | 992   selectorPrefix, selectorSuffix) | 
| 1008 { | 993 { | 
| 1009   ElemHideBase.call(this, text, domains, selector); | 994   ElemHideBase.call(this, text, domains, selector); | 
| 1010 | 995 | 
| 1011   this.regexpSource = regexpSource; | 996   this.regexpSource = regexpSource; | 
| 1012   this.selectorPrefix = selectorPrefix; | 997   this.selectorPrefix = selectorPrefix; | 
| 1013   this.selectorSuffix = selectorSuffix; | 998   this.selectorSuffix = selectorSuffix; | 
| 1014 } | 999 } | 
| 1015 exports.CSSPropertyFilter = CSSPropertyFilter; | 1000 exports.CSSPropertyFilter = CSSPropertyFilter; | 
| 1016 | 1001 | 
| 1017 CSSPropertyFilter.prototype = Object.create(ElemHideBase.prototype, desc({ | 1002 CSSPropertyFilter.prototype = extend(ElemHideBase, { | 
| 1018   type: "cssproperty", | 1003   type: "cssproperty", | 
| 1019 | 1004 | 
| 1020   /** | 1005   /** | 
| 1021    * Expression from which a regular expression should be generated for matching | 1006    * Expression from which a regular expression should be generated for matching | 
| 1022    * CSS properties - for delayed creation of the regexpString property | 1007    * CSS properties - for delayed creation of the regexpString property | 
| 1023    * @type String | 1008    * @type String | 
| 1024    */ | 1009    */ | 
| 1025   regexpSource: null, | 1010   regexpSource: null, | 
| 1026   /** | 1011   /** | 
| 1027    * Substring of CSS selector before properties for the HTML elements that | 1012    * Substring of CSS selector before properties for the HTML elements that | 
| 1028    * should be hidden | 1013    * should be hidden | 
| 1029    * @type String | 1014    * @type String | 
| 1030    */ | 1015    */ | 
| 1031   selectorPrefix: null, | 1016   selectorPrefix: null, | 
| 1032   /** | 1017   /** | 
| 1033    * Substring of CSS selector after properties for the HTML elements that | 1018    * Substring of CSS selector after properties for the HTML elements that | 
| 1034    * should be hidden | 1019    * should be hidden | 
| 1035    * @type String | 1020    * @type String | 
| 1036    */ | 1021    */ | 
| 1037   selectorSuffix: null, | 1022   selectorSuffix: null, | 
| 1038 | 1023 | 
| 1039   /** | 1024   /** | 
| 1040    * Raw regular expression string to be used when testing CSS properties | 1025    * Raw regular expression string to be used when testing CSS properties | 
| 1041    * against this filter | 1026    * against this filter | 
| 1042    * @type String | 1027    * @type String | 
| 1043    */ | 1028    */ | 
| 1044   regexpString: { | 1029   get regexpString() | 
| 1045     get: function() | 1030   { | 
| 1046     { | 1031     // Despite this property being cached, the getter is called | 
| 1047       // Despite this property being cached, the getter is called | 1032     // several times on Safari, due to WebKit bug 132872 | 
| 1048       // several times on Safari, due to WebKit bug 132872 | 1033     let prop = Object.getOwnPropertyDescriptor(this, "regexpString"); | 
| 1049       let prop = Object.getOwnPropertyDescriptor(this, "regexpString"); | 1034     if (prop) | 
| 1050       if (prop) | 1035       return prop.value; | 
| 1051         return prop.value; | 1036 | 
| 1052 | 1037     let regexp = Filter.toRegExp(this.regexpSource); | 
| 1053       let regexp = Filter.toRegExp(this.regexpSource); | 1038     Object.defineProperty(this, "regexpString", {value: regexp}); | 
| 1054       Object.defineProperty(this, "regexpString", {value: regexp}); | 1039     return regexp; | 
| 1055       return regexp; | 1040   } | 
| 1056     } | 1041 }); | 
| 1057   } |  | 
| 1058 })); |  | 
| LEFT | RIGHT | 
|---|