OLD | NEW |
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-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 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 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); | 21 let {Services} = Cu.import("resource://gre/modules/Services.jsm", {}); |
22 | 22 |
| 23 let {port} = require("messaging"); |
23 let {Utils} = require("utils"); | 24 let {Utils} = require("utils"); |
24 let {Flasher} = require("child/flasher"); | 25 let {Flasher} = require("child/flasher"); |
25 | 26 |
26 let nodeData = new WeakMap(); | 27 let nodeData = new WeakMap(); |
27 let windowStats = new WeakMap(); | 28 let windowStats = new WeakMap(); |
28 let windowData = new WeakMap(); | 29 let windowData = new WeakMap(); |
29 let requestEntryMaxId = 0; | 30 let requestEntryMaxId = 0; |
30 | 31 |
31 /** | 32 /** |
32 * Active RequestNotifier instances by their ID | 33 * Active RequestNotifier instances by their ID |
33 * @type Map.<number,RequestNotifier> | 34 * @type Map.<number,RequestNotifier> |
34 */ | 35 */ |
35 let notifiers = new Map(); | 36 let notifiers = new Map(); |
36 | 37 |
37 addMessageListener("AdblockPlus:StartWindowScan", onStartScan); | 38 port.on("startWindowScan", onStartScan); |
38 addMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown); | 39 port.on("shutdownNotifier", onNotifierShutdown); |
39 addMessageListener("AdblockPlus:FlashNodes", onFlashNodes); | 40 port.on("flashNodes", onFlashNodes); |
40 addMessageListener("AdblockPlus:RetrieveNodeSize", onRetrieveNodeSize); | 41 port.on("retrieveNodeSize", onRetrieveNodeSize); |
41 addMessageListener("AdblockPlus:StoreNodesForEntries", onStoreNodes); | 42 port.on("storeNodesForEntries", onStoreNodes); |
42 addMessageListener("AdblockPlus:RetrieveWindowStats", onRetrieveWindowStats); | 43 port.on("retrieveWindowStats", onRetrieveWindowStats); |
43 addMessageListener("AdblockPlus:StoreWindowData", onStoreWindowData); | 44 port.on("storeWindowData", onStoreWindowData); |
44 addMessageListener("AdblockPlus:RetrieveWindowData", onRetrieveWindowData); | 45 port.on("retrieveWindowData", onRetrieveWindowData); |
45 | 46 |
46 onShutdown.add(() => { | 47 function onStartScan({notifierID, outerWindowID}) |
47 removeMessageListener("AdblockPlus:StartWindowScan", onStartScan); | |
48 removeMessageListener("AdblockPlus:ShutdownNotifier", onNotifierShutdown); | |
49 removeMessageListener("AdblockPlus:FlashNodes", onFlashNodes); | |
50 removeMessageListener("AdblockPlus:RetrieveNodeSize", onRetrieveNodeSize); | |
51 removeMessageListener("AdblockPlus:StoreNodesForEntries", onStoreNodes); | |
52 removeMessageListener("AdblockPlus:RetrieveWindowStats", onRetrieveWindowStats
); | |
53 removeMessageListener("AdblockPlus:StoreWindowData", onStoreWindowData); | |
54 removeMessageListener("AdblockPlus:RetrieveWindowData", onRetrieveWindowData); | |
55 }); | |
56 | |
57 function onStartScan(message) | |
58 { | 48 { |
59 let {notifierID, outerWindowID} = message.data; | |
60 let window = Services.wm.getOuterWindowWithId(outerWindowID); | 49 let window = Services.wm.getOuterWindowWithId(outerWindowID); |
61 if (window) | 50 if (window) |
62 new RequestNotifier(window, notifierID); | 51 new RequestNotifier(window, notifierID); |
63 } | 52 } |
64 | 53 |
65 function onNotifierShutdown(message) | 54 function onNotifierShutdown(notifierID) |
66 { | 55 { |
67 let notifier = notifiers.get(message.data); | 56 let notifier = notifiers.get(notifierID); |
68 if (notifier) | 57 if (notifier) |
69 notifier.shutdown(); | 58 notifier.shutdown(); |
70 } | 59 } |
71 | 60 |
72 function onFlashNodes(message) | 61 function onFlashNodes({notifierID, requests, scrollToItem}) |
73 { | 62 { |
74 let {notifierID, requests, scrollToItem} = message.data; | |
75 let notifier = notifiers.get(notifierID); | 63 let notifier = notifiers.get(notifierID); |
76 if (notifier) | 64 if (notifier) |
77 notifier.flashNodes(requests, scrollToItem); | 65 notifier.flashNodes(requests, scrollToItem); |
78 } | 66 } |
79 | 67 |
80 function onRetrieveNodeSize(message) | 68 function onRetrieveNodeSize({notifierID, requests}) |
81 { | 69 { |
82 let {notifierID, responseID, requests} = message.data; | |
83 let notifier = notifiers.get(notifierID); | 70 let notifier = notifiers.get(notifierID); |
84 if (notifier) | 71 if (notifier) |
85 notifier.retrieveNodeSize(requests, responseID); | 72 return notifier.retrieveNodeSize(requests); |
86 } | 73 } |
87 | 74 |
88 function onStoreNodes(message) | 75 function onStoreNodes({notifierID, requests}) |
89 { | 76 { |
90 let {notifierID, responseID, requests} = message.data; | |
91 let notifier = notifiers.get(notifierID); | 77 let notifier = notifiers.get(notifierID); |
92 if (notifier) | 78 if (notifier) |
93 notifier.storeNodesForEntries(requests, responseID); | 79 return notifier.storeNodesForEntries(requests); |
94 } | 80 } |
95 | 81 |
96 function onRetrieveWindowStats(message) | 82 function onRetrieveWindowStats(outerWindowID) |
97 { | 83 { |
98 let {responseID, outerWindowID} = message.data; | |
99 let window = Services.wm.getOuterWindowWithId(outerWindowID); | 84 let window = Services.wm.getOuterWindowWithId(outerWindowID); |
100 if (window) | 85 if (window) |
101 { | 86 return RequestNotifier.getWindowStatistics(window); |
102 let stats = RequestNotifier.getWindowStatistics(window); | |
103 sendAsyncMessage("AdblockPlus:RetrieveWindowStatsResponse", { | |
104 responseID, | |
105 stats | |
106 }); | |
107 } | |
108 } | 87 } |
109 | 88 |
110 function onStoreWindowData(message) | 89 function onStoreWindowData({outerWindowID, data}) |
111 { | 90 { |
112 let {outerWindowID, data} = message.data; | |
113 let window = Services.wm.getOuterWindowWithId(outerWindowID); | 91 let window = Services.wm.getOuterWindowWithId(outerWindowID); |
114 if (window) | 92 if (window) |
115 windowData.set(window.document, data); | 93 windowData.set(window.document, data); |
116 }; | 94 }; |
117 | 95 |
118 function onRetrieveWindowData(message) | 96 function onRetrieveWindowData(outerWindowID) |
119 { | 97 { |
120 let {responseID, outerWindowID} = message.data; | |
121 let window = Services.wm.getOuterWindowWithId(outerWindowID); | 98 let window = Services.wm.getOuterWindowWithId(outerWindowID); |
122 if (window) | 99 if (window) |
123 { | 100 return windowData.get(window.document) || null; |
124 let data = windowData.get(window.document) || null; | |
125 sendAsyncMessage("AdblockPlus:RetrieveWindowDataResponse", { | |
126 responseID, | |
127 data | |
128 }); | |
129 } | |
130 }; | 101 }; |
131 | 102 |
132 /** | 103 /** |
133 * Creates a notifier object for a particular window. After creation the window | 104 * Creates a notifier object for a particular window. After creation the window |
134 * will first be scanned for previously saved requests. Once that scan is | 105 * will first be scanned for previously saved requests. Once that scan is |
135 * complete only new requests for this window will be reported. | 106 * complete only new requests for this window will be reported. |
136 * @param {Window} window window to attach the notifier to | 107 * @param {Window} window window to attach the notifier to |
137 * @param {Integer} notifierID Parent notifier ID to be messaged | 108 * @param {Integer} notifierID Parent notifier ID to be messaged |
138 */ | 109 */ |
139 function RequestNotifier(window, notifierID) | 110 function RequestNotifier(window, notifierID) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 | 151 |
181 /** | 152 /** |
182 * Notifies the parent about a new request. | 153 * Notifies the parent about a new request. |
183 * @param {Node} node DOM node that the request is associated with | 154 * @param {Node} node DOM node that the request is associated with |
184 * @param {Object} entry | 155 * @param {Object} entry |
185 */ | 156 */ |
186 notifyListener: function(node, entry) | 157 notifyListener: function(node, entry) |
187 { | 158 { |
188 if (this.nodes) | 159 if (this.nodes) |
189 this.nodes.set(entry.id, node); | 160 this.nodes.set(entry.id, node); |
190 sendAsyncMessage("AdblockPlus:FoundNodeData", { | 161 port.emit("foundNodeData", { |
191 notifierID: this.id, | 162 notifierID: this.id, |
192 data: entry | 163 data: entry |
193 }); | 164 }); |
194 }, | 165 }, |
195 | 166 |
196 onComplete: function() | 167 onComplete: function() |
197 { | 168 { |
198 sendAsyncMessage("AdblockPlus:ScanComplete", this.id); | 169 port.emit("scanComplete", this.id); |
199 }, | 170 }, |
200 | 171 |
201 /** | 172 /** |
202 * Number of currently posted scan events (will be 0 when the scan finishes | 173 * Number of currently posted scan events (will be 0 when the scan finishes |
203 * running). | 174 * running). |
204 */ | 175 */ |
205 eventsPosted: 0, | 176 eventsPosted: 0, |
206 | 177 |
207 /** | 178 /** |
208 * Starts the initial scan of the window (will recurse into frames). | 179 * Starts the initial scan of the window (will recurse into frames). |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
277 * Stops flashing nodes after a previous flashNodes() call. | 248 * Stops flashing nodes after a previous flashNodes() call. |
278 */ | 249 */ |
279 stopFlashing: function() | 250 stopFlashing: function() |
280 { | 251 { |
281 if (this.flasher) | 252 if (this.flasher) |
282 this.flasher.stop(); | 253 this.flasher.stop(); |
283 this.flasher = null; | 254 this.flasher = null; |
284 }, | 255 }, |
285 | 256 |
286 /** | 257 /** |
287 * Attempts to calculate the size of the nodes associated with the requests, | 258 * Attempts to calculate the size of the nodes associated with the requests. |
288 * Sends message to parent when complete. | |
289 * @param {number[]} requests list of request IDs that were previously | 259 * @param {number[]} requests list of request IDs that were previously |
290 * reported by this notifier. | 260 * reported by this notifier. |
291 * @param {number} responseID ID to be sent with the response. | 261 * @return {number[]|null} either an array containing width and height or |
| 262 * null if the size could not be calculated. |
292 */ | 263 */ |
293 retrieveNodeSize: function(requests, responseID) | 264 retrieveNodeSize: function(requests) |
294 { | 265 { |
295 function getNodeSize(node) | 266 function getNodeSize(node) |
296 { | 267 { |
297 if (node instanceof Ci.nsIDOMHTMLImageElement && (node.naturalWidth || nod
e.naturalHeight)) | 268 if (node instanceof Ci.nsIDOMHTMLImageElement && (node.naturalWidth || nod
e.naturalHeight)) |
298 return [node.naturalWidth, node.naturalHeight]; | 269 return [node.naturalWidth, node.naturalHeight]; |
299 else if (node instanceof Ci.nsIDOMHTMLElement && (node.offsetWidth || node
.offsetHeight)) | 270 else if (node instanceof Ci.nsIDOMHTMLElement && (node.offsetWidth || node
.offsetHeight)) |
300 return [node.offsetWidth, node.offsetHeight]; | 271 return [node.offsetWidth, node.offsetHeight]; |
301 else | 272 else |
302 return null; | 273 return null; |
303 } | 274 } |
304 | 275 |
305 let size = null; | 276 let size = null; |
306 for (let id of requests) | 277 for (let id of requests) |
307 { | 278 { |
308 if (!this.nodes.has(id)) | 279 if (!this.nodes.has(id)) |
309 continue; | 280 continue; |
310 | 281 |
311 let node = this.nodes.get(id); | 282 let node = this.nodes.get(id); |
312 if (Cu.isDeadWrapper(node)) | 283 if (Cu.isDeadWrapper(node)) |
313 this.nodes.delete(node); | 284 this.nodes.delete(node); |
314 else | 285 else |
315 { | 286 { |
316 size = getNodeSize(node); | 287 size = getNodeSize(node); |
317 if (size) | 288 if (size) |
318 break; | 289 break; |
319 } | 290 } |
320 } | 291 } |
321 sendAsyncMessage("AdblockPlus:NotifierResponse", { | 292 return size; |
322 notifierID: this.id, | |
323 responseID, | |
324 response: size | |
325 }); | |
326 }, | 293 }, |
327 | 294 |
328 /** | 295 /** |
329 * Stores the nodes associated with the requests and generates a unique ID | 296 * Stores the nodes associated with the requests and generates a unique ID |
330 * for them that can be used with Policy.refilterNodes(). Sends message to | 297 * for them that can be used with Policy.refilterNodes(). |
331 * parent when complete. | |
332 * @param {number[]} requests list of request IDs that were previously | 298 * @param {number[]} requests list of request IDs that were previously |
333 * reported by this notifier. | 299 * reported by this notifier. |
334 * @param {number} responseID ID to be sent with the response. | 300 * @return {string} unique identifiers associated with the nodes. |
335 */ | 301 */ |
336 storeNodesForEntries: function(requests, responseID) | 302 storeNodesForEntries: function(requests) |
337 { | 303 { |
338 let nodes = []; | 304 let nodes = []; |
339 for (let id of requests) | 305 for (let id of requests) |
340 { | 306 { |
341 if (!this.nodes.has(id)) | 307 if (!this.nodes.has(id)) |
342 continue; | 308 continue; |
343 | 309 |
344 let node = this.nodes.get(id); | 310 let node = this.nodes.get(id); |
345 if (Cu.isDeadWrapper(node)) | 311 if (Cu.isDeadWrapper(node)) |
346 this.nodes.delete(node); | 312 this.nodes.delete(node); |
347 else | 313 else |
348 nodes.push(node); | 314 nodes.push(node); |
349 } | 315 } |
350 | 316 |
351 let {storeNodes} = require("child/contentPolicy"); | 317 let {storeNodes} = require("child/contentPolicy"); |
352 let id = storeNodes(nodes); | 318 return storeNodes(nodes); |
353 sendAsyncMessage("AdblockPlus:NotifierResponse", { | |
354 notifierID: this.id, | |
355 responseID, | |
356 response: id | |
357 }); | |
358 } | 319 } |
359 }; | 320 }; |
360 | 321 |
361 /** | 322 /** |
362 * Attaches request data to a DOM node. | 323 * Attaches request data to a DOM node. |
363 * @param {Node} node node to attach data to | 324 * @param {Node} node node to attach data to |
364 * @param {Window} topWnd top-level window the node belongs to | 325 * @param {Window} topWnd top-level window the node belongs to |
365 * @param {Object} hitData | 326 * @param {Object} hitData |
366 * @param {String} hitData.contentType request type, e.g. "IMAGE" | 327 * @param {String} hitData.contentType request type, e.g. "IMAGE" |
367 * @param {String} hitData.docDomain domain of the document that initiated the
request | 328 * @param {String} hitData.docDomain domain of the document that initiated the
request |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
474 node = node.parentNode; | 435 node = node.parentNode; |
475 } | 436 } |
476 else | 437 else |
477 { | 438 { |
478 node = null; | 439 node = null; |
479 } | 440 } |
480 } | 441 } |
481 | 442 |
482 return null; | 443 return null; |
483 }; | 444 }; |
OLD | NEW |