Index: compiled/ElemHide.cpp |
=================================================================== |
new file mode 100644 |
--- /dev/null |
+++ b/compiled/ElemHide.cpp |
@@ -0,0 +1,235 @@ |
+/* |
+ * This file is part of Adblock Plus <https://adblockplus.org/>, |
+ * Copyright (C) 2006-present eyeo GmbH |
+ * |
+ * Adblock Plus is free software: you can redistribute it and/or modify |
+ * it under the terms of the GNU General Public License version 3 as |
+ * published by the Free Software Foundation. |
+ * |
+ * Adblock Plus is distributed in the hope that it will be useful, |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
+ * GNU General Public License for more details. |
+ * |
+ * You should have received a copy of the GNU General Public License |
+ * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. |
+ */ |
+ |
+#include "ElemHide.h" |
+ |
+DependentString _ElemHide_SelectorList::SelectorAt(size_t idx) const |
+{ |
+ return DependentString(mSelectors[idx]->GetSelector()); |
+} |
+ |
+const String& _ElemHide_SelectorList::FilterKeyAt(size_t idx) const |
+{ |
+ return mSelectors[idx]->GetText(); |
+} |
+ |
+ElemHide* ElemHide::mInstance = new ElemHide(); |
+ |
+void ElemHide::Clear() |
+{ |
+ mFilters.clear(); |
+ mExceptions.clear(); |
+ mFiltersByDomain.clear(); |
+ mKnownExceptions.clear(); |
+} |
+ |
+namespace { |
+ |
+ ActiveFilter::DomainMap* DefaultDomains() |
+ { |
+ static ActiveFilter::DomainMap defaultDomains; |
+ if (defaultDomains.empty()) |
+ defaultDomains[u""_str] = true; |
+ return &defaultDomains; |
+ } |
+ |
+} |
+ |
+void ElemHide::AddToFiltersByDomain(ElemHideBase& filter) |
+{ |
+ auto domains = filter.GetDomains(); |
+ if (!domains) |
+ domains = DefaultDomains(); |
+ |
+ DependentString text(filter.GetText()); |
+ for (auto& domain : *domains) |
+ { |
+ auto& filters = mFiltersByDomain[domain.first]; |
+ if (domain.second) |
+ filters[text] = ElemHideBasePtr(&filter); |
+ else |
+ { |
+ auto iter = filters.find(text); |
+ if (iter != filters.end()) |
+ filters.erase(iter); |
+ } |
+ } |
+} |
+ |
+void ElemHide::Add(ElemHideBase& filter) |
+{ |
+ // we must ensure we have the right class. |
+ // This is an error, but we might get Invalid filters. |
+ if (!filter.As<ElemHideBase>()) |
+ return; |
+ |
+ DependentString text(filter.GetText()); |
+ if (filter.mType == Filter::Type::ELEMHIDEEXCEPTION) |
+ { |
+ if (mKnownExceptions.find(text)) |
+ return; |
+ |
+ auto selector = filter.GetSelector(); |
+ mExceptions[selector].push_back( |
+ ElemHideExceptionPtr(filter.As<ElemHideException>())); |
+ |
+ // Selector is not longer unconditional |
+ mUnconditionalSelectors.erase(text); |
+ |
+ mKnownExceptions.insert(text); |
+ } |
+ else |
+ { |
+ if (mFilters.find(text)) |
+ return; |
+ |
+ mFilters[text] = ElemHideBasePtr(filter.As<ElemHideBase>()); |
+ if (!((filter.GetDomains() && filter.GetDomains()->size()) || |
+ mExceptions.find(filter.GetSelector()))) |
+ { |
+ // The new filter's selector is unconditionally applied to all domains |
+ mUnconditionalSelectors.insert(text); |
+ } |
+ else |
+ { |
+ AddToFiltersByDomain(filter); |
+ } |
+ } |
+} |
+ |
+void ElemHide::Remove(ElemHideBase& filter) |
+{ |
+ DependentString text(filter.GetText()); |
+ |
+ if (filter.mType == Filter::Type::ELEMHIDEEXCEPTION) |
+ { |
+ // never seen the exception. |
+ if (!mKnownExceptions.find(text)) |
+ return; |
+ |
+ auto selector = filter.GetSelector(); |
+ auto& list = mExceptions[selector]; |
+ auto iter = std::find( |
+ list.begin(), list.end(), |
+ ElemHideExceptionPtr(filter.As<ElemHideException>())); |
+ if (iter != list.end()) |
+ list.erase(iter); |
+ mKnownExceptions.erase(text); |
+ } |
+ else |
+ { |
+ if (!mFilters.find(text)) |
+ return; |
+ |
+ if (mUnconditionalSelectors.find(text)) |
+ mUnconditionalSelectors.erase(text); |
+ else |
+ { |
+ auto domains = filter.GetDomains(); |
+ for (auto domain : *domains) |
+ { |
+ auto list = mFiltersByDomain[domain.first]; |
+ list.erase(text); |
+ } |
+ } |
+ |
+ mFilters.erase(text); |
+ } |
+} |
+ |
+ElemHideException* ElemHide::GetException(const ElemHideBase& filter, |
+ DependentString& docDomain) const |
+{ |
+ auto exception = mExceptions.find(filter.GetSelector()); |
+ if (!exception) |
+ return nullptr; |
+ |
+ auto& list = exception->second; |
+ for (auto iter = list.rbegin(); iter != list.rend(); iter++) |
+ if ((*iter)->IsActiveOnDomain(docDomain, u""_str)) |
+ { |
+ ElemHideExceptionPtr filter(*iter); |
+ return filter.release(); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+_ElemHide_SelectorList* ElemHide::GetUnconditionalSelectors() const |
hub
2017/10/25 01:39:11
there is also a more efficient way to implement th
|
+{ |
+ auto list = new _ElemHide_SelectorList; |
+ annotate_address(list, "_ElemHide_SelectorList"); |
+ for (auto unconditional : mUnconditionalSelectors) |
+ { |
+ auto filter = mFilters.find(unconditional.first); |
+ if (filter) |
+ list->push_back(filter->second); |
+ } |
+ return list; |
+} |
+ |
+_ElemHide_SelectorList* ElemHide::GetSelectorsForDomain(const String& domain, |
+ Criteria criteria) const |
+{ |
+ _ElemHide_SelectorList* selectors; |
+ |
+ if (criteria < NO_UNCONDITIONAL) |
+ selectors = GetUnconditionalSelectors(); |
+ else |
+ { |
+ selectors = new _ElemHide_SelectorList; |
+ annotate_address(selectors, "_ElemHide_SelectorList"); |
+ } |
+ |
+ bool specificOnly = (criteria >= SPECIFIC_ONLY); |
+ StringSet seenFilters; |
+ DependentString docDomain(domain); |
+ |
+ DependentString currentDomain(domain); |
+ while (true) |
+ { |
+ if (specificOnly && currentDomain.empty()) |
+ break; |
+ |
+ auto filters = mFiltersByDomain.find(currentDomain); |
+ if (filters) |
+ { |
+ for (auto& entry : filters->second) |
+ { |
+ if (entry.first.is_invalid()) |
+ continue; |
+ |
+ if (seenFilters.find(entry.first)) |
+ continue; |
+ seenFilters.insert(entry.first); |
+ |
+ auto filter = entry.second; |
+ if (filter && !GetException(*filter, docDomain)) |
+ selectors->push_back(filter); |
+ } |
+ } |
+ |
+ if (currentDomain.empty()) |
+ break; |
+ |
+ auto nextDot = currentDomain.find('.'); |
+ currentDomain = nextDot == String::npos ? |
+ u""_str : DependentString(currentDomain, nextDot + 1); |
+ } |
+ |
+ return selectors; |
+} |