| OLD | NEW | 
| (Empty) |  | 
 |    1 /* | 
 |    2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
 |    3  * Copyright (C) 2006-present eyeo GmbH | 
 |    4  * | 
 |    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 | 
 |    7  * published by the Free Software Foundation. | 
 |    8  * | 
 |    9  * Adblock Plus is distributed in the hope that it will be useful, | 
 |   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |   12  * GNU General Public License for more details. | 
 |   13  * | 
 |   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/>. | 
 |   16  */ | 
 |   17  | 
 |   18 #include "ElemHide.h" | 
 |   19  | 
 |   20 DependentString _ElemHide_SelectorList::SelectorAt(size_t idx) const | 
 |   21 { | 
 |   22   return DependentString(mSelectors[idx]->GetSelector()); | 
 |   23 } | 
 |   24  | 
 |   25 const String& _ElemHide_SelectorList::FilterKeyAt(size_t idx) const | 
 |   26 { | 
 |   27   return mSelectors[idx]->GetText(); | 
 |   28 } | 
 |   29  | 
 |   30 ElemHide* ElemHide::mInstance = new ElemHide(); | 
 |   31  | 
 |   32 void ElemHide::Clear() | 
 |   33 { | 
 |   34   mFilters.clear(); | 
 |   35   mExceptions.clear(); | 
 |   36   mFiltersByDomain.clear(); | 
 |   37   mKnownExceptions.clear(); | 
 |   38 } | 
 |   39  | 
 |   40 namespace { | 
 |   41  | 
 |   42   ActiveFilter::DomainMap* DefaultDomains() | 
 |   43   { | 
 |   44     static ActiveFilter::DomainMap defaultDomains; | 
 |   45     if (defaultDomains.empty()) | 
 |   46       defaultDomains[u""_str] = true; | 
 |   47     return &defaultDomains; | 
 |   48   } | 
 |   49  | 
 |   50 } | 
 |   51  | 
 |   52 void ElemHide::AddToFiltersByDomain(ElemHideBase& filter) | 
 |   53 { | 
 |   54   auto domains = filter.GetDomains(); | 
 |   55   if (!domains) | 
 |   56     domains = DefaultDomains(); | 
 |   57  | 
 |   58   DependentString text(filter.GetText()); | 
 |   59   for (auto& domain : *domains) | 
 |   60   { | 
 |   61     auto& filters = mFiltersByDomain[domain.first]; | 
 |   62     if (domain.second) | 
 |   63       filters[text] = ElemHideBasePtr(&filter); | 
 |   64     else | 
 |   65     { | 
 |   66       auto iter = filters.find(text); | 
 |   67       if (iter != filters.end()) | 
 |   68         filters.erase(iter); | 
 |   69     } | 
 |   70   } | 
 |   71 } | 
 |   72  | 
 |   73 void ElemHide::Add(ElemHideBase& filter) | 
 |   74 { | 
 |   75   // we must ensure we have the right class. | 
 |   76   // This is an error, but we might get Invalid filters. | 
 |   77   if (!filter.As<ElemHideBase>()) | 
 |   78     return; | 
 |   79  | 
 |   80   DependentString text(filter.GetText()); | 
 |   81   if (filter.mType == Filter::Type::ELEMHIDEEXCEPTION) | 
 |   82   { | 
 |   83     if (mKnownExceptions.find(text)) | 
 |   84       return; | 
 |   85  | 
 |   86     auto selector = filter.GetSelector(); | 
 |   87     mExceptions[selector].push_back( | 
 |   88       ElemHideExceptionPtr(filter.As<ElemHideException>())); | 
 |   89  | 
 |   90     // Selector is not longer unconditional | 
 |   91     mUnconditionalSelectors.erase(text); | 
 |   92     mUnconditionalSelectorsCache.reset(); | 
 |   93     mKnownExceptions.insert(text); | 
 |   94   } | 
 |   95   else | 
 |   96   { | 
 |   97     if (mFilters.find(text)) | 
 |   98       return; | 
 |   99  | 
 |  100     mFilters[text] = ElemHideBasePtr(filter.As<ElemHideBase>()); | 
 |  101     if (!((filter.GetDomains() && filter.GetDomains()->size()) || | 
 |  102           mExceptions.find(filter.GetSelector()))) | 
 |  103     { | 
 |  104       // The new filter's selector is unconditionally applied to all domains | 
 |  105       mUnconditionalSelectors.insert(text); | 
 |  106       mUnconditionalSelectorsCache.reset(); | 
 |  107     } | 
 |  108     else | 
 |  109     { | 
 |  110       AddToFiltersByDomain(filter); | 
 |  111     } | 
 |  112   } | 
 |  113 } | 
 |  114  | 
 |  115 void ElemHide::Remove(ElemHideBase& filter) | 
 |  116 { | 
 |  117   DependentString text(filter.GetText()); | 
 |  118  | 
 |  119   if (filter.mType == Filter::Type::ELEMHIDEEXCEPTION) | 
 |  120   { | 
 |  121     // never seen the exception. | 
 |  122     if (!mKnownExceptions.find(text)) | 
 |  123       return; | 
 |  124  | 
 |  125     auto selector = filter.GetSelector(); | 
 |  126     auto& list = mExceptions[selector]; | 
 |  127     auto iter = std::find( | 
 |  128       list.begin(), list.end(), | 
 |  129       ElemHideExceptionPtr(filter.As<ElemHideException>())); | 
 |  130     if (iter != list.end()) | 
 |  131       list.erase(iter); | 
 |  132     mKnownExceptions.erase(text); | 
 |  133   } | 
 |  134   else | 
 |  135   { | 
 |  136     if (!mFilters.find(text)) | 
 |  137       return; | 
 |  138  | 
 |  139     if (mUnconditionalSelectors.find(text)) | 
 |  140     { | 
 |  141       mUnconditionalSelectors.erase(text); | 
 |  142       mUnconditionalSelectorsCache.reset(); | 
 |  143     } | 
 |  144     else | 
 |  145     { | 
 |  146       auto domains = filter.GetDomains(); | 
 |  147       for (auto domain : *domains) | 
 |  148       { | 
 |  149         auto& list = mFiltersByDomain[domain.first]; | 
 |  150         list.erase(text); | 
 |  151       } | 
 |  152     } | 
 |  153  | 
 |  154     mFilters.erase(text); | 
 |  155   } | 
 |  156 } | 
 |  157  | 
 |  158 ElemHideException* ElemHide::GetException(const ElemHideBase& filter, | 
 |  159                                           DependentString& docDomain) const | 
 |  160 { | 
 |  161   auto exception = mExceptions.find(filter.GetSelector()); | 
 |  162   if (!exception) | 
 |  163     return nullptr; | 
 |  164  | 
 |  165   auto& list = exception->second; | 
 |  166   for (auto iter = list.rbegin(); iter != list.rend(); iter++) | 
 |  167   { | 
 |  168     DependentString domain(docDomain); | 
 |  169     if ((*iter)->IsActiveOnDomain(domain, u""_str)) | 
 |  170     { | 
 |  171       ElemHideExceptionPtr filter(*iter); | 
 |  172       return filter.release(); | 
 |  173     } | 
 |  174   } | 
 |  175  | 
 |  176   return nullptr; | 
 |  177 } | 
 |  178  | 
 |  179 _ElemHide_SelectorList* ElemHide::GetUnconditionalSelectors() const | 
 |  180 { | 
 |  181   if (!mUnconditionalSelectorsCache) | 
 |  182   { | 
 |  183     mUnconditionalSelectorsCache = intrusive_ptr<_ElemHide_SelectorList>(new _El
     emHide_SelectorList, false); | 
 |  184     annotate_address(mUnconditionalSelectorsCache.get(), "_ElemHide_SelectorList
     "); | 
 |  185     for (auto unconditional : mUnconditionalSelectors) | 
 |  186     { | 
 |  187       auto filter = mFilters.find(unconditional.first); | 
 |  188       if (filter) | 
 |  189         mUnconditionalSelectorsCache->push_back(filter->second); | 
 |  190     } | 
 |  191   } | 
 |  192   return mUnconditionalSelectorsCache.get(); | 
 |  193 } | 
 |  194  | 
 |  195 _ElemHide_SelectorList* ElemHide::GetSelectorsForDomain(const String& domain, | 
 |  196   Criteria criteria) const | 
 |  197 { | 
 |  198   _ElemHide_SelectorList* selectors = new _ElemHide_SelectorList; | 
 |  199   annotate_address(selectors, "_ElemHide_SelectorList"); | 
 |  200  | 
 |  201   if (criteria < NO_UNCONDITIONAL) | 
 |  202     selectors->append(GetUnconditionalSelectors()); | 
 |  203  | 
 |  204   bool specificOnly = (criteria >= SPECIFIC_ONLY); | 
 |  205   StringSet seenFilters; | 
 |  206   DependentString docDomain(domain); | 
 |  207  | 
 |  208   DependentString currentDomain(domain); | 
 |  209   while (true) | 
 |  210   { | 
 |  211     if (specificOnly && currentDomain.empty()) | 
 |  212       break; | 
 |  213  | 
 |  214     auto filters = mFiltersByDomain.find(currentDomain); | 
 |  215     if (filters) | 
 |  216     { | 
 |  217       for (auto& entry : filters->second) | 
 |  218       { | 
 |  219         if (entry.first.is_invalid()) | 
 |  220           continue; | 
 |  221  | 
 |  222         if (seenFilters.find(entry.first)) | 
 |  223           continue; | 
 |  224         seenFilters.insert(entry.first); | 
 |  225  | 
 |  226         auto filter = entry.second; | 
 |  227         if (filter && !GetException(*filter, docDomain)) | 
 |  228           selectors->push_back(filter); | 
 |  229       } | 
 |  230     } | 
 |  231  | 
 |  232     if (currentDomain.empty()) | 
 |  233       break; | 
 |  234  | 
 |  235     auto nextDot = currentDomain.find('.'); | 
 |  236     currentDomain = nextDot == String::npos ? | 
 |  237       u""_str : DependentString(currentDomain, nextDot + 1); | 
 |  238   } | 
 |  239  | 
 |  240   return selectors; | 
 |  241 } | 
| OLD | NEW |