LEFT | RIGHT |
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 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 */ | 48 */ |
49 let collapsedClass = null; | 49 let collapsedClass = null; |
50 | 50 |
51 /** | 51 /** |
52 * Maps numerical content type IDs to strings. | 52 * Maps numerical content type IDs to strings. |
53 * @type Map.<number,string> | 53 * @type Map.<number,string> |
54 */ | 54 */ |
55 let types = new Map(); | 55 let types = new Map(); |
56 | 56 |
57 /** | 57 /** |
| 58 * Processes parent's response to the ShouldAllow message. |
| 59 * @param {nsIDOMWindow} window window that the request is associated with |
| 60 * @param {nsIDOMElement} node DOM element that the request is associated with |
| 61 * @param {Object|undefined} response object received as response |
| 62 * @return {Boolean} false if the request should be blocked |
| 63 */ |
| 64 function processPolicyResponse(window, node, response) |
| 65 { |
| 66 if (typeof response == "undefined") |
| 67 return true; |
| 68 |
| 69 let {allow, collapse, hits} = response; |
| 70 let isObject = false; |
| 71 for (let {frameIndex, contentType, docDomain, thirdParty, location, filter} of
hits) |
| 72 { |
| 73 if (contentType == "OBJECT") |
| 74 isObject = true; |
| 75 |
| 76 let context = node; |
| 77 if (typeof frameIndex == "number") |
| 78 { |
| 79 context = window; |
| 80 for (let i = 0; i < frameIndex; i++) |
| 81 context = context.parent; |
| 82 context = context.document; |
| 83 } |
| 84 RequestNotifier.addNodeData(context, window.top, contentType, docDomain, thi
rdParty, location, filter); |
| 85 } |
| 86 |
| 87 if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) |
| 88 { |
| 89 // Track mouse events for objects |
| 90 if (allow && isObject) |
| 91 { |
| 92 node.addEventListener("mouseover", objectMouseEventHander, true); |
| 93 node.addEventListener("mouseout", objectMouseEventHander, true); |
| 94 } |
| 95 |
| 96 if (collapse) |
| 97 schedulePostProcess(node); |
| 98 } |
| 99 return allow; |
| 100 } |
| 101 |
| 102 /** |
58 * Checks whether a request should be allowed, hides it if necessary | 103 * Checks whether a request should be allowed, hides it if necessary |
59 * @param wnd {nsIDOMWindow} | 104 * @param {nsIDOMWindow} window |
60 * @param node {nsIDOMElement} | 105 * @param {nsIDOMElement} node |
61 * @param contentType {String} | 106 * @param {String} contentType |
62 * @param location {String} | 107 * @param {String} location location of the request, filter key if contentType i
s ELEMHIDE |
63 * @param [callback] {Function} If present, the request will be sent | |
64 * asynchronously and callback called with the | |
65 * response | |
66 * @return {Boolean} false if the request should be blocked | 108 * @return {Boolean} false if the request should be blocked |
67 */ | 109 */ |
68 let shouldAllow = exports.shouldAllow = function(window, node, contentType, loca
tion, callback) | 110 let shouldAllow = exports.shouldAllow = function(window, node, contentType, loca
tion) |
69 { | 111 { |
70 function processResponse(response) | 112 return processPolicyResponse(window, node, sendSyncMessage("AdblockPlus:Should
Allow", { |
71 { | 113 contentType, |
72 if (typeof response == "undefined") | 114 location, |
73 return true; | |
74 | |
75 let {allow, collapse, hits} = response; | |
76 for (let {frameIndex, contentType, docDomain, thirdParty, location, filter}
of hits) | |
77 { | |
78 let context = node; | |
79 if (typeof frameIndex == "number") | |
80 { | |
81 context = window; | |
82 for (let i = 0; i < frameIndex; i++) | |
83 context = context.parent; | |
84 context = context.document; | |
85 } | |
86 RequestNotifier.addNodeData(context, window.top, contentType, docDomain, t
hirdParty, location, filter); | |
87 } | |
88 | |
89 if (node.nodeType == Ci.nsIDOMNode.ELEMENT_NODE) | |
90 { | |
91 // Track mouse events for objects | |
92 if (allow && contentType == "OBJECT") | |
93 { | |
94 node.addEventListener("mouseover", objectMouseEventHander, true); | |
95 node.addEventListener("mouseout", objectMouseEventHander, true); | |
96 } | |
97 | |
98 if (collapse) | |
99 schedulePostProcess(node); | |
100 } | |
101 return allow; | |
102 } | |
103 | |
104 let data = { | |
105 contentType: contentType, | |
106 location: location, | |
107 frames: getFrames(window), | 115 frames: getFrames(window), |
108 isPrivate: isPrivate(window) | 116 isPrivate: isPrivate(window) |
109 }; | 117 })); |
110 if (typeof callback == "function") | 118 }; |
111 { | 119 |
112 sendAsyncMessage("AdblockPlus:ShouldAllow", data, (data) => { | 120 /** |
113 callback(processResponse(data)); | 121 * Asynchronously checks whether a request should be allowed. |
114 }); | 122 * @param {nsIDOMWindow} window |
115 } | 123 * @param {nsIDOMElement} node |
116 else | 124 * @param {String} contentType |
117 return processResponse(sendSyncMessage("AdblockPlus:ShouldAllow", data)); | 125 * @param {String} location location of the request, filter key if contentType i
s ELEMHIDE |
| 126 * @param {Function} callback callback to be called with a boolean value, if |
| 127 * false the request should be blocked |
| 128 */ |
| 129 let shouldAllowAsync = exports.shouldAllowAsync = function(window, node, content
Type, location, callback) |
| 130 { |
| 131 sendAsyncMessage("AdblockPlus:ShouldAllow", { |
| 132 contentType, |
| 133 location, |
| 134 frames: getFrames(window), |
| 135 isPrivate: isPrivate(window) |
| 136 }, response => callback(processPolicyResponse(window, node, response))); |
118 }; | 137 }; |
119 | 138 |
120 /** | 139 /** |
121 * Actual nsIContentPolicy and nsIChannelEventSink implementation | 140 * Actual nsIContentPolicy and nsIChannelEventSink implementation |
122 * @class | 141 * @class |
123 */ | 142 */ |
124 var PolicyImplementation = | 143 var PolicyImplementation = |
125 { | 144 { |
126 classDescription: "Adblock Plus content policy", | 145 classDescription: "Adblock Plus content policy", |
127 classID: Components.ID("cfeaabe6-1dd1-11b2-a0c6-cb5c268894c9"), | 146 classID: Components.ID("cfeaabe6-1dd1-11b2-a0c6-cb5c268894c9"), |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
260 return; | 279 return; |
261 | 280 |
262 let wnd = Utils.getRequestWindow(newChannel); | 281 let wnd = Utils.getRequestWindow(newChannel); |
263 if (!wnd) | 282 if (!wnd) |
264 return; | 283 return; |
265 | 284 |
266 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) | 285 if (contentType == Ci.nsIContentPolicy.TYPE_DOCUMENT) |
267 { | 286 { |
268 if (wnd.history.length <= 1 && wnd.opener) | 287 if (wnd.history.length <= 1 && wnd.opener) |
269 { | 288 { |
270 // Special treatment for pop-up windows. Note that we might not have | 289 // Special treatment for pop-up windows - this will close the window |
| 290 // rather than preventing the redirect. Note that we might not have |
271 // seen the original channel yet because the redirect happened before | 291 // seen the original channel yet because the redirect happened before |
272 // the async code in observe() had a chance to run. | 292 // the async code in observe() had a chance to run. |
273 this.observe(wnd, "content-document-global-created", null, oldChannel.
URI.spec); | 293 this.observe(wnd, "content-document-global-created", null, oldChannel.
URI.spec); |
274 this.observe(wnd, "content-document-global-created", null, newChannel.
URI.spec); | 294 this.observe(wnd, "content-document-global-created", null, newChannel.
URI.spec); |
275 } | 295 } |
276 return; | 296 return; |
277 } | 297 } |
278 | 298 |
279 shouldAllow(wnd, wnd.document, types.get(contentType), newChannel.URI.spec
, function(allow) | 299 shouldAllowAsync(wnd, wnd.document, types.get(contentType), newChannel.URI
.spec, function(allow) |
280 { | 300 { |
281 callback.onRedirectVerifyCallback(allow ? Cr.NS_OK : Cr.NS_BINDING_ABORT
ED); | 301 callback.onRedirectVerifyCallback(allow ? Cr.NS_OK : Cr.NS_BINDING_ABORT
ED); |
282 }); | 302 }); |
283 async = true; | 303 async = true; |
284 } | 304 } |
285 catch (e) | 305 catch (e) |
286 { | 306 { |
287 // We shouldn't throw exceptions here - this will prevent the redirect. | 307 // We shouldn't throw exceptions here - this will prevent the redirect. |
288 Cu.reportError(e); | 308 Cu.reportError(e); |
289 } | 309 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 Utils.runAsync(postProcessNodes); | 346 Utils.runAsync(postProcessNodes); |
327 } | 347 } |
328 } | 348 } |
329 | 349 |
330 /** | 350 /** |
331 * Processes nodes scheduled for post-processing (typically hides them). | 351 * Processes nodes scheduled for post-processing (typically hides them). |
332 */ | 352 */ |
333 function postProcessNodes() | 353 function postProcessNodes() |
334 { | 354 { |
335 if (!collapsedClass) | 355 if (!collapsedClass) |
336 { | 356 collapsedClass = sendSyncMessage("AdblockPlus:GetCollapsedClass"); |
337 let response = sendSyncMessage("AdblockPlus:GetCollapsedClass"); | |
338 if (response.length) | |
339 collapsedClass = response[0]; | |
340 | |
341 if (!collapsedClass) | |
342 { | |
343 Utils.runAsync(postProcessNodes); | |
344 return; | |
345 } | |
346 } | |
347 | 357 |
348 let nodes = scheduledNodes; | 358 let nodes = scheduledNodes; |
349 scheduledNodes = null; | 359 scheduledNodes = null; |
| 360 |
| 361 if (!collapsedClass) |
| 362 return; |
350 | 363 |
351 for (let node of nodes) | 364 for (let node of nodes) |
352 { | 365 { |
353 // adjust frameset's cols/rows for frames | 366 // adjust frameset's cols/rows for frames |
354 let parentNode = node.parentNode; | 367 let parentNode = node.parentNode; |
355 if (parentNode && parentNode instanceof Ci.nsIDOMHTMLFrameSetElement) | 368 if (parentNode && parentNode instanceof Ci.nsIDOMHTMLFrameSetElement) |
356 { | 369 { |
357 let hasCols = (parentNode.cols && parentNode.cols.indexOf(",") > 0); | 370 let hasCols = (parentNode.cols && parentNode.cols.indexOf(",") > 0); |
358 let hasRows = (parentNode.rows && parentNode.rows.indexOf(",") > 0); | 371 let hasRows = (parentNode.rows && parentNode.rows.indexOf(",") > 0); |
359 if ((hasCols || hasRows) && !(hasCols && hasRows)) | 372 if ((hasCols || hasRows) && !(hasCols && hasRows)) |
360 { | 373 { |
361 let index = -1; | 374 let index = -1; |
362 for (let frame = node; frame; frame = frame.previousSibling) | 375 for (let frame = node; frame; frame = frame.previousSibling) |
363 if (frame instanceof Ci.nsIDOMHTMLFrameElement || frame instanceof Ci.
nsIDOMHTMLFrameSetElement) | 376 if (frame instanceof Ci.nsIDOMHTMLFrameElement || frame instanceof Ci.
nsIDOMHTMLFrameSetElement) |
364 index++; | 377 index++; |
365 | 378 |
366 let property = (hasCols ? "cols" : "rows"); | 379 let property = (hasCols ? "cols" : "rows"); |
367 let weights = parentNode[property].split(","); | 380 let weights = parentNode[property].split(","); |
368 weights[index] = "0"; | 381 weights[index] = "0"; |
369 parentNode[property] = weights.join(","); | 382 parentNode[property] = weights.join(","); |
370 } | 383 } |
371 } | 384 } |
372 else | 385 else |
373 node.classList.add(collapsedClass); | 386 node.classList.add(collapsedClass); |
374 } | 387 } |
375 } | 388 } |
LEFT | RIGHT |