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

Side by Side Diff: lib/matcher.js

Issue 5434053851348992: Issue 1282 - Let user-defined filters override filter lists (Closed)
Patch Set: Created Dec. 9, 2014, 1:12 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/filterClasses.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 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 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
209 209
210 /** 210 /**
211 * Combines a matcher for blocking and exception rules, automatically sorts 211 * Combines a matcher for blocking and exception rules, automatically sorts
212 * rules into two Matcher instances. 212 * rules into two Matcher instances.
213 * @constructor 213 * @constructor
214 */ 214 */
215 function CombinedMatcher() 215 function CombinedMatcher()
216 { 216 {
217 this.blacklist = new Matcher(); 217 this.blacklist = new Matcher();
218 this.whitelist = new Matcher(); 218 this.whitelist = new Matcher();
219 this.userBlacklist = new Matcher();
220 this.userWhitelist = new Matcher();
219 this.resultCache = Object.create(null); 221 this.resultCache = Object.create(null);
220 } 222 }
221 exports.CombinedMatcher = CombinedMatcher; 223 exports.CombinedMatcher = CombinedMatcher;
222 224
223 /** 225 /**
224 * Maximal number of matching cache entries to be kept 226 * Maximal number of matching cache entries to be kept
225 * @type Number 227 * @type Number
226 */ 228 */
227 CombinedMatcher.maxCacheEntries = 1000; 229 CombinedMatcher.maxCacheEntries = 1000;
228 230
229 CombinedMatcher.prototype = 231 CombinedMatcher.prototype =
230 { 232 {
231 /** 233 /**
232 * Matcher for blocking rules. 234 * Matcher for blocking rules.
233 * @type Matcher 235 * @type Matcher
234 */ 236 */
235 blacklist: null, 237 blacklist: null,
236 238
237 /** 239 /**
238 * Matcher for exception rules. 240 * Matcher for exception rules.
239 * @type Matcher 241 * @type Matcher
240 */ 242 */
241 whitelist: null, 243 whitelist: null,
242 244
243 /** 245 /**
246 * Matcher for user-defined blocking rules.
247 * @type Matcher
248 */
249 userBlacklist: null,
250
251 /**
252 * Matcher for user-defined exception rules.
253 * @type Matcher
254 */
255 userWhitelist: null,
256
257 /**
244 * Lookup table of previous matchesAny results 258 * Lookup table of previous matchesAny results
245 * @type Object 259 * @type Object
246 */ 260 */
247 resultCache: null, 261 resultCache: null,
248 262
249 /** 263 /**
250 * Number of entries in resultCache 264 * Number of entries in resultCache
251 * @type Number 265 * @type Number
252 */ 266 */
253 cacheEntries: 0, 267 cacheEntries: 0,
254 268
269 _getMatcher: function(filter)
270 {
271 if (filter.isUserDefined)
272 {
273 if (filter instanceof WhitelistFilter)
274 return this.userWhitelist;
275 else
276 return this.userBlacklist;
277 }
278 else
279 {
280 if (filter instanceof WhitelistFilter)
281 return this.whitelist;
282 else
283 return this.blacklist;
284 }
285 },
286
255 /** 287 /**
256 * @see Matcher#clear 288 * @see Matcher#clear
257 */ 289 */
258 clear: function() 290 clear: function()
259 { 291 {
260 this.blacklist.clear(); 292 this.blacklist.clear();
261 this.whitelist.clear(); 293 this.whitelist.clear();
294 this.userBlacklist.clear();
295 this.userWhitelist.clear();
262 this.resultCache = Object.create(null); 296 this.resultCache = Object.create(null);
263 this.cacheEntries = 0; 297 this.cacheEntries = 0;
264 }, 298 },
265 299
266 /** 300 /**
267 * @see Matcher#add 301 * @see Matcher#add
268 */ 302 */
269 add: function(filter) 303 add: function(filter)
270 { 304 {
271 if (filter instanceof WhitelistFilter) 305 this._getMatcher(filter).add(filter);
272 this.whitelist.add(filter);
273 else
274 this.blacklist.add(filter);
275 306
276 if (this.cacheEntries > 0) 307 if (this.cacheEntries > 0)
277 { 308 {
278 this.resultCache = Object.create(null); 309 this.resultCache = Object.create(null);
279 this.cacheEntries = 0; 310 this.cacheEntries = 0;
280 } 311 }
281 }, 312 },
282 313
283 /** 314 /**
284 * @see Matcher#remove 315 * @see Matcher#remove
285 */ 316 */
286 remove: function(filter) 317 remove: function(filter)
287 { 318 {
288 if (filter instanceof WhitelistFilter) 319 this._getMatcher(filter).remove(filter);
289 this.whitelist.remove(filter);
290 else
291 this.blacklist.remove(filter);
292 320
293 if (this.cacheEntries > 0) 321 if (this.cacheEntries > 0)
294 { 322 {
295 this.resultCache = Object.create(null); 323 this.resultCache = Object.create(null);
296 this.cacheEntries = 0; 324 this.cacheEntries = 0;
297 } 325 }
298 }, 326 },
299 327
300 /** 328 /**
301 * @see Matcher#findKeyword 329 * @see Matcher#findKeyword
302 */ 330 */
303 findKeyword: function(filter) 331 findKeyword: function(filter)
304 { 332 {
305 if (filter instanceof WhitelistFilter) 333 return this._getMatcher(filter).findKeyword(filter);
306 return this.whitelist.findKeyword(filter);
307 else
308 return this.blacklist.findKeyword(filter);
309 }, 334 },
310 335
311 /** 336 /**
312 * @see Matcher#hasFilter 337 * @see Matcher#hasFilter
313 */ 338 */
314 hasFilter: function(filter) 339 hasFilter: function(filter)
315 { 340 {
316 if (filter instanceof WhitelistFilter) 341 return this._getMatcher(filter).hasFilter(filter);
317 return this.whitelist.hasFilter(filter);
318 else
319 return this.blacklist.hasFilter(filter);
320 }, 342 },
321 343
322 /** 344 /**
323 * @see Matcher#getKeywordForFilter 345 * @see Matcher#getKeywordForFilter
324 */ 346 */
325 getKeywordForFilter: function(filter) 347 getKeywordForFilter: function(filter)
326 { 348 {
327 if (filter instanceof WhitelistFilter) 349 return this._getMatcher(filter).getKeywordForFilter(filter);
328 return this.whitelist.getKeywordForFilter(filter);
329 else
330 return this.blacklist.getKeywordForFilter(filter);
331 }, 350 },
332 351
333 /** 352 /**
334 * Checks whether a particular filter is slow 353 * Checks whether a particular filter is slow
335 */ 354 */
336 isSlowFilter: function(/**RegExpFilter*/ filter) /**Boolean*/ 355 isSlowFilter: function(/**RegExpFilter*/ filter) /**Boolean*/
337 { 356 {
338 let matcher = (filter instanceof WhitelistFilter ? this.whitelist : this.bla cklist); 357 let matcher = this._getMatcher(filter);
339 if (matcher.hasFilter(filter)) 358 if (matcher.hasFilter(filter))
340 return !matcher.getKeywordForFilter(filter); 359 return !matcher.getKeywordForFilter(filter);
341 else 360 else
342 return !matcher.findKeyword(filter); 361 return !matcher.findKeyword(filter);
343 }, 362 },
344 363
345 /** 364 /**
346 * Optimized filter matching testing both whitelist and blacklist matchers 365 * Optimized filter matching testing both whitelist and blacklist matchers
347 * simultaneously. For parameters see Matcher.matchesAny(). 366 * simultaneously.
348 * @see Matcher#matchesAny 367 * @see Matcher#matchesAny
349 */ 368 */
350 matchesAnyInternal: function(location, contentType, docDomain, thirdParty, sit ekey) 369 matchesAnyInternal: function(blacklist, whitelist, candidates, location, conte ntType, docDomain, thirdParty, sitekey)
351 { 370 {
352 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
353 if (candidates === null)
354 candidates = [];
355 candidates.push("");
356
357 let blacklistHit = null; 371 let blacklistHit = null;
358 for (let i = 0, l = candidates.length; i < l; i++) 372 for (let i = 0, l = candidates.length; i < l; i++)
359 { 373 {
360 let substr = candidates[i]; 374 let substr = candidates[i];
361 if (substr in this.whitelist.filterByKeyword) 375 if (substr in whitelist.filterByKeyword)
362 { 376 {
363 let result = this.whitelist._checkEntryMatch(substr, location, contentTy pe, docDomain, thirdParty, sitekey); 377 let result = whitelist._checkEntryMatch(substr, location, contentType, d ocDomain, thirdParty, sitekey);
364 if (result) 378 if (result)
365 return result; 379 return result;
366 } 380 }
367 if (substr in this.blacklist.filterByKeyword && blacklistHit === null) 381 if (substr in blacklist.filterByKeyword && blacklistHit === null)
368 blacklistHit = this.blacklist._checkEntryMatch(substr, location, content Type, docDomain, thirdParty, sitekey); 382 blacklistHit = blacklist._checkEntryMatch(substr, location, contentType, docDomain, thirdParty, sitekey);
369 } 383 }
370 return blacklistHit; 384 return blacklistHit;
371 }, 385 },
372 386
373 /** 387 /**
374 * @see Matcher#matchesAny 388 * @see Matcher#matchesAny
375 */ 389 */
376 matchesAny: function(location, contentType, docDomain, thirdParty, sitekey) 390 matchesAny: function(location, contentType, docDomain, thirdParty, sitekey)
377 { 391 {
378 let key = location + " " + contentType + " " + docDomain + " " + thirdParty + " " + sitekey; 392 let key = location + " " + contentType + " " + docDomain + " " + thirdParty + " " + sitekey;
379 if (key in this.resultCache) 393 if (key in this.resultCache)
380 return this.resultCache[key]; 394 return this.resultCache[key];
381 395
382 let result = this.matchesAnyInternal(location, contentType, docDomain, third Party, sitekey); 396 let candidates = location.toLowerCase().match(/[a-z0-9%]{3,}/g);
397 if (candidates === null)
398 candidates = [];
399 candidates.push("");
400
401 let result = (this.matchesAnyInternal(this.userBlacklist, this.userWhitelist , candidates, location, contentType, docDomain, thirdParty, sitekey) ||
402 this.matchesAnyInternal(this.blacklist, this.whitelist, candidates, location, contentType, docDomain, thirdParty, sitekey));
383 403
384 if (this.cacheEntries >= CombinedMatcher.maxCacheEntries) 404 if (this.cacheEntries >= CombinedMatcher.maxCacheEntries)
385 { 405 {
386 this.resultCache = Object.create(null); 406 this.resultCache = Object.create(null);
387 this.cacheEntries = 0; 407 this.cacheEntries = 0;
388 } 408 }
389 409
390 this.resultCache[key] = result; 410 this.resultCache[key] = result;
391 this.cacheEntries++; 411 this.cacheEntries++;
392 412
393 return result; 413 return result;
394 } 414 }
395 } 415 }
396 416
397 /** 417 /**
398 * Shared CombinedMatcher instance that should usually be used. 418 * Shared CombinedMatcher instance that should usually be used.
399 * @type CombinedMatcher 419 * @type CombinedMatcher
400 */ 420 */
401 let defaultMatcher = exports.defaultMatcher = new CombinedMatcher(); 421 let defaultMatcher = exports.defaultMatcher = new CombinedMatcher();
OLDNEW
« no previous file with comments | « lib/filterClasses.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld