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

Side by Side Diff: lib/requestNotifier.js

Issue 29329490: Issue 3222 - Use WeakMap to store data, remove bug 982561 work-around (Closed)
Patch Set: Removed unnecessary Services.jsm import Created Oct. 29, 2015, 6:56 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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-2015 Eyeo GmbH 3 * Copyright (C) 2006-2015 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
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 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/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 /** 18 /**
19 * @fileOverview Stores Adblock Plus data to be attached to a window. 19 * @fileOverview Stores Adblock Plus data to be attached to a window.
20 */ 20 */
21 21
22 Cu.import("resource://gre/modules/Services.jsm");
23
24 let {Utils} = require("utils"); 22 let {Utils} = require("utils");
25 let {BlockingFilter, WhitelistFilter, ElemHideBase, ElemHideFilter, ElemHideExce ption} = require("filterClasses"); 23 let {BlockingFilter, WhitelistFilter, ElemHideBase, ElemHideFilter, ElemHideExce ption} = require("filterClasses");
26 24
27 let nodeData = new WeakMap(); 25 let nodeData = new WeakMap();
28 let windowStats = new WeakMap(); 26 let windowStats = new WeakMap();
29 let windowSelection = new WeakMap(); 27 let windowSelection = new WeakMap();
30 let requestEntryMaxId = 0; 28 let requestEntryMaxId = 0;
31 29
32 let setEntry, hasEntry, getEntry;
33 // Last issue(Bug 982561) preventing us from using WeakMap fixed for FF version 32
34 if (Services.vc.compare(Utils.platformVersion, "32.0a1") >= 0)
35 {
36 setEntry = (map, key, value) => map.set(key, value);
37 hasEntry = (map, key) => map.has(key);
38 getEntry = (map, key) => map.get(key);
39 }
40 else
41 {
42 // Fall back to user data
43 let dataSeed = Math.random();
44 let nodeDataProp = "abpNodeData" + dataSeed;
45 let windowStatsProp = "abpWindowStats" + dataSeed;
46 let windowSelectionProp = "abpWindowSelection" + dataSeed;
47 let getProp = function(map)
48 {
49 switch (map)
50 {
51 case nodeData:
52 return nodeDataProp;
53 case windowStats:
54 return windowStatsProp;
55 case windowSelection:
56 return windowSelectionProp;
57 default:
58 return null;
59 }
60 };
61
62 setEntry = (map, key, value) => key.setUserData(getProp(map), value, null);
63 hasEntry = (map, key) => key.getUserData(getProp(map));
64 getEntry = (map, key) => key.getUserData(getProp(map)) || undefined;
65 }
66
67 /** 30 /**
68 * List of notifiers in use - these notifiers need to receive notifications on 31 * List of notifiers in use - these notifiers need to receive notifications on
69 * new requests. 32 * new requests.
70 * @type RequestNotifier[] 33 * @type RequestNotifier[]
71 */ 34 */
72 let activeNotifiers = []; 35 let activeNotifiers = [];
73 36
74 /** 37 /**
75 * Creates a notifier object for a particular window. After creation the window 38 * Creates a notifier object for a particular window. After creation the window
76 * will first be scanned for previously saved requests. Once that scan is 39 * will first be scanned for previously saved requests. Once that scan is
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
158 { 121 {
159 let doc = wnd.document; 122 let doc = wnd.document;
160 let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, nul l, false); 123 let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, nul l, false);
161 124
162 let process = function() 125 let process = function()
163 { 126 {
164 if (!this.listener) 127 if (!this.listener)
165 return; 128 return;
166 129
167 let node = walker.currentNode; 130 let node = walker.currentNode;
168 let data = getEntry(nodeData, node); 131 let data = nodeData.get(node);
169 if (typeof data != "undefined") 132 if (typeof data != "undefined")
170 for (let k in data) 133 for (let k in data)
171 this.notifyListener(wnd, node, data[k]); 134 this.notifyListener(wnd, node, data[k]);
172 135
173 if (walker.nextNode()) 136 if (walker.nextNode())
174 Utils.runAsync(process); 137 Utils.runAsync(process);
175 else 138 else
176 { 139 {
177 // Done with the current window, start the scan for its frames 140 // Done with the current window, start the scan for its frames
178 for (let i = 0; i < wnd.frames.length; i++) 141 for (let i = 0; i < wnd.frames.length; i++)
179 this.startScan(wnd.frames[i]); 142 this.startScan(wnd.frames[i]);
180 143
181 this.eventsPosted--; 144 this.eventsPosted--;
182 if (!this.eventsPosted) 145 if (!this.eventsPosted)
183 { 146 {
184 this.scanComplete = true; 147 this.scanComplete = true;
185 this.notifyListener(wnd, null, null); 148 this.notifyListener(wnd, null, null);
186 } 149 }
187 } 150 }
188 }.bind(this); 151 }.bind(this);
189 152
190 // Process each node in a separate event to allow other events to process 153 // Process each node in a separate event to allow other events to process
191 this.eventsPosted++; 154 this.eventsPosted++;
192 Utils.runAsync(process); 155 Utils.runAsync(process);
193 } 156 }
194 }; 157 };
195 158
196 RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection ) 159 RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection )
197 { 160 {
198 setEntry(windowSelection, wnd.document, selection); 161 windowSelection.set(wnd.document, selection);
199 }; 162 };
200 RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/ 163 RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/
201 { 164 {
202 if (hasEntry(windowSelection, wnd.document)) 165 if (windowSelection.has(wnd.document))
203 return getEntry(windowSelection, wnd.document); 166 return windowSelection.get(wnd.document);
204 else 167 else
205 return null; 168 return null;
206 }; 169 };
207 170
208 /** 171 /**
209 * Attaches request data to a DOM node. 172 * Attaches request data to a DOM node.
210 * @param {Node} node node to attach data to 173 * @param {Node} node node to attach data to
211 * @param {Window} topWnd top-level window the node belongs to 174 * @param {Window} topWnd top-level window the node belongs to
212 * @param {String} contentType request type, e.g. "IMAGE" 175 * @param {String} contentType request type, e.g. "IMAGE"
213 * @param {String} docDomain domain of the document that initiated the request 176 * @param {String} docDomain domain of the document that initiated the request
214 * @param {Boolean} thirdParty will be true if a third-party server has been re quested 177 * @param {Boolean} thirdParty will be true if a third-party server has been re quested
215 * @param {String} location the address that has been requested 178 * @param {String} location the address that has been requested
216 * @param {Filter} filter filter applied to the request or null if none 179 * @param {Filter} filter filter applied to the request or null if none
217 */ 180 */
218 RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**St ring*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter) 181 RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**St ring*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter)
219 { 182 {
220 return new RequestEntry(node, topWnd, contentType, docDomain, thirdParty, loca tion, filter); 183 return new RequestEntry(node, topWnd, contentType, docDomain, thirdParty, loca tion, filter);
221 } 184 }
222 185
223 /** 186 /**
224 * Retrieves the statistics for a window. 187 * Retrieves the statistics for a window.
225 * @result {Object} Object with the properties items, blocked, whitelisted, hidd en, filters containing statistics for the window (might be null) 188 * @result {Object} Object with the properties items, blocked, whitelisted, hidd en, filters containing statistics for the window (might be null)
226 */ 189 */
227 RequestNotifier.getWindowStatistics = function(/**Window*/ wnd) 190 RequestNotifier.getWindowStatistics = function(/**Window*/ wnd)
228 { 191 {
229 if (hasEntry(windowStats, wnd.document)) 192 if (windowStats.has(wnd.document))
230 return getEntry(windowStats, wnd.document); 193 return windowStats.get(wnd.document);
231 else 194 else
232 return null; 195 return null;
233 } 196 }
234 197
235 /** 198 /**
236 * Retrieves the request entry associated with a DOM node. 199 * Retrieves the request entry associated with a DOM node.
237 * @param {Node} node 200 * @param {Node} node
238 * @param {Boolean} noParent if missing or false, the search will extend to the parent nodes until one is found that has data associated with it 201 * @param {Boolean} noParent if missing or false, the search will extend to the parent nodes until one is found that has data associated with it
239 * @param {Integer} [type] request type to be looking for 202 * @param {Integer} [type] request type to be looking for
240 * @param {String} [location] request location to be looking for 203 * @param {String} [location] request location to be looking for
241 * @result {[Node, RequestEntry]} 204 * @result {[Node, RequestEntry]}
242 * @static 205 * @static
243 */ 206 */
244 RequestNotifier.getDataForNode = function(node, noParent, type, location) 207 RequestNotifier.getDataForNode = function(node, noParent, type, location)
245 { 208 {
246 while (node) 209 while (node)
247 { 210 {
248 let data = getEntry(nodeData, node); 211 let data = nodeData.get(node);
249 if (typeof data != "undefined") 212 if (typeof data != "undefined")
250 { 213 {
251 let entry = null; 214 let entry = null;
252 // Look for matching entry 215 // Look for matching entry
253 for (let k in data) 216 for (let k in data)
254 { 217 {
255 if ((!entry || entry.id < data[k].id) && 218 if ((!entry || entry.id < data[k].id) &&
256 (typeof type == "undefined" || data[k].type == type) && 219 (typeof type == "undefined" || data[k].type == type) &&
257 (typeof location == "undefined" || data[k].location == location)) 220 (typeof location == "undefined" || data[k].location == location))
258 { 221 {
(...skipping 24 matching lines...) Expand all
283 this.type = contentType; 246 this.type = contentType;
284 this.docDomain = docDomain; 247 this.docDomain = docDomain;
285 this.thirdParty = thirdParty; 248 this.thirdParty = thirdParty;
286 this.location = location; 249 this.location = location;
287 this.filter = filter; 250 this.filter = filter;
288 this.id = ++requestEntryMaxId; 251 this.id = ++requestEntryMaxId;
289 252
290 this.attachToNode(node); 253 this.attachToNode(node);
291 254
292 // Update window statistics 255 // Update window statistics
293 if (!hasEntry(windowStats, topWnd.document)) 256 if (!windowStats.has(topWnd.document))
294 { 257 {
295 setEntry(windowStats, topWnd.document, { 258 windowStats.set(topWnd.document, {
296 items: 0, 259 items: 0,
297 hidden: 0, 260 hidden: 0,
298 blocked: 0, 261 blocked: 0,
299 whitelisted: 0, 262 whitelisted: 0,
300 filters: {} 263 filters: {}
301 }); 264 });
302 } 265 }
303 266
304 let stats = getEntry(windowStats, topWnd.document); 267 let stats = windowStats.get(topWnd.document);
305 if (!filter || !(filter instanceof ElemHideBase)) 268 if (!filter || !(filter instanceof ElemHideBase))
306 stats.items++; 269 stats.items++;
307 if (filter) 270 if (filter)
308 { 271 {
309 if (filter instanceof BlockingFilter) 272 if (filter instanceof BlockingFilter)
310 stats.blocked++; 273 stats.blocked++;
311 else if (filter instanceof WhitelistFilter || filter instanceof ElemHideExce ption) 274 else if (filter instanceof WhitelistFilter || filter instanceof ElemHideExce ption)
312 stats.whitelisted++; 275 stats.whitelisted++;
313 else if (filter instanceof ElemHideFilter) 276 else if (filter instanceof ElemHideFilter)
314 stats.hidden++; 277 stats.hidden++;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 * Filter that was applied to this request (if any) 318 * Filter that was applied to this request (if any)
356 * @type Filter 319 * @type Filter
357 */ 320 */
358 filter: null, 321 filter: null,
359 322
360 /** 323 /**
361 * Attaches this request object to a DOM node. 324 * Attaches this request object to a DOM node.
362 */ 325 */
363 attachToNode: function(/**Node*/ node) 326 attachToNode: function(/**Node*/ node)
364 { 327 {
365 let existingData = getEntry(nodeData, node); 328 let existingData = nodeData.get(node);
366 if (typeof existingData == "undefined") 329 if (typeof existingData == "undefined")
367 { 330 {
368 existingData = {}; 331 existingData = {};
369 setEntry(nodeData, node, existingData); 332 nodeData.set(node, existingData);
370 } 333 }
371 334
372 // Add this request to the node data 335 // Add this request to the node data
373 existingData[this.type + " " + this.location] = this; 336 existingData[this.type + " " + this.location] = this;
374 } 337 }
375 }; 338 };
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld