| 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 {filterIt, mapIt, flattenIt, 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   yield* mapIt(filterIt(filter.domains || [], ([domain]) => domain != ""), | 
|  | 49                ([domain, include]) => [domain, include, | 
|  | 50                                        filtersByDomain.get(domain)]); | 
|  | 51 } | 
|  | 52 | 
|  | 53 /** | 
|  | 54  * Yields subdomains of a domain | 
|  | 55  * @param {string} domain | 
|  | 56  * @yields {string} | 
|  | 57  */ | 
|  | 58 function* subdomains(domain) | 
|  | 59 { | 
|  | 60   yield* mapIt(regExpIt(/([^|]*)\|/g, domain.replace(/([^.]+\.)/g, "$'|")), | 
|  | 61                ([, subdomain]) => subdomain); | 
|  | 62 } | 
|  | 63 | 
|  | 64 /** | 
|  | 65  * Yields the filters for a domain and its subdomains, along with whether the | 
|  | 66  * filter should be included on its corresponding domain | 
|  | 67  * @param {string} domain | 
|  | 68  * @yields {Array.<ElemHideEmulationFilter,boolean>} | 
|  | 69  */ | 
|  | 70 function* filtersForDomain(domain) | 
|  | 71 { | 
|  | 72   yield* filtersByDomain.get(domain) || []; | 
|  | 73 | 
|  | 74   yield* flattenIt(mapIt(subdomains(domain), | 
|  | 75                          subdomain => filtersByDomain.get(subdomain) || [])); | 
|  | 76 } | 
| 28 | 77 | 
| 29 /** | 78 /** | 
| 30  * Container for element hiding emulation filters | 79  * Container for element hiding emulation filters | 
| 31  * @class | 80  * @class | 
| 32  */ | 81  */ | 
| 33 let ElemHideEmulation = { | 82 let ElemHideEmulation = { | 
| 34   /** | 83   /** | 
| 35    * Removes all known filters | 84    * Removes all known filters | 
| 36    */ | 85    */ | 
| 37   clear() | 86   clear() | 
| 38   { | 87   { | 
| 39     filters.clear(); | 88     filtersByDomain.clear(); | 
| 40   }, | 89   }, | 
| 41 | 90 | 
| 42   /** | 91   /** | 
| 43    * Add a new element hiding emulation filter | 92    * Add a new element hiding emulation filter | 
| 44    * @param {ElemHideEmulationFilter} filter | 93    * @param {ElemHideEmulationFilter} filter | 
| 45    */ | 94    */ | 
| 46   add(filter) | 95   add(filter) | 
| 47   { | 96   { | 
| 48     filters.add(filter.text); | 97     if (knownFilters.has(filter)) | 
|  | 98       return; | 
|  | 99 | 
|  | 100     for (let [domain, include, filters] of filterDomains(filter)) | 
|  | 101     { | 
|  | 102       if (filters) | 
|  | 103         filters.set(filter, include); | 
|  | 104       else | 
|  | 105         filtersByDomain.set(domain, new Map([[filter, include]])); | 
|  | 106     } | 
|  | 107 | 
|  | 108     knownFilters.add(filter); | 
| 49   }, | 109   }, | 
| 50 | 110 | 
| 51   /** | 111   /** | 
| 52    * Removes an element hiding emulation filter | 112    * Removes an element hiding emulation filter | 
| 53    * @param {ElemHideEmulationFilter} filter | 113    * @param {ElemHideEmulationFilter} filter | 
| 54    */ | 114    */ | 
| 55   remove(filter) | 115   remove(filter) | 
| 56   { | 116   { | 
| 57     filters.delete(filter.text); | 117     if (!knownFilters.has(filter)) | 
|  | 118       return; | 
|  | 119 | 
|  | 120     for (let [domain, , filters] of filterDomains(filter)) | 
|  | 121     { | 
|  | 122       if (filters) | 
|  | 123       { | 
|  | 124         filters.delete(filter); | 
|  | 125 | 
|  | 126         if (filters.size == 0) | 
|  | 127           filtersByDomain.delete(domain); | 
|  | 128       } | 
|  | 129     } | 
|  | 130 | 
|  | 131     knownFilters.delete(filter); | 
| 58   }, | 132   }, | 
| 59 | 133 | 
| 60   /** | 134   /** | 
| 61    * Returns a list of all rules active on a particular domain | 135    * Returns a list of all rules active on a particular domain | 
| 62    * @param {string} domain | 136    * @param {string} domain | 
| 63    * @return {ElemHideEmulationFilter[]} | 137    * @return {ElemHideEmulationFilter[]} | 
| 64    */ | 138    */ | 
| 65   getRulesForDomain(domain) | 139   getRulesForDomain(domain) | 
| 66   { | 140   { | 
| 67     let result = []; | 141     let result = []; | 
| 68     for (let text of filters.values()) | 142 | 
|  | 143     let excludeSet = new Set(); | 
|  | 144     for (let [filter, include] of filtersForDomain(domain.toUpperCase())) | 
| 69     { | 145     { | 
| 70       let filter = Filter.fromText(text); | 146       if (!include) | 
| 71       if (filter.isActiveOnDomain(domain) && | 147       { | 
| 72           !ElemHide.getException(filter, domain)) | 148         excludeSet.add(filter); | 
|  | 149       } | 
|  | 150       else if ((excludeSet.size == 0 || !excludeSet.has(filter)) && | 
|  | 151                !ElemHide.getException(filter, domain)) | 
| 73       { | 152       { | 
| 74         result.push(filter); | 153         result.push(filter); | 
| 75       } | 154       } | 
| 76     } | 155     } | 
|  | 156 | 
| 77     return result; | 157     return result; | 
| 78   } | 158   } | 
| 79 }; | 159 }; | 
| 80 exports.ElemHideEmulation = ElemHideEmulation; | 160 exports.ElemHideEmulation = ElemHideEmulation; | 
| OLD | NEW | 
|---|