| OLD | NEW | 
|    1 /* |    1 /* | 
|    2  * This file is part of Adblock Plus <https://adblockplus.org/>, |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
|    3  * Copyright (C) 2006-present eyeo GmbH |    3  * Copyright (C) 2006-present eyeo GmbH | 
|    4  * |    4  * | 
|    5  * Adblock Plus is free software: you can redistribute it and/or modify |    5  * Adblock Plus is free software: you can redistribute it and/or modify | 
|    6  * it under the terms of the GNU General Public License version 3 as |    6  * it under the terms of the GNU General Public License version 3 as | 
|    7  * published by the Free Software Foundation. |    7  * published by the Free Software Foundation. | 
|    8  * |    8  * | 
|    9  * Adblock Plus is distributed in the hope that it will be useful, |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
|   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|   12  * GNU General Public License for more details. |   12  * GNU General Public License for more details. | 
|   13  * |   13  * | 
|   14  * You should have received a copy of the GNU General Public License |   14  * You should have received a copy of the GNU General Public License | 
|   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |   15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
|   16  */ |   16  */ | 
|   17  |   17  | 
|   18 "use strict"; |   18 "use strict"; | 
|   19  |   19  | 
|   20 /** |   20 /** | 
|   21  * @fileOverview Element hiding emulation implementation. |   21  * @fileOverview Element hiding emulation implementation. | 
|   22  */ |   22  */ | 
|   23  |   23  | 
|   24 const {ElemHide} = require("./elemHide"); |   24 const {ElemHide} = require("./elemHide"); | 
|   25 const {Filter} = require("./filterClasses"); |   25 const {regExpIt} = require("./coreUtils"); | 
|   26  |   26  | 
|   27 let filters = new Set(); |   27 /** | 
 |   28  * Map of element hiding emulation filters by domain | 
 |   29  * @type {Map.<string,Map.<ElemHideEmulationFilter,boolean>>} | 
 |   30  */ | 
 |   31 let filtersByDomain = new Map(); | 
 |   32  | 
 |   33 /** | 
 |   34  * Set containing known element hiding emulation filters | 
 |   35  * @type {Set.<ElemHideEmulation>} | 
 |   36  */ | 
 |   37 let knownFilters = new Set(); | 
 |   38  | 
 |   39 /** | 
 |   40  * Yields the domains associated with a filter, along with whether the filter | 
 |   41  * should be included on the domain and the set of filters associated with the | 
 |   42  * domain | 
 |   43  * @param {ElemHideEmulationFilter} filter | 
 |   44  * @yields {Array.<string,boolean,?Set.<ElemHideEmulationFilter>>} | 
 |   45  */ | 
 |   46 function* filterDomains(filter) | 
 |   47 { | 
 |   48   for (let [domain, include] of filter.domains || []) | 
 |   49   { | 
 |   50     if (domain != "") | 
 |   51       yield [domain, include, filtersByDomain.get(domain)]; | 
 |   52   } | 
 |   53 } | 
 |   54  | 
 |   55 /** | 
 |   56  * Yields subdomains of a domain | 
 |   57  * @param {string} domain | 
 |   58  * @yields {string} | 
 |   59  */ | 
 |   60 function* subdomains(domain) | 
 |   61 { | 
 |   62   for (let [, subdomain] of | 
 |   63        regExpIt(/([^|]*)\|/g, domain.replace(/([^.]+\.)/g, "$'|"))) | 
 |   64   { | 
 |   65     yield subdomain; | 
 |   66   } | 
 |   67 } | 
 |   68  | 
 |   69 /** | 
 |   70  * Yields the filters for a domain and its subdomains, along with whether the | 
 |   71  * filter should be included on its corresponding domain | 
 |   72  * @param {string} domain | 
 |   73  * @yields {Array.<ElemHideEmulationFilter,boolean>} | 
 |   74  */ | 
 |   75 function* filtersForDomain(domain) | 
 |   76 { | 
 |   77   yield* filtersByDomain.get(domain) || []; | 
 |   78  | 
 |   79   for (let subdomain of subdomains(domain)) | 
 |   80     yield* filtersByDomain.get(subdomain) || []; | 
 |   81 } | 
|   28  |   82  | 
|   29 /** |   83 /** | 
|   30  * Container for element hiding emulation filters |   84  * Container for element hiding emulation filters | 
|   31  * @class |   85  * @class | 
|   32  */ |   86  */ | 
|   33 let ElemHideEmulation = { |   87 let ElemHideEmulation = { | 
|   34   /** |   88   /** | 
|   35    * Removes all known filters |   89    * Removes all known filters | 
|   36    */ |   90    */ | 
|   37   clear() |   91   clear() | 
|   38   { |   92   { | 
|   39     filters.clear(); |   93     filtersByDomain.clear(); | 
|   40   }, |   94   }, | 
|   41  |   95  | 
|   42   /** |   96   /** | 
|   43    * Add a new element hiding emulation filter |   97    * Add a new element hiding emulation filter | 
|   44    * @param {ElemHideEmulationFilter} filter |   98    * @param {ElemHideEmulationFilter} filter | 
|   45    */ |   99    */ | 
|   46   add(filter) |  100   add(filter) | 
|   47   { |  101   { | 
|   48     filters.add(filter.text); |  102     if (knownFilters.has(filter)) | 
 |  103       return; | 
 |  104  | 
 |  105     for (let [domain, include, filters] of filterDomains(filter)) | 
 |  106     { | 
 |  107       if (filters) | 
 |  108         filters.set(filter, include); | 
 |  109       else | 
 |  110         filtersByDomain.set(domain, new Map([[filter, include]])); | 
 |  111     } | 
 |  112  | 
 |  113     knownFilters.add(filter); | 
|   49   }, |  114   }, | 
|   50  |  115  | 
|   51   /** |  116   /** | 
|   52    * Removes an element hiding emulation filter |  117    * Removes an element hiding emulation filter | 
|   53    * @param {ElemHideEmulationFilter} filter |  118    * @param {ElemHideEmulationFilter} filter | 
|   54    */ |  119    */ | 
|   55   remove(filter) |  120   remove(filter) | 
|   56   { |  121   { | 
|   57     filters.delete(filter.text); |  122     if (!knownFilters.has(filter)) | 
 |  123       return; | 
 |  124  | 
 |  125     for (let [domain, , filters] of filterDomains(filter)) | 
 |  126     { | 
 |  127       if (filters) | 
 |  128       { | 
 |  129         filters.delete(filter); | 
 |  130  | 
 |  131         if (filters.size == 0) | 
 |  132           filtersByDomain.delete(domain); | 
 |  133       } | 
 |  134     } | 
 |  135  | 
 |  136     knownFilters.delete(filter); | 
|   58   }, |  137   }, | 
|   59  |  138  | 
|   60   /** |  139   /** | 
|   61    * Returns a list of all rules active on a particular domain |  140    * Returns a list of all rules active on a particular domain | 
|   62    * @param {string} domain |  141    * @param {string} domain | 
|   63    * @return {ElemHideEmulationFilter[]} |  142    * @return {ElemHideEmulationFilter[]} | 
|   64    */ |  143    */ | 
|   65   getRulesForDomain(domain) |  144   getRulesForDomain(domain) | 
|   66   { |  145   { | 
|   67     let result = []; |  146     let result = []; | 
|   68     for (let text of filters.values()) |  147  | 
 |  148     let excludeSet = new Set(); | 
 |  149     for (let [filter, include] of filtersForDomain(domain.toUpperCase())) | 
|   69     { |  150     { | 
|   70       let filter = Filter.fromText(text); |  151       if (!include) | 
|   71       if (filter.isActiveOnDomain(domain) && |  152       { | 
|   72           !ElemHide.getException(filter, domain)) |  153         excludeSet.add(filter); | 
 |  154       } | 
 |  155       else if ((excludeSet.size == 0 || !excludeSet.has(filter)) && | 
 |  156                !ElemHide.getException(filter, domain)) | 
|   73       { |  157       { | 
|   74         result.push(filter); |  158         result.push(filter); | 
|   75       } |  159       } | 
|   76     } |  160     } | 
 |  161  | 
|   77     return result; |  162     return result; | 
|   78   } |  163   } | 
|   79 }; |  164 }; | 
|   80 exports.ElemHideEmulation = ElemHideEmulation; |  165 exports.ElemHideEmulation = ElemHideEmulation; | 
| OLD | NEW |