| LEFT | RIGHT | 
|---|
| 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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 48 | 48 | 
| 49 /** | 49 /** | 
| 50  * Map to be used instead when a filter has a blank domains property. | 50  * Map to be used instead when a filter has a blank domains property. | 
| 51  * @type {Map.<string,boolean>} | 51  * @type {Map.<string,boolean>} | 
| 52  * @const | 52  * @const | 
| 53  */ | 53  */ | 
| 54 let defaultDomains = new Map([["", true]]); | 54 let defaultDomains = new Map([["", true]]); | 
| 55 | 55 | 
| 56 /** | 56 /** | 
| 57  * Set containing known element hiding filters | 57  * Set containing known element hiding filters | 
| 58  * @type {Set.<ElemHideFilter>} | 58  * @type {Set.<ElemHideFilter>} | 
| 59  */ | 59  */ | 
| 60 let knownFilters = new Set(); | 60 let knownFilters = new Set(); | 
| 61 | 61 | 
| 62 /** | 62 /** | 
| 63  * Adds a filter to the lookup table of filters by domain. | 63  * Adds a filter to the lookup table of filters by domain. | 
| 64  * @param {Filter} filter | 64  * @param {Filter} filter | 
| 65  */ | 65  */ | 
| 66 function addToFiltersByDomain(filter) | 66 function addToFiltersByDomain(filter) | 
| 67 { | 67 { | 
| 68   let domains = filter.domains || defaultDomains; | 68   let domains = filter.domains || defaultDomains; | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 107 /** | 107 /** | 
| 108  * Container for element hiding filters | 108  * Container for element hiding filters | 
| 109  * @class | 109  * @class | 
| 110  */ | 110  */ | 
| 111 exports.ElemHide = { | 111 exports.ElemHide = { | 
| 112   /** | 112   /** | 
| 113    * Removes all known filters | 113    * Removes all known filters | 
| 114    */ | 114    */ | 
| 115   clear() | 115   clear() | 
| 116   { | 116   { | 
| 117     for (let collection of [filtersByDomain, filterBySelector, | 117     for (let collection of [filtersByDomain, filterBySelector, knownFilters]) | 
| 118                             knownFilters]) |  | 
| 119     { |  | 
| 120       collection.clear(); | 118       collection.clear(); | 
| 121     } | 119 | 
| 122     unconditionalSelectors = null; | 120     unconditionalSelectors = null; | 
| 123     FilterNotifier.emit("elemhideupdate"); | 121     FilterNotifier.emit("elemhideupdate"); | 
| 124   }, | 122   }, | 
| 125 | 123 | 
| 126   /** | 124   /** | 
| 127    * Add a new element hiding filter | 125    * Add a new element hiding filter | 
| 128    * @param {ElemHideFilter} filter | 126    * @param {ElemHideFilter} filter | 
| 129    */ | 127    */ | 
| 130   add(filter) | 128   add(filter) | 
| 131   { | 129   { | 
| 132     if (knownFilters.has(filter)) | 130     if (knownFilters.has(filter)) | 
| 133       return; | 131       return; | 
| 134 | 132 | 
| 135     if (!(filter.domains || ElemHideExceptions.hasExceptions(filter.selector))) | 133     let {selector} = filter; | 
|  | 134 | 
|  | 135     if (!(filter.domains || ElemHideExceptions.hasExceptions(selector))) | 
| 136     { | 136     { | 
| 137       // The new filter's selector is unconditionally applied to all domains | 137       // The new filter's selector is unconditionally applied to all domains | 
| 138       filterBySelector.set(filter.selector, filter); | 138       filterBySelector.set(selector, filter); | 
| 139       unconditionalSelectors = null; | 139       unconditionalSelectors = null; | 
| 140     } | 140     } | 
| 141     else | 141     else | 
| 142     { | 142     { | 
| 143       // The new filter's selector only applies to some domains | 143       // The new filter's selector only applies to some domains | 
| 144       addToFiltersByDomain(filter); | 144       addToFiltersByDomain(filter); | 
| 145     } | 145     } | 
| 146 | 146 | 
| 147     knownFilters.add(filter); | 147     knownFilters.add(filter); | 
| 148     FilterNotifier.emit("elemhideupdate"); | 148     FilterNotifier.emit("elemhideupdate"); | 
| 149   }, | 149   }, | 
| 150 | 150 | 
| 151   /** | 151   /** | 
| 152    * Removes an element hiding filter | 152    * Removes an element hiding filter | 
| 153    * @param {ElemHideFilter} filter | 153    * @param {ElemHideFilter} filter | 
| 154    */ | 154    */ | 
| 155   remove(filter) | 155   remove(filter) | 
| 156   { | 156   { | 
| 157     if (!knownFilters.has(filter)) | 157     if (!knownFilters.has(filter)) | 
| 158       return; | 158       return; | 
| 159 | 159 | 
|  | 160     let {selector} = filter; | 
|  | 161 | 
| 160     // Unconditially applied element hiding filters | 162     // Unconditially applied element hiding filters | 
| 161     if (filterBySelector.get(filter.selector) == filter) | 163     if (filterBySelector.get(selector) == filter) | 
| 162     { | 164     { | 
| 163       filterBySelector.delete(filter.selector); | 165       filterBySelector.delete(selector); | 
| 164       unconditionalSelectors = null; | 166       unconditionalSelectors = null; | 
| 165     } | 167     } | 
| 166     // Conditionally applied element hiding filters | 168     // Conditionally applied element hiding filters | 
| 167     else | 169     else | 
| 168     { | 170     { | 
| 169       let domains = filter.domains || defaultDomains; | 171       let domains = filter.domains || defaultDomains; | 
| 170       for (let domain of domains.keys()) | 172       for (let domain of domains.keys()) | 
| 171       { | 173       { | 
| 172         let filters = filtersByDomain.get(domain); | 174         let filters = filtersByDomain.get(domain); | 
| 173         if (filters) | 175         if (filters) | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
| 184    * on a particular host name. | 186    * on a particular host name. | 
| 185    * @param {string} domain | 187    * @param {string} domain | 
| 186    * @param {boolean} [specificOnly] true if generic filters should not apply. | 188    * @param {boolean} [specificOnly] true if generic filters should not apply. | 
| 187    * @returns {string[]} List of selectors. | 189    * @returns {string[]} List of selectors. | 
| 188    */ | 190    */ | 
| 189   getSelectorsForDomain(domain, specificOnly = false) | 191   getSelectorsForDomain(domain, specificOnly = false) | 
| 190   { | 192   { | 
| 191     let selectors = []; | 193     let selectors = []; | 
| 192 | 194 | 
| 193     let excluded = new Set(); | 195     let excluded = new Set(); | 
| 194     let currentDomain = domain ? domain.toUpperCase() : ""; | 196     let currentDomain = domain ? domain.replace(/\.+$/, "").toLowerCase() : ""; | 
| 195 | 197 | 
| 196     // This code is a performance hot-spot, which is why we've made certain | 198     // This code is a performance hot-spot, which is why we've made certain | 
| 197     // micro-optimisations. Please be careful before making changes. | 199     // micro-optimisations. Please be careful before making changes. | 
| 198     while (true) | 200     while (true) | 
| 199     { | 201     { | 
| 200       if (specificOnly && currentDomain == "") | 202       if (specificOnly && currentDomain == "") | 
| 201         break; | 203         break; | 
| 202 | 204 | 
| 203       let filters = filtersByDomain.get(currentDomain); | 205       let filters = filtersByDomain.get(currentDomain); | 
| 204       if (filters) | 206       if (filters) | 
| 205       { | 207       { | 
| 206         for (let [filter, isIncluded] of filters) | 208         for (let [filter, isIncluded] of filters) | 
| 207         { | 209         { | 
| 208           if (!isIncluded) | 210           if (!isIncluded) | 
| 209           { | 211           { | 
| 210             excluded.add(filter); | 212             excluded.add(filter); | 
| 211           } | 213           } | 
| 212           else if ((excluded.size == 0 || !excluded.has(filter)) && | 214           else | 
| 213                    !ElemHideExceptions.getException(filter, domain)) |  | 
| 214           { | 215           { | 
| 215             selectors.push(filter.selector); | 216             let {selector} = filter; | 
|  | 217             if ((excluded.size == 0 || !excluded.has(filter)) && | 
|  | 218                 !ElemHideExceptions.getException(selector, domain)) | 
|  | 219             { | 
|  | 220               selectors.push(selector); | 
|  | 221             } | 
| 216           } | 222           } | 
| 217         } | 223         } | 
| 218       } | 224       } | 
| 219 | 225 | 
| 220       if (currentDomain == "") | 226       if (currentDomain == "") | 
| 221         break; | 227         break; | 
| 222 | 228 | 
| 223       let nextDot = currentDomain.indexOf("."); | 229       let nextDot = currentDomain.indexOf("."); | 
| 224       currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); | 230       currentDomain = nextDot == -1 ? "" : currentDomain.substr(nextDot + 1); | 
| 225     } | 231     } | 
| 226 | 232 | 
| 227     if (!specificOnly) | 233     if (!specificOnly) | 
| 228       selectors = getUnconditionalSelectors().concat(selectors); | 234       selectors = getUnconditionalSelectors().concat(selectors); | 
| 229 | 235 | 
| 230     return selectors; | 236     return selectors; | 
| 231   } | 237   } | 
| 232 }; | 238 }; | 
| LEFT | RIGHT | 
|---|