Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: compiled/ElemHide.cpp

Issue 29587914: Issue 5142 - Convert Element Hiding to C++ (Closed) Base URL: https://hg.adblockplus.org/adblockpluscore/
Patch Set: Re-added elemHide.js test. Fixed test failures related. Addresses review comments. Created Jan. 19, 2018, 2:02 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(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 OwnedString ElemHide_SelectorList::SelectorAt(size_t idx) const
21 {
22 return mSelectors[idx]->GetSelector();
23 }
24
25 const String& ElemHide_SelectorList::FilterKeyAt(size_t idx) const
26 {
27 return mSelectors[idx]->GetText();
28 }
29
30 void ElemHide::Clear()
31 {
32 mFilters.clear();
33 mExceptions.clear();
34 mFiltersByDomain.clear();
35 mKnownExceptions.clear();
36 }
37
38 const ActiveFilter::DomainMap ElemHide::defaultDomains = {
39 { ActiveFilter::DEFAULT_DOMAIN, true }
40 };
41
42 void ElemHide::AddToFiltersByDomain(ElemHideBase& filter)
43 {
44 const auto* domains = filter.GetDomains();
45 if (!domains)
46 domains = &defaultDomains;
47
48 DependentString text(filter.GetText());
49 for (const auto& domain : *domains)
50 {
51 auto& filters = mFiltersByDomain[domain.first];
52 if (domain.second)
53 filters[text] = ElemHideBasePtr(&filter);
54 else
55 filters[text] = ElemHideBasePtr();
56 }
57 }
58
59 void ElemHide::Add(ElemHideBase& filter)
60 {
61 // we must ensure we have the right class.
62 // This is an error, but we might get Invalid filters.
63 if (!filter.As<ElemHideBase>())
64 return;
65
66 DependentString text(filter.GetText());
67 if (filter.mType == Filter::Type::ELEMHIDEEXCEPTION)
68 {
69 if (mKnownExceptions.find(text))
70 return;
71
72 auto selector = filter.GetSelector();
73 mExceptions[selector].emplace_back(filter.As<ElemHideException>());
74
75 // Selector is no longer unconditional
76 auto entry = mUnconditionalSelectors.find(selector);
77 if (entry)
78 {
79 AddToFiltersByDomain(*mFilters[entry->second]);
80 mUnconditionalSelectors.erase(selector);
81 mUnconditionalSelectorsCache.reset();
82 }
83 mKnownExceptions.insert(text);
84 }
85 else
86 {
87 if (mFilters.find(text))
88 return;
89
90 auto selector = filter.GetSelector();
91 mFilters[text] = &filter;
92 if (!((filter.GetDomains() && filter.GetDomains()->size()) ||
93 mExceptions.find(selector)))
94 {
95 // The new filter's selector is unconditionally applied to all domains
96 mUnconditionalSelectors[selector] = DependentString(filter.GetText());
97 mUnconditionalSelectorsCache.reset();
98 }
99 else
100 AddToFiltersByDomain(filter);
101 }
102 }
103
104 void ElemHide::Remove(ElemHideBase& filter)
105 {
106 DependentString text(filter.GetText());
107
108 auto selector = filter.GetSelector();
109 auto exceptionFilter = filter.As<ElemHideException>();
110 if (exceptionFilter)
111 {
112 // never seen the exception.
113 if (!mKnownExceptions.find(text))
114 return;
115
116 auto& list = mExceptions[selector];
117 auto iter = std::find(list.begin(), list.end(),
118 ElemHideExceptionPtr(exceptionFilter));
119 if (iter != list.end())
120 list.erase(iter);
121 mKnownExceptions.erase(text);
122 }
123 else
124 {
125 if (!mFilters.find(text))
126 return;
127
128 if (mUnconditionalSelectors.find(selector))
129 {
130 mUnconditionalSelectors.erase(selector);
131 mUnconditionalSelectorsCache.reset();
132 }
133 else
134 {
135 const auto* domains = filter.GetDomains();
136 if (!domains)
137 domains = &defaultDomains;
138
139 for (const auto& domain : *domains)
140 {
141 auto& list = mFiltersByDomain[domain.first];
142 list.erase(text);
143 }
144 }
145
146 mFilters.erase(text);
147 }
148 }
149
150 ElemHideException* ElemHide::GetException(const ElemHideBase& filter,
151 DependentString& docDomain) const
152 {
153 auto exception = mExceptions.find(filter.GetSelector());
154 if (!exception)
155 return nullptr;
156
157 auto& list = exception->second;
158 for (auto iter = list.rbegin(); iter != list.rend(); iter++)
159 {
160 DependentString domain(docDomain);
161 if ((*iter)->IsActiveOnDomain(domain, DependentString()))
162 {
163 ElemHideExceptionPtr filter(*iter);
164 return filter.release();
165 }
166 }
167
168 return nullptr;
169 }
170
171 ElemHide_SelectorList* ElemHide::GetUnconditionalSelectors() const
172 {
173 if (!mUnconditionalSelectorsCache)
174 {
175 mUnconditionalSelectorsCache =
176 intrusive_ptr<ElemHide_SelectorList>(new ElemHide_SelectorList(), false);
177 annotate_address(mUnconditionalSelectorsCache.get(), "ElemHide_SelectorList" );
178 for (auto unconditional : mUnconditionalSelectors)
179 {
180 if (!(unconditional.is_deleted() || unconditional.is_invalid()))
181 {
182 auto entry = mFilters.find(unconditional.second);
183 if (entry)
184 mUnconditionalSelectorsCache->push_back(entry->second);
185 }
186 }
187 }
188 return intrusive_ptr<ElemHide_SelectorList>(mUnconditionalSelectorsCache).rele ase();
189 }
190
191 ElemHide_SelectorList* ElemHide::GetSelectorsForDomain(const String& domain,
192 Criteria criteria) const
193 {
194 intrusive_ptr<ElemHide_SelectorList> selectors(new ElemHide_SelectorList());
195 annotate_address(selectors.get(), "ElemHide_SelectorList");
196
197 if (criteria < NO_UNCONDITIONAL)
198 {
199 intrusive_ptr<ElemHide_SelectorList> selector(GetUnconditionalSelectors());
200 selectors->append(*selector);
201 }
202
203 bool specificOnly = criteria >= SPECIFIC_ONLY;
204 StringSet seenFilters;
205 DependentString docDomain(domain);
206
207 DependentString currentDomain(domain);
208 while (true)
209 {
210 if (specificOnly && currentDomain.empty())
211 break;
212
213 auto filters = mFiltersByDomain.find(currentDomain);
214 if (filters)
215 {
216 for (const auto& entry : filters->second)
217 {
218 if (entry.first.is_invalid() || entry.first.is_deleted())
219 continue;
220
221 if (seenFilters.find(entry.first))
222 continue;
223 seenFilters.insert(entry.first);
224
225 auto filter = entry.second;
226 if (filter && !GetException(*filter, docDomain))
227 selectors->push_back(filter);
228 }
229 }
230
231 if (currentDomain.empty())
232 break;
233
234 auto nextDot = currentDomain.find(u'.');
235 currentDomain = nextDot == String::npos ?
236 u""_str : DependentString(currentDomain, nextDot + 1);
237 }
238
239 return selectors.release();
240 }
OLDNEW
« no previous file with comments | « compiled/ElemHide.h ('k') | compiled/Map.h » ('j') | test/elemHide.js » ('J')

Powered by Google App Engine
This is Rietveld