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

Side by Side Diff: lib/filterListener.js

Issue 29335650: Issue 2595 - Use the core code from adblockpluscore (Closed)
Patch Set: Created Feb. 4, 2016, 6:35 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « lib/filterClasses.js ('k') | lib/filterNotifier.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 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 /**
19 * @fileOverview Component synchronizing filter storage with Matcher instances a nd ElemHide.
20 */
21
22 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
23 Cu.import("resource://gre/modules/Services.jsm");
24
25 let {FilterStorage} = require("filterStorage");
26 let {FilterNotifier} = require("filterNotifier");
27 let {ElemHide} = require("elemHide");
28 let {CSSRules} = require("cssRules");
29 let {defaultMatcher} = require("matcher");
30 let {ActiveFilter, RegExpFilter, ElemHideBase, CSSPropertyFilter} =
31 require("filterClasses");
32 let {Prefs} = require("prefs");
33
34 /**
35 * Value of the FilterListener.batchMode property.
36 * @type Boolean
37 */
38 let batchMode = false;
39
40 /**
41 * Increases on filter changes, filters will be saved if it exceeds 1.
42 * @type Integer
43 */
44 let isDirty = 0;
45
46 /**
47 * This object can be used to change properties of the filter change listeners.
48 * @class
49 */
50 let FilterListener =
51 {
52 /**
53 * Set to true when executing many changes, changes will only be fully applied after this variable is set to false again.
54 * @type Boolean
55 */
56 get batchMode()
57 {
58 return batchMode;
59 },
60 set batchMode(value)
61 {
62 batchMode = value;
63 flushElemHide();
64 },
65
66 /**
67 * Increases "dirty factor" of the filters and calls FilterStorage.saveToDisk( )
68 * if it becomes 1 or more. Save is executed delayed to prevent multiple
69 * subsequent calls. If the parameter is 0 it forces saving filters if any
70 * changes were recorded after the previous save.
71 */
72 setDirty: function(/**Integer*/ factor)
73 {
74 if (factor == 0 && isDirty > 0)
75 isDirty = 1;
76 else
77 isDirty += factor;
78 if (isDirty >= 1)
79 {
80 isDirty = 0;
81 FilterStorage.saveToDisk();
82 }
83 }
84 };
85
86 /**
87 * Observer listening to history purge actions.
88 * @class
89 */
90 let HistoryPurgeObserver =
91 {
92 observe: function(subject, topic, data)
93 {
94 if (topic == "browser:purge-session-history" && Prefs.clearStatsOnHistoryPur ge)
95 {
96 FilterStorage.resetHitCounts();
97 FilterListener.setDirty(0); // Force saving to disk
98
99 Prefs.recentReports = [];
100 }
101 },
102 QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference, Ci.nsIObse rver])
103 };
104
105 /**
106 * Initializes filter listener on startup, registers the necessary hooks.
107 */
108 function init()
109 {
110 FilterNotifier.addListener(function(action, item, newValue, oldValue)
111 {
112 let match = /^(\w+)\.(.*)/.exec(action);
113 if (match && match[1] == "filter")
114 onFilterChange(match[2], item, newValue, oldValue);
115 else if (match && match[1] == "subscription")
116 onSubscriptionChange(match[2], item, newValue, oldValue);
117 else
118 onGenericChange(action, item);
119 });
120
121 if ("nsIStyleSheetService" in Ci)
122 ElemHide.init();
123 else
124 flushElemHide = function() {}; // No global stylesheet in Chrome & Co.
125 FilterStorage.loadFromDisk();
126
127 Services.obs.addObserver(HistoryPurgeObserver, "browser:purge-session-history" , true);
128 onShutdown.add(function()
129 {
130 Services.obs.removeObserver(HistoryPurgeObserver, "browser:purge-session-his tory");
131 });
132 }
133 init();
134
135 /**
136 * Calls ElemHide.apply() if necessary.
137 */
138 function flushElemHide()
139 {
140 if (!batchMode && ElemHide.isDirty)
141 ElemHide.apply();
142 }
143
144 /**
145 * Notifies Matcher instances or ElemHide object about a new filter
146 * if necessary.
147 * @param {Filter} filter filter that has been added
148 */
149 function addFilter(filter)
150 {
151 if (!(filter instanceof ActiveFilter) || filter.disabled)
152 return;
153
154 let hasEnabled = false;
155 for (let i = 0; i < filter.subscriptions.length; i++)
156 if (!filter.subscriptions[i].disabled)
157 hasEnabled = true;
158 if (!hasEnabled)
159 return;
160
161 if (filter instanceof RegExpFilter)
162 defaultMatcher.add(filter);
163 else if (filter instanceof ElemHideBase)
164 {
165 if (filter instanceof CSSPropertyFilter)
166 CSSRules.add(filter);
167 else
168 ElemHide.add(filter);
169 }
170 }
171
172 /**
173 * Notifies Matcher instances or ElemHide object about removal of a filter
174 * if necessary.
175 * @param {Filter} filter filter that has been removed
176 */
177 function removeFilter(filter)
178 {
179 if (!(filter instanceof ActiveFilter))
180 return;
181
182 if (!filter.disabled)
183 {
184 let hasEnabled = false;
185 for (let i = 0; i < filter.subscriptions.length; i++)
186 if (!filter.subscriptions[i].disabled)
187 hasEnabled = true;
188 if (hasEnabled)
189 return;
190 }
191
192 if (filter instanceof RegExpFilter)
193 defaultMatcher.remove(filter);
194 else if (filter instanceof ElemHideBase)
195 {
196 if (filter instanceof CSSPropertyFilter)
197 CSSRules.remove(filter);
198 else
199 ElemHide.remove(filter);
200 }
201 }
202
203 /**
204 * Subscription change listener
205 */
206 function onSubscriptionChange(action, subscription, newValue, oldValue)
207 {
208 FilterListener.setDirty(1);
209
210 if (action != "added" && action != "removed" && action != "disabled" && action != "updated")
211 return;
212
213 if (action != "removed" && !(subscription.url in FilterStorage.knownSubscripti ons))
214 {
215 // Ignore updates for subscriptions not in the list
216 return;
217 }
218
219 if ((action == "added" || action == "removed" || action == "updated") && subsc ription.disabled)
220 {
221 // Ignore adding/removing/updating of disabled subscriptions
222 return;
223 }
224
225 if (action == "added" || action == "removed" || action == "disabled")
226 {
227 let method = (action == "added" || (action == "disabled" && newValue == fals e) ? addFilter : removeFilter);
228 if (subscription.filters)
229 subscription.filters.forEach(method);
230 }
231 else if (action == "updated")
232 {
233 subscription.oldFilters.forEach(removeFilter);
234 subscription.filters.forEach(addFilter);
235 }
236
237 flushElemHide();
238 }
239
240 /**
241 * Filter change listener
242 */
243 function onFilterChange(action, filter, newValue, oldValue)
244 {
245 if (action == "hitCount" && newValue == 0)
246 {
247 // Filter hits are being reset, make sure these changes are saved.
248 FilterListener.setDirty(0);
249 }
250 else if (action == "hitCount" || action == "lastHit")
251 FilterListener.setDirty(0.002);
252 else
253 FilterListener.setDirty(1);
254
255 if (action != "added" && action != "removed" && action != "disabled")
256 return;
257
258 if ((action == "added" || action == "removed") && filter.disabled)
259 {
260 // Ignore adding/removing of disabled filters
261 return;
262 }
263
264 if (action == "added" || (action == "disabled" && newValue == false))
265 addFilter(filter);
266 else
267 removeFilter(filter);
268 flushElemHide();
269 }
270
271 /**
272 * Generic notification listener
273 */
274 function onGenericChange(action)
275 {
276 if (action == "load")
277 {
278 isDirty = 0;
279
280 defaultMatcher.clear();
281 ElemHide.clear();
282 CSSRules.clear();
283 for (let subscription of FilterStorage.subscriptions)
284 if (!subscription.disabled)
285 subscription.filters.forEach(addFilter);
286 flushElemHide();
287 }
288 else if (action == "save")
289 isDirty = 0;
290 }
OLDNEW
« no previous file with comments | « lib/filterClasses.js ('k') | lib/filterNotifier.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld