| 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 | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 29 /** | 29 /** | 
| 30  * Abstract base class for filter subscriptions | 30  * Abstract base class for filter subscriptions | 
| 31  * | 31  * | 
| 32  * @param {string} url    download location of the subscription | 32  * @param {string} url    download location of the subscription | 
| 33  * @param {string} [title]  title of the filter subscription | 33  * @param {string} [title]  title of the filter subscription | 
| 34  * @constructor | 34  * @constructor | 
| 35  */ | 35  */ | 
| 36 function Subscription(url, title) | 36 function Subscription(url, title) | 
| 37 { | 37 { | 
| 38   this.url = url; | 38   this.url = url; | 
| 39   this.filters = []; | 39 | 
|  | 40   this._filterText = []; | 
|  | 41   this._filters = []; | 
|  | 42 | 
|  | 43   this._filterTextSet = new Set(); | 
|  | 44 | 
| 40   if (title) | 45   if (title) | 
| 41     this._title = title; | 46     this._title = title; | 
|  | 47 | 
| 42   Subscription.knownSubscriptions.set(url, this); | 48   Subscription.knownSubscriptions.set(url, this); | 
| 43 } | 49 } | 
| 44 exports.Subscription = Subscription; | 50 exports.Subscription = Subscription; | 
| 45 | 51 | 
| 46 Subscription.prototype = | 52 Subscription.prototype = | 
| 47 { | 53 { | 
| 48   /** | 54   /** | 
| 49    * Download location of the subscription | 55    * Download location of the subscription | 
| 50    * @type {string} | 56    * @type {string} | 
| 51    */ | 57    */ | 
| 52   url: null, | 58   url: null, | 
| 53 | 59 | 
| 54   /** | 60   /** | 
| 55    * Type of the subscription | 61    * Type of the subscription | 
| 56    * @type {?string} | 62    * @type {?string} | 
| 57    */ | 63    */ | 
| 58   type: null, | 64   type: null, | 
| 59 | 65 | 
| 60   /** | 66   /** | 
| 61    * Filters contained in the filter subscription | 67    * Filter text contained in the filter subscription. | 
| 62    * @type {Filter[]} | 68    * @type {Array.<string>} | 
|  | 69    * @private | 
| 63    */ | 70    */ | 
| 64   filters: null, | 71   _filterText: null, | 
|  | 72 | 
|  | 73   /** | 
|  | 74    * {@link Filter} objects corresponding to the subscription's filter text. | 
|  | 75    * @type {Array.<Filter>} | 
|  | 76    * @private | 
|  | 77    */ | 
|  | 78   _filters: null, | 
|  | 79 | 
|  | 80   /** | 
|  | 81    * Set of filter text contained in the filter subscription, used for faster | 
|  | 82    * lookup. | 
|  | 83    * @type {Set.<string>} | 
|  | 84    * @private | 
|  | 85    */ | 
|  | 86   _filterTextSet: null, | 
| 65 | 87 | 
| 66   _title: null, | 88   _title: null, | 
| 67   _fixedTitle: false, | 89   _fixedTitle: false, | 
| 68   _disabled: false, | 90   _disabled: false, | 
| 69 | 91 | 
| 70   /** | 92   /** | 
| 71    * Title of the filter subscription | 93    * Title of the filter subscription | 
| 72    * @type {string} | 94    * @type {string} | 
| 73    */ | 95    */ | 
| 74   get title() | 96   get title() | 
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 118     if (value != this._disabled) | 140     if (value != this._disabled) | 
| 119     { | 141     { | 
| 120       let oldValue = this._disabled; | 142       let oldValue = this._disabled; | 
| 121       this._disabled = value; | 143       this._disabled = value; | 
| 122       filterNotifier.emit("subscription.disabled", this, value, oldValue); | 144       filterNotifier.emit("subscription.disabled", this, value, oldValue); | 
| 123     } | 145     } | 
| 124     return this._disabled; | 146     return this._disabled; | 
| 125   }, | 147   }, | 
| 126 | 148 | 
| 127   /** | 149   /** | 
|  | 150    * The number of filters in the subscription. | 
|  | 151    * @type {number} | 
|  | 152    */ | 
|  | 153   get filterCount() | 
|  | 154   { | 
|  | 155     return this._filters.length; | 
|  | 156   }, | 
|  | 157 | 
|  | 158   /** | 
|  | 159    * Yields the text for each filter in the subscription. | 
|  | 160    * @yields {string} | 
|  | 161    */ | 
|  | 162   *filterText() | 
|  | 163   { | 
|  | 164     yield* this._filterText; | 
|  | 165   }, | 
|  | 166 | 
|  | 167   /** | 
|  | 168    * Yields the {@link Filter} object for each filter in the subscription. | 
|  | 169    * @yields {Filter} | 
|  | 170    */ | 
|  | 171   *filters() | 
|  | 172   { | 
|  | 173     yield* this._filters; | 
|  | 174   }, | 
|  | 175 | 
|  | 176   /** | 
|  | 177    * Returns the {@link Filter} object at the given 0-based index. | 
|  | 178    * @param {number} index | 
|  | 179    * @returns {?Filter} | 
|  | 180    */ | 
|  | 181   filterAt(index) | 
|  | 182   { | 
|  | 183     return this._filters[index] || null; | 
|  | 184   }, | 
|  | 185 | 
|  | 186   /** | 
|  | 187    * Returns the 0-based index of the given filter. | 
|  | 188    * @param {Filter} filter | 
|  | 189    * @param {number} [fromIndex] The index from which to start the search. | 
|  | 190    * @return {number} | 
|  | 191    */ | 
|  | 192   searchFilter(filter, fromIndex = 0) | 
|  | 193   { | 
|  | 194     return this._filterText.indexOf(filter.text, fromIndex); | 
|  | 195   }, | 
|  | 196 | 
|  | 197   /** | 
|  | 198    * Checks whether the subscription contains the given filter. | 
|  | 199    * @param {Filter} filter | 
|  | 200    * @return {boolean} | 
|  | 201    */ | 
|  | 202   hasFilter(filter) | 
|  | 203   { | 
|  | 204     return this._filterTextSet.has(filter.text); | 
|  | 205   }, | 
|  | 206 | 
|  | 207   /** | 
|  | 208    * Removes all filters from the subscription. | 
|  | 209    */ | 
|  | 210   clearFilters() | 
|  | 211   { | 
|  | 212     this._filterText = []; | 
|  | 213     this._filters = []; | 
|  | 214 | 
|  | 215     this._filterTextSet.clear(); | 
|  | 216   }, | 
|  | 217 | 
|  | 218   /** | 
|  | 219    * Adds a filter to the subscription. | 
|  | 220    * @param {Filter} filter | 
|  | 221    */ | 
|  | 222   addFilter(filter) | 
|  | 223   { | 
|  | 224     this._filterText.push(filter.text); | 
|  | 225     this._filters.push(filter); | 
|  | 226 | 
|  | 227     this._filterTextSet.add(filter.text); | 
|  | 228   }, | 
|  | 229 | 
|  | 230   /** | 
|  | 231    * Inserts a filter into the subscription. | 
|  | 232    * @param {Filter} filter | 
|  | 233    * @param {number} index The index at which to insert the filter. | 
|  | 234    */ | 
|  | 235   insertFilterAt(filter, index) | 
|  | 236   { | 
|  | 237     this._filterText.splice(index, 0, filter.text); | 
|  | 238     this._filters.splice(index, 0, filter); | 
|  | 239 | 
|  | 240     this._filterTextSet.add(filter.text); | 
|  | 241   }, | 
|  | 242 | 
|  | 243   /** | 
|  | 244    * Deletes a filter from the subscription. | 
|  | 245    * @param {number} index The index at which to delete the filter. | 
|  | 246    */ | 
|  | 247   deleteFilterAt(index) | 
|  | 248   { | 
|  | 249     let items = this._filterText.splice(index, 1); | 
|  | 250 | 
|  | 251     this._filters.splice(index, 1); | 
|  | 252 | 
|  | 253     // Performance note: A subscription can contain the same filter multiple | 
|  | 254     // times. We can only delete the text from the set if all occurrences of | 
|  | 255     // the filter have been removed. This makes deletion an expensive | 
|  | 256     // operation. It is only needed when a user-defined filter is removed, | 
|  | 257     // which is relatively rare. In comparison, filters must be looked up in | 
|  | 258     // subscriptions a lot more often; therefore, it makes sense to maintain | 
|  | 259     // the set at this cost. An alternative here would be to use a map instead | 
|  | 260     // of a set, with the value of each entry being the reference count, but | 
|  | 261     // this would make addition more expensive thus slowing down the loading of | 
|  | 262     // the initial subscriptions. | 
|  | 263     if (items.length > 0 && this._filterText.indexOf(items[0]) == -1) | 
|  | 264       this._filterTextSet.delete(items[0]); | 
|  | 265   }, | 
|  | 266 | 
|  | 267   /** | 
| 128    * Serializes the subscription for writing out on disk. | 268    * Serializes the subscription for writing out on disk. | 
| 129    * @yields {string} | 269    * @yields {string} | 
| 130    */ | 270    */ | 
| 131   *serialize() | 271   *serialize() | 
| 132   { | 272   { | 
| 133     let {url, type, _title, _fixedTitle, _disabled} = this; | 273     let {url, type, _title, _fixedTitle, _disabled} = this; | 
| 134 | 274 | 
| 135     yield "[Subscription]"; | 275     yield "[Subscription]"; | 
| 136     yield "url=" + url; | 276     yield "url=" + url; | 
| 137 | 277 | 
| 138     if (type) | 278     if (type) | 
| 139       yield "type=" + type; | 279       yield "type=" + type; | 
| 140     if (_title) | 280     if (_title) | 
| 141       yield "title=" + _title; | 281       yield "title=" + _title; | 
| 142     if (_fixedTitle) | 282     if (_fixedTitle) | 
| 143       yield "fixedTitle=true"; | 283       yield "fixedTitle=true"; | 
| 144     if (_disabled) | 284     if (_disabled) | 
| 145       yield "disabled=true"; | 285       yield "disabled=true"; | 
| 146   }, | 286   }, | 
| 147 | 287 | 
| 148   *serializeFilters() | 288   *serializeFilters() | 
| 149   { | 289   { | 
| 150     let {filters} = this; | 290     let {_filterText} = this; | 
| 151 | 291 | 
| 152     yield "[Subscription filters]"; | 292     yield "[Subscription filters]"; | 
| 153 | 293 | 
| 154     for (let filter of filters) | 294     for (let text of _filterText) | 
| 155       yield filter.text.replace(/\[/g, "\\["); | 295       yield text.replace(/\[/g, "\\["); | 
| 156   }, | 296   }, | 
| 157 | 297 | 
| 158   toString() | 298   toString() | 
| 159   { | 299   { | 
| 160     return [...this.serialize()].join("\n"); | 300     return [...this.serialize()].join("\n"); | 
| 161   } | 301   } | 
| 162 }; | 302 }; | 
| 163 | 303 | 
| 164 /** | 304 /** | 
| 165  * Cache for known filter subscriptions, maps URL to subscription objects. | 305  * Cache for known filter subscriptions, maps URL to subscription objects. | 
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 326 | 466 | 
| 327 /** | 467 /** | 
| 328  * Creates a new user-defined filter group and adds the given filter to it. | 468  * Creates a new user-defined filter group and adds the given filter to it. | 
| 329  * This group will act as the default group for this filter type. | 469  * This group will act as the default group for this filter type. | 
| 330  * @param {Filter} filter | 470  * @param {Filter} filter | 
| 331  * @return {SpecialSubscription} | 471  * @return {SpecialSubscription} | 
| 332  */ | 472  */ | 
| 333 SpecialSubscription.createForFilter = function(filter) | 473 SpecialSubscription.createForFilter = function(filter) | 
| 334 { | 474 { | 
| 335   let subscription = SpecialSubscription.create(); | 475   let subscription = SpecialSubscription.create(); | 
| 336   subscription.filters.push(filter); | 476   subscription.addFilter(filter); | 
| 337   for (let [type, class_] of SpecialSubscription.defaultsMap) | 477   for (let [type, class_] of SpecialSubscription.defaultsMap) | 
| 338   { | 478   { | 
| 339     if (filter instanceof class_) | 479     if (filter instanceof class_) | 
| 340       subscription.defaults = [type]; | 480       subscription.defaults = [type]; | 
| 341   } | 481   } | 
| 342   if (!subscription.defaults) | 482   if (!subscription.defaults) | 
| 343     subscription.defaults = ["blocking"]; | 483     subscription.defaults = ["blocking"]; | 
| 344   return subscription; | 484   return subscription; | 
| 345 }; | 485 }; | 
| 346 | 486 | 
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 582     if (errors) | 722     if (errors) | 
| 583       yield "errors=" + errors; | 723       yield "errors=" + errors; | 
| 584     if (version) | 724     if (version) | 
| 585       yield "version=" + version; | 725       yield "version=" + version; | 
| 586     if (requiredVersion) | 726     if (requiredVersion) | 
| 587       yield "requiredVersion=" + requiredVersion; | 727       yield "requiredVersion=" + requiredVersion; | 
| 588     if (downloadCount) | 728     if (downloadCount) | 
| 589       yield "downloadCount=" + downloadCount; | 729       yield "downloadCount=" + downloadCount; | 
| 590   } | 730   } | 
| 591 }); | 731 }); | 
| OLD | NEW | 
|---|