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

Delta Between Two Patch Sets: lib/requestNotifier.js

Issue 29329450: Issue 3208 - Don`t use numerical content types outside nsIContentPolicy.shouldLoad (Closed)
Left Patch Set: Created Oct. 28, 2015, 2:42 p.m.
Right Patch Set: Removed unrelated change Created Nov. 4, 2015, 9:27 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « lib/objectTabs.js ('k') | lib/ui.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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();
28 let requestNotifierMaxId = 0;
30 let requestEntryMaxId = 0; 29 let requestEntryMaxId = 0;
31 30
32 let setEntry, hasEntry, getEntry; 31 /**
33 // Last issue(Bug 982561) preventing us from using WeakMap fixed for FF version 32 32 * Active RequestNotifier instances by their ID
34 if (Services.vc.compare(Utils.platformVersion, "32.0a1") >= 0) 33 * @type Map
35 { 34 */
36 setEntry = (map, key, value) => map.set(key, value); 35 let notifiers = new Map();
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 /**
68 * List of notifiers in use - these notifiers need to receive notifications on
69 * new requests.
70 * @type RequestNotifier[]
71 */
72 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
77 * complete only new requests for this window will be reported. 40 * complete only new requests for this window will be reported.
78 * @param {Window} wnd window to attach the notifier to 41 * @param {Window} wnd window to attach the notifier to
79 * @param {Function} listener listener to be called whenever a new request is f ound 42 * @param {Function} listener listener to be called whenever a new request is f ound
80 * @param {Object} [listenerObj] "this" pointer to be used when calling the lis tener 43 * @param {Object} [listenerObj] "this" pointer to be used when calling the lis tener
81 */ 44 */
82 function RequestNotifier(wnd, listener, listenerObj) 45 function RequestNotifier(wnd, listener, listenerObj)
83 { 46 {
84 this.window = wnd; 47 this.window = wnd;
85 this.listener = listener; 48 this.listener = listener;
86 this.listenerObj = listenerObj || null; 49 this.listenerObj = listenerObj || null;
87 activeNotifiers.push(this); 50 this.id = ++requestNotifierMaxId;
51 notifiers.set(this.id, this);
88 if (wnd) 52 if (wnd)
89 this.startScan(wnd); 53 this.startScan(wnd);
90 else 54 else
91 this.scanComplete = true; 55 this.scanComplete = true;
92 } 56 }
93 exports.RequestNotifier = RequestNotifier; 57 exports.RequestNotifier = RequestNotifier;
94 58
95 RequestNotifier.prototype = 59 RequestNotifier.prototype =
96 { 60 {
97 /** 61 /**
62 * The unique ID of this notifier.
63 * @type Integer
64 */
65 id: null,
66
67 /**
98 * The window this notifier is associated with. 68 * The window this notifier is associated with.
99 * @type Window 69 * @type Window
100 */ 70 */
101 window: null, 71 window: null,
102 72
103 /** 73 /**
104 * The listener to be called when a new request is found. 74 * The listener to be called when a new request is found.
105 * @type Function 75 * @type Function
106 */ 76 */
107 listener: null, 77 listener: null,
(...skipping 13 matching lines...) Expand all
121 /** 91 /**
122 * Shuts down the notifier once it is no longer used. The listener 92 * Shuts down the notifier once it is no longer used. The listener
123 * will no longer be called after that. 93 * will no longer be called after that.
124 */ 94 */
125 shutdown: function() 95 shutdown: function()
126 { 96 {
127 delete this.window; 97 delete this.window;
128 delete this.listener; 98 delete this.listener;
129 delete this.listenerObj; 99 delete this.listenerObj;
130 100
131 for (let i = activeNotifiers.length - 1; i >= 0; i--) 101 notifiers.delete(this.id);
132 if (activeNotifiers[i] == this)
133 activeNotifiers.splice(i, 1);
134 }, 102 },
135 103
136 /** 104 /**
137 * Notifies listener about a new request. 105 * Notifies listener about a new request.
138 * @param {Window} wnd 106 * @param {Window} wnd
139 * @param {Node} node 107 * @param {Node} node
140 * @param {RequestEntry} entry 108 * @param {RequestEntry} entry
141 */ 109 */
142 notifyListener: function(wnd, node, entry) 110 notifyListener: function(wnd, node, entry)
143 { 111 {
(...skipping 14 matching lines...) Expand all
158 { 126 {
159 let doc = wnd.document; 127 let doc = wnd.document;
160 let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, nul l, false); 128 let walker = doc.createTreeWalker(doc, Ci.nsIDOMNodeFilter.SHOW_ELEMENT, nul l, false);
161 129
162 let process = function() 130 let process = function()
163 { 131 {
164 if (!this.listener) 132 if (!this.listener)
165 return; 133 return;
166 134
167 let node = walker.currentNode; 135 let node = walker.currentNode;
168 let data = getEntry(nodeData, node); 136 let data = nodeData.get(node);
169 if (typeof data != "undefined") 137 if (typeof data != "undefined")
170 for (let k in data) 138 for (let k in data)
171 this.notifyListener(wnd, node, data[k]); 139 this.notifyListener(wnd, node, data[k]);
172 140
173 if (walker.nextNode()) 141 if (walker.nextNode())
174 Utils.runAsync(process); 142 Utils.runAsync(process);
175 else 143 else
176 { 144 {
177 // Done with the current window, start the scan for its frames 145 // Done with the current window, start the scan for its frames
178 for (let i = 0; i < wnd.frames.length; i++) 146 for (let i = 0; i < wnd.frames.length; i++)
179 this.startScan(wnd.frames[i]); 147 this.startScan(wnd.frames[i]);
180 148
181 this.eventsPosted--; 149 this.eventsPosted--;
182 if (!this.eventsPosted) 150 if (!this.eventsPosted)
183 { 151 {
184 this.scanComplete = true; 152 this.scanComplete = true;
185 this.notifyListener(wnd, null, null); 153 this.notifyListener(wnd, null, null);
186 } 154 }
187 } 155 }
188 }.bind(this); 156 }.bind(this);
189 157
190 // Process each node in a separate event to allow other events to process 158 // Process each node in a separate event to allow other events to process
191 this.eventsPosted++; 159 this.eventsPosted++;
192 Utils.runAsync(process); 160 Utils.runAsync(process);
193 } 161 }
194 }; 162 };
195 163
196 RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection ) 164 RequestNotifier.storeSelection = function(/**Window*/ wnd, /**String*/ selection )
197 { 165 {
198 setEntry(windowSelection, wnd.document, selection); 166 windowSelection.set(wnd.document, selection);
199 }; 167 };
200 RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/ 168 RequestNotifier.getSelection = function(/**Window*/ wnd) /**String*/
201 { 169 {
202 if (hasEntry(windowSelection, wnd.document)) 170 if (windowSelection.has(wnd.document))
203 return getEntry(windowSelection, wnd.document); 171 return windowSelection.get(wnd.document);
204 else 172 else
205 return null; 173 return null;
206 }; 174 };
207 175
208 /** 176 /**
209 * Attaches request data to a DOM node. 177 * Attaches request data to a DOM node.
210 * @param {Node} node node to attach data to 178 * @param {Node} node node to attach data to
211 * @param {Window} topWnd top-level window the node belongs to 179 * @param {Window} topWnd top-level window the node belongs to
212 * @param {String} contentType request type, e.g. "IMAGE" 180 * @param {String} contentType request type, e.g. "IMAGE"
213 * @param {String} docDomain domain of the document that initiated the request 181 * @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 182 * @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 183 * @param {String} location the address that has been requested
216 * @param {Filter} filter filter applied to the request or null if none 184 * @param {Filter} filter filter applied to the request or null if none
217 */ 185 */
218 RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**St ring*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter) 186 RequestNotifier.addNodeData = function(/**Node*/ node, /**Window*/ topWnd, /**St ring*/ contentType, /**String*/ docDomain, /**Boolean*/ thirdParty, /**String*/ location, /**Filter*/ filter)
219 { 187 {
220 return new RequestEntry(node, topWnd, contentType, docDomain, thirdParty, loca tion, filter); 188 return new RequestEntry(node, topWnd, contentType, docDomain, thirdParty, loca tion, filter);
221 } 189 }
222 190
223 /** 191 /**
224 * Retrieves the statistics for a window. 192 * 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) 193 * @result {Object} Object with the properties items, blocked, whitelisted, hidd en, filters containing statistics for the window (might be null)
226 */ 194 */
227 RequestNotifier.getWindowStatistics = function(/**Window*/ wnd) 195 RequestNotifier.getWindowStatistics = function(/**Window*/ wnd)
228 { 196 {
229 if (hasEntry(windowStats, wnd.document)) 197 if (windowStats.has(wnd.document))
230 return getEntry(windowStats, wnd.document); 198 return windowStats.get(wnd.document);
231 else 199 else
232 return null; 200 return null;
233 } 201 }
234 202
235 /** 203 /**
236 * Retrieves the request entry associated with a DOM node. 204 * Retrieves the request entry associated with a DOM node.
237 * @param {Node} node 205 * @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 206 * @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 207 * @param {Integer} [type] request type to be looking for
240 * @param {String} [location] request location to be looking for 208 * @param {String} [location] request location to be looking for
241 * @result {[Node, RequestEntry]} 209 * @result {[Node, RequestEntry]}
242 * @static 210 * @static
243 */ 211 */
244 RequestNotifier.getDataForNode = function(node, noParent, type, location) 212 RequestNotifier.getDataForNode = function(node, noParent, type, location)
245 { 213 {
246 while (node) 214 while (node)
247 { 215 {
248 let data = getEntry(nodeData, node); 216 let data = nodeData.get(node);
249 if (typeof data != "undefined") 217 if (typeof data != "undefined")
250 { 218 {
251 let entry = null; 219 let entry = null;
252 // Look for matching entry 220 // Look for matching entry
253 for (let k in data) 221 for (let k in data)
254 { 222 {
255 if ((!entry || entry.id < data[k].id) && 223 if ((!entry || entry.id < data[k].id) &&
256 (typeof type == "undefined" || data[k].type == type) && 224 (typeof type == "undefined" || data[k].type == type) &&
257 (typeof location == "undefined" || data[k].location == location)) 225 (typeof location == "undefined" || data[k].location == location))
258 { 226 {
(...skipping 24 matching lines...) Expand all
283 this.type = contentType; 251 this.type = contentType;
284 this.docDomain = docDomain; 252 this.docDomain = docDomain;
285 this.thirdParty = thirdParty; 253 this.thirdParty = thirdParty;
286 this.location = location; 254 this.location = location;
287 this.filter = filter; 255 this.filter = filter;
288 this.id = ++requestEntryMaxId; 256 this.id = ++requestEntryMaxId;
289 257
290 this.attachToNode(node); 258 this.attachToNode(node);
291 259
292 // Update window statistics 260 // Update window statistics
293 if (!hasEntry(windowStats, topWnd.document)) 261 if (!windowStats.has(topWnd.document))
294 { 262 {
295 setEntry(windowStats, topWnd.document, { 263 windowStats.set(topWnd.document, {
296 items: 0, 264 items: 0,
297 hidden: 0, 265 hidden: 0,
298 blocked: 0, 266 blocked: 0,
299 whitelisted: 0, 267 whitelisted: 0,
300 filters: {} 268 filters: {}
301 }); 269 });
302 } 270 }
303 271
304 let stats = getEntry(windowStats, topWnd.document); 272 let stats = windowStats.get(topWnd.document);
305 if (!filter || !(filter instanceof ElemHideBase)) 273 if (!filter || !(filter instanceof ElemHideBase))
306 stats.items++; 274 stats.items++;
307 if (filter) 275 if (filter)
308 { 276 {
309 if (filter instanceof BlockingFilter) 277 if (filter instanceof BlockingFilter)
310 stats.blocked++; 278 stats.blocked++;
311 else if (filter instanceof WhitelistFilter || filter instanceof ElemHideExce ption) 279 else if (filter instanceof WhitelistFilter || filter instanceof ElemHideExce ption)
312 stats.whitelisted++; 280 stats.whitelisted++;
313 else if (filter instanceof ElemHideFilter) 281 else if (filter instanceof ElemHideFilter)
314 stats.hidden++; 282 stats.hidden++;
315 283
316 if (filter.text in stats.filters) 284 if (filter.text in stats.filters)
317 stats.filters[filter.text]++; 285 stats.filters[filter.text]++;
318 else 286 else
319 stats.filters[filter.text] = 1; 287 stats.filters[filter.text] = 1;
320 } 288 }
321 289
322 // Notify listeners 290 // Notify listeners
323 for (let notifier of activeNotifiers) 291 for (let notifier of notifiers.values())
324 if (!notifier.window || notifier.window == topWnd) 292 if (!notifier.window || notifier.window == topWnd)
325 notifier.notifyListener(topWnd, node, this); 293 notifier.notifyListener(topWnd, node, this);
326 } 294 }
327 RequestEntry.prototype = 295 RequestEntry.prototype =
328 { 296 {
329 /** 297 /**
330 * id of request (used to determine last entry attached to a node) 298 * id of request (used to determine last entry attached to a node)
331 * @type integer 299 * @type integer
332 */ 300 */
333 id: 0, 301 id: 0,
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 get localizedDescr() 339 get localizedDescr()
372 { 340 {
373 return require("contentPolicy").Policy.localizedDescr.get(this.type); 341 return require("contentPolicy").Policy.localizedDescr.get(this.type);
374 }, 342 },
375 343
376 /** 344 /**
377 * Attaches this request object to a DOM node. 345 * Attaches this request object to a DOM node.
378 */ 346 */
379 attachToNode: function(/**Node*/ node) 347 attachToNode: function(/**Node*/ node)
380 { 348 {
381 let existingData = getEntry(nodeData, node); 349 let existingData = nodeData.get(node);
382 if (typeof existingData == "undefined") 350 if (typeof existingData == "undefined")
383 { 351 {
384 existingData = {}; 352 existingData = {};
385 setEntry(nodeData, node, existingData); 353 nodeData.set(node, existingData);
386 } 354 }
387 355
388 // Add this request to the node data 356 // Add this request to the node data
389 existingData[this.type + " " + this.location] = this; 357 existingData[this.type + " " + this.location] = this;
390 } 358 }
391 }; 359 };
LEFTRIGHT

Powered by Google App Engine
This is Rietveld