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

Side by Side Diff: lib/filterStorage.js

Issue 29375915: Issue 4878 - Start using ESLint for adblockpluscore (Closed)
Patch Set: Disable no-console for the tests Created Feb. 21, 2017, 11:25 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-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 "use strict";
19
18 /** 20 /**
19 * @fileOverview FilterStorage class responsible for managing user's subscriptio ns and filters. 21 * @fileOverview FilterStorage class responsible for managing user's
22 * subscriptions and filters.
20 */ 23 */
21 24
22 Cu.import("resource://gre/modules/Services.jsm"); 25 Cu.import("resource://gre/modules/Services.jsm");
23 Cu.import("resource://gre/modules/FileUtils.jsm"); 26 Cu.import("resource://gre/modules/FileUtils.jsm");
24 Cu.import("resource://gre/modules/XPCOMUtils.jsm"); 27 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
25 28
26 let {IO} = require("io"); 29 const {IO} = require("io");
27 let {Prefs} = require("prefs"); 30 const {Prefs} = require("prefs");
28 let {Filter, ActiveFilter} = require("filterClasses"); 31 const {Filter, ActiveFilter} = require("filterClasses");
29 let {Subscription, SpecialSubscription, ExternalSubscription} = require("subscri ptionClasses"); 32 const {Subscription, SpecialSubscription,
30 let {FilterNotifier} = require("filterNotifier"); 33 ExternalSubscription} = require("subscriptionClasses");
31 let {Utils} = require("utils"); 34 const {FilterNotifier} = require("filterNotifier");
35 const {Utils} = require("utils");
32 36
33 /** 37 /**
34 * Version number of the filter storage file format. 38 * Version number of the filter storage file format.
35 * @type Integer 39 * @type {number}
36 */ 40 */
37 let formatVersion = 4; 41 let formatVersion = 4;
38 42
39 /** 43 /**
40 * This class reads user's filters from disk, manages them in memory and writes them back. 44 * This class reads user's filters from disk, manages them in memory
45 * and writes them back.
41 * @class 46 * @class
42 */ 47 */
43 let FilterStorage = exports.FilterStorage = 48 let FilterStorage = exports.FilterStorage =
44 { 49 {
45 /** 50 /**
46 * Version number of the patterns.ini format used. 51 * Version number of the patterns.ini format used.
47 * @type Integer 52 * @type {number}
48 */ 53 */
49 get formatVersion() 54 get formatVersion()
50 { 55 {
51 return formatVersion; 56 return formatVersion;
52 }, 57 },
53 58
54 /** 59 /**
55 * File that the filter list has been loaded from and should be saved to 60 * File that the filter list has been loaded from and should be saved to
56 * @type nsIFile 61 * @type {nsIFile}
57 */ 62 */
58 get sourceFile() 63 get sourceFile()
59 { 64 {
60 let file = null; 65 let file = null;
61 if (Prefs.patternsfile) 66 if (Prefs.patternsfile)
62 { 67 {
63 // Override in place, use it instead of placing the file in the regular da ta dir 68 // Override in place, use it instead of placing the file in the
69 // regular data dir
64 file = IO.resolveFilePath(Prefs.patternsfile); 70 file = IO.resolveFilePath(Prefs.patternsfile);
65 } 71 }
66 if (!file) 72 if (!file)
67 { 73 {
68 // Place the file in the data dir 74 // Place the file in the data dir
69 file = IO.resolveFilePath(Prefs.data_directory); 75 file = IO.resolveFilePath(Prefs.data_directory);
70 if (file) 76 if (file)
71 file.append("patterns.ini"); 77 file.append("patterns.ini");
72 } 78 }
73 if (!file) 79 if (!file)
74 { 80 {
75 // Data directory pref misconfigured? Try the default value 81 // Data directory pref misconfigured? Try the default value
76 try 82 try
77 { 83 {
78 file = IO.resolveFilePath(Services.prefs.getDefaultBranch("extensions.ad blockplus.").getCharPref("data_directory")); 84 file = IO.resolveFilePath(
85 Services.prefs.getDefaultBranch("extensions.adblockplus."
86 ).getCharPref("data_directory"));
79 if (file) 87 if (file)
80 file.append("patterns.ini"); 88 file.append("patterns.ini");
81 } catch(e) {} 89 }
90 catch (e) {}
82 } 91 }
83 92
84 if (!file) 93 if (!file)
85 Cu.reportError("Adblock Plus: Failed to resolve filter file location from extensions.adblockplus.patternsfile preference"); 94 {
95 Cu.reportError("Adblock Plus: Failed to resolve filter file location " +
96 "from extensions.adblockplus.patternsfile preference");
97 }
86 98
87 // Property is configurable because of the test suite. 99 // Property is configurable because of the test suite.
88 Object.defineProperty(this, "sourceFile", {value: file, configurable: true}) ; 100 Object.defineProperty(this, "sourceFile",
101 {value: file, configurable: true});
89 return file; 102 return file;
90 }, 103 },
91 104
92 /** 105 /**
93 * Will be set to true if no patterns.ini file exists. 106 * Will be set to true if no patterns.ini file exists.
94 * @type Boolean 107 * @type {boolean}
95 */ 108 */
96 firstRun: false, 109 firstRun: false,
97 110
98 /** 111 /**
99 * Map of properties listed in the filter storage file before the sections 112 * Map of properties listed in the filter storage file before the sections
100 * start. Right now this should be only the format version. 113 * start. Right now this should be only the format version.
101 */ 114 */
102 fileProperties: Object.create(null), 115 fileProperties: Object.create(null),
103 116
104 /** 117 /**
105 * List of filter subscriptions containing all filters 118 * List of filter subscriptions containing all filters
106 * @type Subscription[] 119 * @type {Subscription[]}
107 */ 120 */
108 subscriptions: [], 121 subscriptions: [],
109 122
110 /** 123 /**
111 * Map of subscriptions already on the list, by their URL/identifier 124 * Map of subscriptions already on the list, by their URL/identifier
112 * @type Object 125 * @type {Object}
113 */ 126 */
114 knownSubscriptions: Object.create(null), 127 knownSubscriptions: Object.create(null),
115 128
116 /** 129 /**
117 * Finds the filter group that a filter should be added to by default. Will 130 * Finds the filter group that a filter should be added to by default. Will
118 * return null if this group doesn't exist yet. 131 * return null if this group doesn't exist yet.
132 * @param {Filter} filter
133 * @return {SpecialSubscription|null}
119 */ 134 */
120 getGroupForFilter: function(/**Filter*/ filter) /**SpecialSubscription*/ 135 getGroupForFilter(filter)
121 { 136 {
122 let generalSubscription = null; 137 let generalSubscription = null;
123 for (let subscription of FilterStorage.subscriptions) 138 for (let subscription of FilterStorage.subscriptions)
124 { 139 {
125 if (subscription instanceof SpecialSubscription && !subscription.disabled) 140 if (subscription instanceof SpecialSubscription && !subscription.disabled)
126 { 141 {
127 // Always prefer specialized subscriptions 142 // Always prefer specialized subscriptions
128 if (subscription.isDefaultFor(filter)) 143 if (subscription.isDefaultFor(filter))
129 return subscription; 144 return subscription;
130 145
131 // If this is a general subscription - store it as fallback 146 // If this is a general subscription - store it as fallback
132 if (!generalSubscription && (!subscription.defaults || !subscription.def aults.length)) 147 if (!generalSubscription &&
148 (!subscription.defaults || !subscription.defaults.length))
133 generalSubscription = subscription; 149 generalSubscription = subscription;
134 } 150 }
135 } 151 }
136 return generalSubscription; 152 return generalSubscription;
137 }, 153 },
138 154
139 /** 155 /**
140 * Adds a filter subscription to the list 156 * Adds a filter subscription to the list
141 * @param {Subscription} subscription filter subscription to be added 157 * @param {Subscription} subscription filter subscription to be added
142 * @param {Boolean} silent if true, no listeners will be triggered (to be use d when filter list is reloaded) 158 * @param {boolean} silent if true, no listeners will be triggered
159 * (to be used when filter list is reloaded)
143 */ 160 */
144 addSubscription: function(subscription, silent) 161 addSubscription(subscription, silent)
145 { 162 {
146 if (subscription.url in FilterStorage.knownSubscriptions) 163 if (subscription.url in FilterStorage.knownSubscriptions)
147 return; 164 return;
148 165
149 FilterStorage.subscriptions.push(subscription); 166 FilterStorage.subscriptions.push(subscription);
150 FilterStorage.knownSubscriptions[subscription.url] = subscription; 167 FilterStorage.knownSubscriptions[subscription.url] = subscription;
151 addSubscriptionFilters(subscription); 168 addSubscriptionFilters(subscription);
152 169
153 if (!silent) 170 if (!silent)
154 FilterNotifier.triggerListeners("subscription.added", subscription); 171 FilterNotifier.triggerListeners("subscription.added", subscription);
155 }, 172 },
156 173
157 /** 174 /**
158 * Removes a filter subscription from the list 175 * Removes a filter subscription from the list
159 * @param {Subscription} subscription filter subscription to be removed 176 * @param {Subscription} subscription filter subscription to be removed
160 * @param {Boolean} silent if true, no listeners will be triggered (to be use d when filter list is reloaded) 177 * @param {boolean} silent if true, no listeners will be triggered
178 * (to be used when filter list is reloaded)
161 */ 179 */
162 removeSubscription: function(subscription, silent) 180 removeSubscription(subscription, silent)
163 { 181 {
164 for (let i = 0; i < FilterStorage.subscriptions.length; i++) 182 for (let i = 0; i < FilterStorage.subscriptions.length; i++)
165 { 183 {
166 if (FilterStorage.subscriptions[i].url == subscription.url) 184 if (FilterStorage.subscriptions[i].url == subscription.url)
167 { 185 {
168 removeSubscriptionFilters(subscription); 186 removeSubscriptionFilters(subscription);
169 187
170 FilterStorage.subscriptions.splice(i--, 1); 188 FilterStorage.subscriptions.splice(i--, 1);
171 delete FilterStorage.knownSubscriptions[subscription.url]; 189 delete FilterStorage.knownSubscriptions[subscription.url];
172 if (!silent) 190 if (!silent)
173 FilterNotifier.triggerListeners("subscription.removed", subscription); 191 FilterNotifier.triggerListeners("subscription.removed", subscription);
174 return; 192 return;
175 } 193 }
176 } 194 }
177 }, 195 },
178 196
179 /** 197 /**
180 * Moves a subscription in the list to a new position. 198 * Moves a subscription in the list to a new position.
181 * @param {Subscription} subscription filter subscription to be moved 199 * @param {Subscription} subscription filter subscription to be moved
182 * @param {Subscription} [insertBefore] filter subscription to insert before 200 * @param {Subscription} [insertBefore] filter subscription to insert before
183 * (if omitted the subscription will be put at the end of the list) 201 * (if omitted the subscription will be put at the end of the list)
184 */ 202 */
185 moveSubscription: function(subscription, insertBefore) 203 moveSubscription(subscription, insertBefore)
186 { 204 {
187 let currentPos = FilterStorage.subscriptions.indexOf(subscription); 205 let currentPos = FilterStorage.subscriptions.indexOf(subscription);
188 if (currentPos < 0) 206 if (currentPos < 0)
189 return; 207 return;
190 208
191 let newPos = insertBefore ? FilterStorage.subscriptions.indexOf(insertBefore ) : -1; 209 let newPos = -1;
210 if (insertBefore)
211 newPos = FilterStorage.subscriptions.indexOf(insertBefore);
212
192 if (newPos < 0) 213 if (newPos < 0)
193 newPos = FilterStorage.subscriptions.length; 214 newPos = FilterStorage.subscriptions.length;
194 215
195 if (currentPos < newPos) 216 if (currentPos < newPos)
196 newPos--; 217 newPos--;
197 if (currentPos == newPos) 218 if (currentPos == newPos)
198 return; 219 return;
199 220
200 FilterStorage.subscriptions.splice(currentPos, 1); 221 FilterStorage.subscriptions.splice(currentPos, 1);
201 FilterStorage.subscriptions.splice(newPos, 0, subscription); 222 FilterStorage.subscriptions.splice(newPos, 0, subscription);
202 FilterNotifier.triggerListeners("subscription.moved", subscription); 223 FilterNotifier.triggerListeners("subscription.moved", subscription);
203 }, 224 },
204 225
205 /** 226 /**
206 * Replaces the list of filters in a subscription by a new list 227 * Replaces the list of filters in a subscription by a new list
207 * @param {Subscription} subscription filter subscription to be updated 228 * @param {Subscription} subscription filter subscription to be updated
208 * @param {Filter[]} filters new filter list 229 * @param {Filter[]} filters new filter list
209 */ 230 */
210 updateSubscriptionFilters: function(subscription, filters) 231 updateSubscriptionFilters(subscription, filters)
211 { 232 {
212 removeSubscriptionFilters(subscription); 233 removeSubscriptionFilters(subscription);
213 subscription.oldFilters = subscription.filters; 234 subscription.oldFilters = subscription.filters;
214 subscription.filters = filters; 235 subscription.filters = filters;
215 addSubscriptionFilters(subscription); 236 addSubscriptionFilters(subscription);
216 FilterNotifier.triggerListeners("subscription.updated", subscription); 237 FilterNotifier.triggerListeners("subscription.updated", subscription);
217 delete subscription.oldFilters; 238 delete subscription.oldFilters;
218 }, 239 },
219 240
220 /** 241 /**
221 * Adds a user-defined filter to the list 242 * Adds a user-defined filter to the list
222 * @param {Filter} filter 243 * @param {Filter} filter
223 * @param {SpecialSubscription} [subscription] particular group that the filte r should be added to 244 * @param {SpecialSubscription} [subscription] particular group that the
224 * @param {Integer} [position] position within the subscription at which the f ilter should be added 245 * filter should be added to
225 * @param {Boolean} silent if true, no listeners will be triggered (to be use d when filter list is reloaded) 246 * @param {number} [position] position within the subscription at which
247 * the filter should be added
248 * @param {boolean} silent if true, no listeners will be triggered (to
249 * be used when filter list is reloaded)
226 */ 250 */
227 addFilter: function(filter, subscription, position, silent) 251 addFilter(filter, subscription, position, silent)
228 { 252 {
229 if (!subscription) 253 if (!subscription)
230 { 254 {
231 if (filter.subscriptions.some(s => s instanceof SpecialSubscription && !s. disabled)) 255 if (filter.subscriptions.some(s => s instanceof SpecialSubscription &&
256 !s.disabled))
232 return; // No need to add 257 return; // No need to add
233 subscription = FilterStorage.getGroupForFilter(filter); 258 subscription = FilterStorage.getGroupForFilter(filter);
234 } 259 }
235 if (!subscription) 260 if (!subscription)
236 { 261 {
237 // No group for this filter exists, create one 262 // No group for this filter exists, create one
238 subscription = SpecialSubscription.createForFilter(filter); 263 subscription = SpecialSubscription.createForFilter(filter);
239 this.addSubscription(subscription); 264 this.addSubscription(subscription);
240 return; 265 return;
241 } 266 }
242 267
243 if (typeof position == "undefined") 268 if (typeof position == "undefined")
244 position = subscription.filters.length; 269 position = subscription.filters.length;
245 270
246 if (filter.subscriptions.indexOf(subscription) < 0) 271 if (filter.subscriptions.indexOf(subscription) < 0)
247 filter.subscriptions.push(subscription); 272 filter.subscriptions.push(subscription);
248 subscription.filters.splice(position, 0, filter); 273 subscription.filters.splice(position, 0, filter);
249 if (!silent) 274 if (!silent)
250 FilterNotifier.triggerListeners("filter.added", filter, subscription, posi tion); 275 {
276 FilterNotifier.triggerListeners("filter.added", filter, subscription,
277 position);
278 }
251 }, 279 },
252 280
253 /** 281 /**
254 * Removes a user-defined filter from the list 282 * Removes a user-defined filter from the list
255 * @param {Filter} filter 283 * @param {Filter} filter
256 * @param {SpecialSubscription} [subscription] a particular filter group that 284 * @param {SpecialSubscription} [subscription] a particular filter group that
257 * the filter should be removed from (if ommited will be removed from all subscriptions) 285 * the filter should be removed from (if ommited will be removed from all
258 * @param {Integer} [position] position inside the filter group at which the 286 * subscriptions)
287 * @param {number} [position] position inside the filter group at which the
259 * filter should be removed (if ommited all instances will be removed) 288 * filter should be removed (if ommited all instances will be removed)
260 */ 289 */
261 removeFilter: function(filter, subscription, position) 290 removeFilter(filter, subscription, position)
262 { 291 {
263 let subscriptions = (subscription ? [subscription] : filter.subscriptions.sl ice()); 292 let subscriptions = (
293 subscription ? [subscription] : filter.subscriptions.slice()
294 );
264 for (let i = 0; i < subscriptions.length; i++) 295 for (let i = 0; i < subscriptions.length; i++)
265 { 296 {
266 let subscription = subscriptions[i]; 297 let currentSubscription = subscriptions[i];
267 if (subscription instanceof SpecialSubscription) 298 if (currentSubscription instanceof SpecialSubscription)
268 { 299 {
269 let positions = []; 300 let positions = [];
270 if (typeof position == "undefined") 301 if (typeof position == "undefined")
271 { 302 {
272 let index = -1; 303 let index = -1;
273 do 304 do
274 { 305 {
275 index = subscription.filters.indexOf(filter, index + 1); 306 index = currentSubscription.filters.indexOf(filter, index + 1);
276 if (index >= 0) 307 if (index >= 0)
277 positions.push(index); 308 positions.push(index);
278 } while (index >= 0); 309 } while (index >= 0);
279 } 310 }
280 else 311 else
281 positions.push(position); 312 positions.push(position);
282 313
283 for (let j = positions.length - 1; j >= 0; j--) 314 for (let j = positions.length - 1; j >= 0; j--)
284 { 315 {
285 let position = positions[j]; 316 let currentPosition = positions[j];
286 if (subscription.filters[position] == filter) 317 if (currentSubscription.filters[currentPosition] == filter)
287 { 318 {
288 subscription.filters.splice(position, 1); 319 currentSubscription.filters.splice(currentPosition, 1);
289 if (subscription.filters.indexOf(filter) < 0) 320 if (currentSubscription.filters.indexOf(filter) < 0)
290 { 321 {
291 let index = filter.subscriptions.indexOf(subscription); 322 let index = filter.subscriptions.indexOf(currentSubscription);
292 if (index >= 0) 323 if (index >= 0)
293 filter.subscriptions.splice(index, 1); 324 filter.subscriptions.splice(index, 1);
294 } 325 }
295 FilterNotifier.triggerListeners("filter.removed", filter, subscripti on, position); 326 FilterNotifier.triggerListeners(
327 "filter.removed", filter, currentSubscription, currentPosition
328 );
296 } 329 }
297 } 330 }
298 } 331 }
299 } 332 }
300 }, 333 },
301 334
302 /** 335 /**
303 * Moves a user-defined filter to a new position 336 * Moves a user-defined filter to a new position
304 * @param {Filter} filter 337 * @param {Filter} filter
305 * @param {SpecialSubscription} subscription filter group where the filter is located 338 * @param {SpecialSubscription} subscription filter group where the filter is
306 * @param {Integer} oldPosition current position of the filter 339 * located
307 * @param {Integer} newPosition new position of the filter 340 * @param {number} oldPosition current position of the filter
341 * @param {number} newPosition new position of the filter
308 */ 342 */
309 moveFilter: function(filter, subscription, oldPosition, newPosition) 343 moveFilter(filter, subscription, oldPosition, newPosition)
310 { 344 {
311 if (!(subscription instanceof SpecialSubscription) || subscription.filters[o ldPosition] != filter) 345 if (!(subscription instanceof SpecialSubscription) ||
346 subscription.filters[oldPosition] != filter)
312 return; 347 return;
313 348
314 newPosition = Math.min(Math.max(newPosition, 0), subscription.filters.length - 1); 349 newPosition = Math.min(Math.max(newPosition, 0),
350 subscription.filters.length - 1);
315 if (oldPosition == newPosition) 351 if (oldPosition == newPosition)
316 return; 352 return;
317 353
318 subscription.filters.splice(oldPosition, 1); 354 subscription.filters.splice(oldPosition, 1);
319 subscription.filters.splice(newPosition, 0, filter); 355 subscription.filters.splice(newPosition, 0, filter);
320 FilterNotifier.triggerListeners("filter.moved", filter, subscription, oldPos ition, newPosition); 356 FilterNotifier.triggerListeners("filter.moved", filter, subscription,
357 oldPosition, newPosition);
321 }, 358 },
322 359
323 /** 360 /**
324 * Increases the hit count for a filter by one 361 * Increases the hit count for a filter by one
325 * @param {Filter} filter 362 * @param {Filter} filter
326 */ 363 */
327 increaseHitCount: function(filter) 364 increaseHitCount(filter)
328 { 365 {
329 if (!Prefs.savestats || !(filter instanceof ActiveFilter)) 366 if (!Prefs.savestats || !(filter instanceof ActiveFilter))
330 return; 367 return;
331 368
332 filter.hitCount++; 369 filter.hitCount++;
333 filter.lastHit = Date.now(); 370 filter.lastHit = Date.now();
334 }, 371 },
335 372
336 /** 373 /**
337 * Resets hit count for some filters 374 * Resets hit count for some filters
338 * @param {Filter[]} filters filters to be reset, if null all filters will be reset 375 * @param {Filter[]} filters filters to be reset, if null all filters will
376 * be reset
339 */ 377 */
340 resetHitCounts: function(filters) 378 resetHitCounts(filters)
341 { 379 {
342 if (!filters) 380 if (!filters)
343 { 381 {
344 filters = []; 382 filters = [];
345 for (let text in Filter.knownFilters) 383 for (let text in Filter.knownFilters)
346 filters.push(Filter.knownFilters[text]); 384 filters.push(Filter.knownFilters[text]);
347 } 385 }
348 for (let filter of filters) 386 for (let filter of filters)
349 { 387 {
350 filter.hitCount = 0; 388 filter.hitCount = 0;
351 filter.lastHit = 0; 389 filter.lastHit = 0;
352 } 390 }
353 }, 391 },
354 392
355 _loading: false, 393 _loading: false,
356 394
357 /** 395 /**
358 * Loads all subscriptions from the disk 396 * Loads all subscriptions from the disk
359 * @param {nsIFile} [sourceFile] File to read from 397 * @param {nsIFile} [sourceFile] File to read from
360 */ 398 */
361 loadFromDisk: function(sourceFile) 399 loadFromDisk(sourceFile)
362 { 400 {
363 if (this._loading) 401 if (this._loading)
364 return; 402 return;
365 403
366 this._loading = true; 404 this._loading = true;
367 405
368 let readFile = function(sourceFile, backupIndex) 406 let readFile = function(currentSourceFile, backupIndex)
369 { 407 {
370 let parser = new INIParser(); 408 let parser = new INIParser();
371 IO.readFromFile(sourceFile, parser, function(e) 409 IO.readFromFile(currentSourceFile, parser, readFromFileException =>
372 { 410 {
373 if (!e && parser.subscriptions.length == 0) 411 if (!readFromFileException && parser.subscriptions.length == 0)
374 { 412 {
375 // No filter subscriptions in the file, this isn't right. 413 // No filter subscriptions in the file, this isn't right.
376 e = new Error("No data in the file"); 414 readFromFileException = new Error("No data in the file");
377 } 415 }
378 416
379 if (e) 417 if (readFromFileException)
380 Cu.reportError(e); 418 Cu.reportError(readFromFileException);
381 419
382 if (e && !explicitFile) 420 if (readFromFileException && !explicitFile)
383 { 421 {
384 // Attempt to load a backup 422 // Attempt to load a backup
385 sourceFile = this.sourceFile; 423 currentSourceFile = this.sourcefile;
386 if (sourceFile) 424 if (currentSourceFile)
387 { 425 {
388 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(sourceFile.leafName) || [null, sourceFile.leafName, ""]; 426 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(
427 currentSourceFile.leafName
428 ) || [null, currentSourceFile.leafName, ""];
389 429
390 sourceFile = sourceFile.clone(); 430 currentSourceFile = currentSourceFile.clone();
391 sourceFile.leafName = part1 + "-backup" + (++backupIndex) + part2; 431 currentSourceFile.leafName = (
432 part1 + "-backup" + (++backupIndex) + part2
433 );
392 434
393 IO.statFile(sourceFile, function(e, statData) 435 IO.statFile(currentSourceFile, (statFileException, statData) =>
394 { 436 {
395 if (!e && statData.exists) 437 if (!statFileException && statData.exists)
396 readFile(sourceFile, backupIndex); 438 readFile(currentSourceFile, backupIndex);
397 else 439 else
398 doneReading(parser); 440 doneReading(parser);
399 }); 441 });
400 return; 442 return;
401 } 443 }
402 } 444 }
403 doneReading(parser); 445 doneReading(parser);
404 }.bind(this)); 446 });
405 }.bind(this); 447 }.bind(this);
406 448
407 var doneReading = function(parser) 449 let doneReading = function(parser)
408 { 450 {
409 // Old special groups might have been converted, remove them if they are e mpty 451 // Old special groups might have been converted, remove them if
452 // they are empty
410 let specialMap = {"~il~": true, "~wl~": true, "~fl~": true, "~eh~": true}; 453 let specialMap = {"~il~": true, "~wl~": true, "~fl~": true, "~eh~": true};
411 let knownSubscriptions = Object.create(null); 454 let knownSubscriptions = Object.create(null);
412 for (let i = 0; i < parser.subscriptions.length; i++) 455 for (let i = 0; i < parser.subscriptions.length; i++)
413 { 456 {
414 let subscription = parser.subscriptions[i]; 457 let subscription = parser.subscriptions[i];
415 if (subscription instanceof SpecialSubscription && subscription.filters. length == 0 && subscription.url in specialMap) 458 if (subscription instanceof SpecialSubscription &&
459 subscription.filters.length == 0 && subscription.url in specialMap)
416 parser.subscriptions.splice(i--, 1); 460 parser.subscriptions.splice(i--, 1);
417 else 461 else
418 knownSubscriptions[subscription.url] = subscription; 462 knownSubscriptions[subscription.url] = subscription;
419 } 463 }
420 464
421 this.fileProperties = parser.fileProperties; 465 this.fileProperties = parser.fileProperties;
422 this.subscriptions = parser.subscriptions; 466 this.subscriptions = parser.subscriptions;
423 this.knownSubscriptions = knownSubscriptions; 467 this.knownSubscriptions = knownSubscriptions;
424 Filter.knownFilters = parser.knownFilters; 468 Filter.knownFilters = parser.knownFilters;
425 Subscription.knownSubscriptions = parser.knownSubscriptions; 469 Subscription.knownSubscriptions = parser.knownSubscriptions;
426 470
427 if (parser.userFilters) 471 if (parser.userFilters)
428 { 472 {
429 for (let i = 0; i < parser.userFilters.length; i++) 473 for (let i = 0; i < parser.userFilters.length; i++)
430 { 474 {
431 let filter = Filter.fromText(parser.userFilters[i]); 475 let filter = Filter.fromText(parser.userFilters[i]);
432 this.addFilter(filter, null, undefined, true); 476 this.addFilter(filter, null, undefined, true);
433 } 477 }
434 } 478 }
435 479
436 this._loading = false; 480 this._loading = false;
437 FilterNotifier.triggerListeners("load"); 481 FilterNotifier.triggerListeners("load");
438 482
439 if (sourceFile != this.sourceFile) 483 if (sourceFile != this.sourceFile)
440 this.saveToDisk(); 484 this.saveToDisk();
441
442 }.bind(this); 485 }.bind(this);
443 486
444 let explicitFile; 487 let explicitFile;
445 if (sourceFile) 488 if (sourceFile)
446 { 489 {
447 explicitFile = true; 490 explicitFile = true;
448 readFile(sourceFile, 0); 491 readFile(sourceFile, 0);
449 } 492 }
450 else 493 else
451 { 494 {
452 explicitFile = false; 495 explicitFile = false;
453 sourceFile = FilterStorage.sourceFile; 496 ({sourceFile} = FilterStorage);
454 497
455 let callback = function(e, statData) 498 let callback = function(e, statData)
456 { 499 {
457 if (e || !statData.exists) 500 if (e || !statData.exists)
458 { 501 {
459 this.firstRun = true; 502 this.firstRun = true;
460 this._loading = false; 503 this._loading = false;
461 FilterNotifier.triggerListeners("load"); 504 FilterNotifier.triggerListeners("load");
462 } 505 }
463 else 506 else
464 readFile(sourceFile, 0); 507 readFile(sourceFile, 0);
465 }.bind(this); 508 }.bind(this);
466 509
467 if (sourceFile) 510 if (sourceFile)
468 IO.statFile(sourceFile, callback); 511 IO.statFile(sourceFile, callback);
469 else 512 else
470 callback(true); 513 callback(true);
471 } 514 }
472 }, 515 },
473 516
474 _generateFilterData: function*(subscriptions) 517 *_generateFilterData(subscriptions)
475 { 518 {
476 yield "# Adblock Plus preferences"; 519 yield "# Adblock Plus preferences";
477 yield "version=" + formatVersion; 520 yield "version=" + formatVersion;
478 521
479 let saved = Object.create(null); 522 let saved = Object.create(null);
480 let buf = []; 523 let buf = [];
481 524
482 // Save filter data 525 // Save filter data
483 for (let i = 0; i < subscriptions.length; i++) 526 for (let i = 0; i < subscriptions.length; i++)
484 { 527 {
(...skipping 15 matching lines...) Expand all
500 // Save subscriptions 543 // Save subscriptions
501 for (let i = 0; i < subscriptions.length; i++) 544 for (let i = 0; i < subscriptions.length; i++)
502 { 545 {
503 let subscription = subscriptions[i]; 546 let subscription = subscriptions[i];
504 547
505 yield ""; 548 yield "";
506 549
507 subscription.serialize(buf); 550 subscription.serialize(buf);
508 if (subscription.filters.length) 551 if (subscription.filters.length)
509 { 552 {
510 buf.push("", "[Subscription filters]") 553 buf.push("", "[Subscription filters]");
511 subscription.serializeFilters(buf); 554 subscription.serializeFilters(buf);
512 } 555 }
513 for (let k = 0; k < buf.length; k++) 556 for (let k = 0; k < buf.length; k++)
514 yield buf[k]; 557 yield buf[k];
515 buf.splice(0); 558 buf.splice(0);
516 } 559 }
517 }, 560 },
518 561
519 /** 562 /**
520 * Will be set to true if saveToDisk() is running (reentrance protection). 563 * Will be set to true if saveToDisk() is running (reentrance protection).
521 * @type Boolean 564 * @type {boolean}
522 */ 565 */
523 _saving: false, 566 _saving: false,
524 567
525 /** 568 /**
526 * Will be set to true if a saveToDisk() call arrives while saveToDisk() is 569 * Will be set to true if a saveToDisk() call arrives while saveToDisk() is
527 * already running (delayed execution). 570 * already running (delayed execution).
528 * @type Boolean 571 * @type {boolean}
529 */ 572 */
530 _needsSave: false, 573 _needsSave: false,
531 574
532 /** 575 /**
533 * Saves all subscriptions back to disk 576 * Saves all subscriptions back to disk
534 * @param {nsIFile} [targetFile] File to be written 577 * @param {nsIFile} [targetFile] File to be written
535 */ 578 */
536 saveToDisk: function(targetFile) 579 saveToDisk(targetFile)
537 { 580 {
538 let explicitFile = true; 581 let explicitFile = true;
539 if (!targetFile) 582 if (!targetFile)
540 { 583 {
541 targetFile = FilterStorage.sourceFile; 584 targetFile = FilterStorage.sourceFile;
542 explicitFile = false; 585 explicitFile = false;
543 } 586 }
544 if (!targetFile) 587 if (!targetFile)
545 return; 588 return;
546 589
547 if (!explicitFile && this._saving) 590 if (!explicitFile && this._saving)
548 { 591 {
549 this._needsSave = true; 592 this._needsSave = true;
550 return; 593 return;
551 } 594 }
552 595
553 // Make sure the file's parent directory exists 596 // Make sure the file's parent directory exists
554 try { 597 try
555 targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE, FileUtils.PERMS_DIRECT ORY); 598 {
556 } catch (e) {} 599 targetFile.parent.create(Ci.nsIFile.DIRECTORY_TYPE,
600 FileUtils.PERMS_DIRECTORY);
601 }
602 catch (e) {}
557 603
558 let writeFilters = function() 604 let writeFilters = function()
559 { 605 {
560 IO.writeToFile(targetFile, this._generateFilterData(subscriptions), functi on(e) 606 IO.writeToFile(targetFile, this._generateFilterData(subscriptions), e =>
561 { 607 {
562 if (!explicitFile) 608 if (!explicitFile)
563 this._saving = false; 609 this._saving = false;
564 610
565 if (e) 611 if (e)
566 Cu.reportError(e); 612 Cu.reportError(e);
567 613
568 if (!explicitFile && this._needsSave) 614 if (!explicitFile && this._needsSave)
569 { 615 {
570 this._needsSave = false; 616 this._needsSave = false;
571 this.saveToDisk(); 617 this.saveToDisk();
572 } 618 }
573 else 619 else
574 FilterNotifier.triggerListeners("save"); 620 FilterNotifier.triggerListeners("save");
575 }.bind(this)); 621 });
576 }.bind(this); 622 }.bind(this);
577 623
578 let checkBackupRequired = function(callbackNotRequired, callbackRequired) 624 let checkBackupRequired = function(callbackNotRequired, callbackRequired)
579 { 625 {
580 if (explicitFile || Prefs.patternsbackups <= 0) 626 if (explicitFile || Prefs.patternsbackups <= 0)
581 callbackNotRequired(); 627 callbackNotRequired();
582 else 628 else
583 { 629 {
584 IO.statFile(targetFile, function(e, statData) 630 IO.statFile(targetFile, (statFileException, statData) =>
585 { 631 {
586 if (e || !statData.exists) 632 if (statFileException || !statData.exists)
587 callbackNotRequired(); 633 callbackNotRequired();
588 else 634 else
589 { 635 {
590 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(targetFile.leafName) || [null, targetFile.leafName, ""]; 636 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(targetFile.leafName) ||
637 [null, targetFile.leafName, ""];
591 let newestBackup = targetFile.clone(); 638 let newestBackup = targetFile.clone();
592 newestBackup.leafName = part1 + "-backup1" + part2; 639 newestBackup.leafName = part1 + "-backup1" + part2;
593 IO.statFile(newestBackup, function(e, statData) 640 IO.statFile(
594 { 641 newestBackup,
595 if (!e && (!statData.exists || (Date.now() - statData.lastModified ) / 3600000 >= Prefs.patternsbackupinterval)) 642 (statBackupFileException, statBackupData) =>
596 callbackRequired(part1, part2) 643 {
597 else 644 if (!statBackupFileException && (!statBackupData.exists ||
598 callbackNotRequired(); 645 (Date.now() - statBackupData.lastModified) /
599 }); 646 3600000 >= Prefs.patternsbackupinterval))
647 callbackRequired(part1, part2);
648 else
649 callbackNotRequired();
650 }
651 );
600 } 652 }
601 }); 653 });
602 } 654 }
603 }.bind(this); 655 };
604 656
605 let removeLastBackup = function(part1, part2) 657 let removeLastBackup = function(part1, part2)
606 { 658 {
607 let file = targetFile.clone(); 659 let file = targetFile.clone();
608 file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2; 660 file.leafName = part1 + "-backup" + Prefs.patternsbackups + part2;
609 IO.removeFile(file, (e) => renameBackup(part1, part2, Prefs.patternsbackup s - 1)); 661 IO.removeFile(
610 }.bind(this); 662 file, e => renameBackup(part1, part2, Prefs.patternsbackups - 1)
663 );
664 };
611 665
612 let renameBackup = function(part1, part2, index) 666 let renameBackup = function(part1, part2, index)
613 { 667 {
614 if (index > 0) 668 if (index > 0)
615 { 669 {
616 let fromFile = targetFile.clone(); 670 let fromFile = targetFile.clone();
617 fromFile.leafName = part1 + "-backup" + index + part2; 671 fromFile.leafName = part1 + "-backup" + index + part2;
618 672
619 let toName = part1 + "-backup" + (index + 1) + part2; 673 let toName = part1 + "-backup" + (index + 1) + part2;
620 674
621 IO.renameFile(fromFile, toName, (e) => renameBackup(part1, part2, index - 1)); 675 IO.renameFile(fromFile, toName, e => renameBackup(part1, part2,
676 index - 1));
622 } 677 }
623 else 678 else
624 { 679 {
625 let toFile = targetFile.clone(); 680 let toFile = targetFile.clone();
626 toFile.leafName = part1 + "-backup" + (index + 1) + part2; 681 toFile.leafName = part1 + "-backup" + (index + 1) + part2;
627 682
628 IO.copyFile(targetFile, toFile, writeFilters); 683 IO.copyFile(targetFile, toFile, writeFilters);
629 } 684 }
630 }.bind(this); 685 };
631 686
632 // Do not persist external subscriptions 687 // Do not persist external subscriptions
633 let subscriptions = this.subscriptions.filter((s) => !(s instanceof External Subscription)); 688 let subscriptions = this.subscriptions.filter(
689 s => !(s instanceof ExternalSubscription)
690 );
634 if (!explicitFile) 691 if (!explicitFile)
635 this._saving = true; 692 this._saving = true;
636 693
637 checkBackupRequired(writeFilters, removeLastBackup); 694 checkBackupRequired(writeFilters, removeLastBackup);
638 }, 695 },
639 696
640 /** 697 /**
641 * Returns the list of existing backup files. 698 * Returns the list of existing backup files.
699 * @return {nsIFile[]}
642 */ 700 */
643 getBackupFiles: function() /**nsIFile[]*/ 701 getBackupFiles()
644 { 702 {
645 // TODO: This method should be asynchronous
646 let result = []; 703 let result = [];
647 704
648 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(FilterStorage.sourceFile.leafNam e) || [null, FilterStorage.sourceFile.leafName, ""]; 705 let [, part1, part2] = /^(.*)(\.\w+)$/.exec(
706 FilterStorage.sourceFile.leafName
707 ) || [null, FilterStorage.sourceFile.leafName, ""];
649 for (let i = 1; ; i++) 708 for (let i = 1; ; i++)
650 { 709 {
651 let file = FilterStorage.sourceFile.clone(); 710 let file = FilterStorage.sourceFile.clone();
652 file.leafName = part1 + "-backup" + i + part2; 711 file.leafName = part1 + "-backup" + i + part2;
653 if (file.exists()) 712 if (file.exists())
654 result.push(file); 713 result.push(file);
655 else 714 else
656 break; 715 break;
657 } 716 }
658 return result; 717 return result;
659 } 718 }
660 }; 719 };
661 720
662 /** 721 /**
663 * Joins subscription's filters to the subscription without any notifications. 722 * Joins subscription's filters to the subscription without any notifications.
664 * @param {Subscription} subscription filter subscription that should be connect ed to its filters 723 * @param {Subscription} subscription filter subscription that should be
724 * connected to its filters
665 */ 725 */
666 function addSubscriptionFilters(subscription) 726 function addSubscriptionFilters(subscription)
667 { 727 {
668 if (!(subscription.url in FilterStorage.knownSubscriptions)) 728 if (!(subscription.url in FilterStorage.knownSubscriptions))
669 return; 729 return;
670 730
671 for (let filter of subscription.filters) 731 for (let filter of subscription.filters)
672 filter.subscriptions.push(subscription); 732 filter.subscriptions.push(subscription);
673 } 733 }
674 734
675 /** 735 /**
676 * Removes subscription's filters from the subscription without any notification s. 736 * Removes subscription's filters from the subscription without any
737 * notifications.
677 * @param {Subscription} subscription filter subscription to be removed 738 * @param {Subscription} subscription filter subscription to be removed
678 */ 739 */
679 function removeSubscriptionFilters(subscription) 740 function removeSubscriptionFilters(subscription)
680 { 741 {
681 if (!(subscription.url in FilterStorage.knownSubscriptions)) 742 if (!(subscription.url in FilterStorage.knownSubscriptions))
682 return; 743 return;
683 744
684 for (let filter of subscription.filters) 745 for (let filter of subscription.filters)
685 { 746 {
686 let i = filter.subscriptions.indexOf(subscription); 747 let i = filter.subscriptions.indexOf(subscription);
(...skipping 11 matching lines...) Expand all
698 this.fileProperties = this.curObj = {}; 759 this.fileProperties = this.curObj = {};
699 this.subscriptions = []; 760 this.subscriptions = [];
700 this.knownFilters = Object.create(null); 761 this.knownFilters = Object.create(null);
701 this.knownSubscriptions = Object.create(null); 762 this.knownSubscriptions = Object.create(null);
702 } 763 }
703 INIParser.prototype = 764 INIParser.prototype =
704 { 765 {
705 linesProcessed: 0, 766 linesProcessed: 0,
706 subscriptions: null, 767 subscriptions: null,
707 knownFilters: null, 768 knownFilters: null,
708 knownSubscriptions : null, 769 knownSubscriptions: null,
709 wantObj: true, 770 wantObj: true,
710 fileProperties: null, 771 fileProperties: null,
711 curObj: null, 772 curObj: null,
712 curSection: null, 773 curSection: null,
713 userFilters: null, 774 userFilters: null,
714 775
715 process: function(val) 776 process(val)
716 { 777 {
717 let origKnownFilters = Filter.knownFilters; 778 let origKnownFilters = Filter.knownFilters;
718 Filter.knownFilters = this.knownFilters; 779 Filter.knownFilters = this.knownFilters;
719 let origKnownSubscriptions = Subscription.knownSubscriptions; 780 let origKnownSubscriptions = Subscription.knownSubscriptions;
720 Subscription.knownSubscriptions = this.knownSubscriptions; 781 Subscription.knownSubscriptions = this.knownSubscriptions;
721 let match; 782 let match;
722 try 783 try
723 { 784 {
724 if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val))) 785 if (this.wantObj === true && (match = /^(\w+)=(.*)$/.exec(val)))
725 this.curObj[match[1]] = match[2]; 786 this.curObj[match[1]] = match[2];
726 else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val))) 787 else if (val === null || (match = /^\s*\[(.+)\]\s*$/.exec(val)))
727 { 788 {
728 if (this.curObj) 789 if (this.curObj)
729 { 790 {
730 // Process current object before going to next section 791 // Process current object before going to next section
731 switch (this.curSection) 792 switch (this.curSection)
732 { 793 {
733 case "filter": 794 case "filter":
734 case "pattern": 795 case "pattern":
735 if ("text" in this.curObj) 796 if ("text" in this.curObj)
736 Filter.fromObject(this.curObj); 797 Filter.fromObject(this.curObj);
737 break; 798 break;
738 case "subscription": 799 case "subscription": {
739 let subscription = Subscription.fromObject(this.curObj); 800 let subscription = Subscription.fromObject(this.curObj);
740 if (subscription) 801 if (subscription)
741 this.subscriptions.push(subscription); 802 this.subscriptions.push(subscription);
742 break; 803 break;
804 }
743 case "subscription filters": 805 case "subscription filters":
744 case "subscription patterns": 806 case "subscription patterns":
745 if (this.subscriptions.length) 807 if (this.subscriptions.length)
746 { 808 {
747 let subscription = this.subscriptions[this.subscriptions.length - 1]; 809 let subscription = this.subscriptions[
810 this.subscriptions.length - 1
811 ];
748 for (let text of this.curObj) 812 for (let text of this.curObj)
749 { 813 {
750 let filter = Filter.fromText(text); 814 let filter = Filter.fromText(text);
751 subscription.filters.push(filter); 815 subscription.filters.push(filter);
752 filter.subscriptions.push(subscription); 816 filter.subscriptions.push(subscription);
753 } 817 }
754 } 818 }
755 break; 819 break;
756 case "user patterns": 820 case "user patterns":
757 this.userFilters = this.curObj; 821 this.userFilters = this.curObj;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 Subscription.knownSubscriptions = origKnownSubscriptions; 855 Subscription.knownSubscriptions = origKnownSubscriptions;
792 } 856 }
793 857
794 // Allow events to be processed every now and then. 858 // Allow events to be processed every now and then.
795 // Note: IO.readFromFile() will deal with the potential reentrance here. 859 // Note: IO.readFromFile() will deal with the potential reentrance here.
796 this.linesProcessed++; 860 this.linesProcessed++;
797 if (this.linesProcessed % 1000 == 0) 861 if (this.linesProcessed % 1000 == 0)
798 return Utils.yield(); 862 return Utils.yield();
799 } 863 }
800 }; 864 };
OLDNEW
« .eslintrc.json ('K') | « lib/filterNotifier.js ('k') | lib/matcher.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld