Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2014 Eyeo GmbH | 3 * Copyright (C) 2006-2014 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 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
168 { | 168 { |
169 Array.prototype.forEach.call( | 169 Array.prototype.forEach.call( |
170 document.querySelectorAll(highlightedElementsSelector), | 170 document.querySelectorAll(highlightedElementsSelector), |
171 unhighlightElement | 171 unhighlightElement |
172 ); | 172 ); |
173 | 173 |
174 highlightedElementsSelector = null; | 174 highlightedElementsSelector = null; |
175 } | 175 } |
176 } | 176 } |
177 | 177 |
178 function getElementURLs(element) { | |
179 var urls = []; | |
180 | |
181 if (element.src) | |
182 urls.push(element.src); | |
183 | |
184 switch (element.localName) | |
185 { | |
186 case "object": | |
187 var url = element.getAttribute("data"); | |
Wladimir Palant
2014/12/08 11:43:00
For reference: <object> also has archive and codeb
Sebastian Noack
2014/12/08 16:45:04
I agree, also note they are obsolete since HTML5,
Wladimir Palant
2014/12/08 20:31:09
Oh, you didn't have to deal with Java? :)
Sebastian Noack
2014/12/08 21:12:49
I see, that stuff is for Java. I prefer to ignore
| |
188 if (url) | |
189 return [resolveURL(url)]; | |
190 | |
191 for (var i = 0; i < element.children.length; i++) | |
192 { | |
193 var child = element.children[i]; | |
194 if (child.localName != "param") | |
195 continue; | |
196 | |
197 var name = child.getAttribute("name"); | |
198 if (name != "movie" && name != "src") | |
199 continue; | |
200 | |
201 var value = child.getAttribute("value"); | |
202 if (!value) | |
203 continue; | |
204 | |
205 return [resolveURL(value)]; | |
206 } | |
207 | |
208 return []; | |
209 | |
210 case "video": | |
211 case "audio": | |
212 case "picture": | |
213 for (var i = 0; i < element.children.length; i++) | |
214 { | |
215 var child = element.children[i]; | |
216 | |
217 if (child.localName != "source") | |
218 continue; | |
Wladimir Palant
2014/12/08 11:43:00
It seems that we need to handle <track> elements a
Sebastian Noack
2014/12/08 16:45:04
Done.
| |
219 | |
220 if (child.src) | |
221 urls.push(child.src); | |
222 | |
223 urls = urls.concat(parseSrcSet(child)); | |
Wladimir Palant
2014/12/08 11:43:00
Rather than generate a new array, I'd prefer:
url
Sebastian Noack
2014/12/08 16:45:04
Right, I forgot that push() can add multiple items
| |
224 } | |
225 | |
226 if (element.poster) | |
227 urls.push(element.poster); | |
228 | |
229 break; | |
230 | |
231 case "img": | |
232 urls = urls.concat(parseSrcSet(element)); | |
233 } | |
234 | |
235 return urls; | |
236 } | |
237 | |
238 function isBlockable(element) | |
239 { | |
240 if (element.id) | |
241 return true; | |
242 if (element.classList.length > 0) | |
243 return true; | |
244 if (getElementURLs(element).length > 0) | |
245 return true; | |
246 | |
247 // We only generate filters based on the "style" attribute, | |
248 // if this is the only way we can generate a filter, and | |
249 // only if there are at least two CSS properties defined. | |
250 if (/:.+:/.test(element.getAttribute("style"))) | |
251 return true; | |
252 | |
253 return false; | |
254 } | |
255 | |
178 // Gets the absolute position of an element by walking up the DOM tree, | 256 // Gets the absolute position of an element by walking up the DOM tree, |
179 // adding up offsets. | 257 // adding up offsets. |
180 // I hope there's a better way because it just seems absolutely stupid | 258 // I hope there's a better way because it just seems absolutely stupid |
181 // that the DOM wouldn't have a direct way to get this, given that it | 259 // that the DOM wouldn't have a direct way to get this, given that it |
182 // has hundreds and hundreds of other methods that do random junk. | 260 // has hundreds and hundreds of other methods that do random junk. |
183 function getAbsolutePosition(elt) { | 261 function getAbsolutePosition(elt) { |
184 var l = 0; | 262 var l = 0; |
185 var t = 0; | 263 var t = 0; |
186 for(; elt; elt = elt.offsetParent) { | 264 for(; elt; elt = elt.offsetParent) { |
187 l += elt.offsetLeft; | 265 l += elt.offsetLeft; |
188 t += elt.offsetTop; | 266 t += elt.offsetTop; |
189 } | 267 } |
190 return [l, t]; | 268 return [l, t]; |
191 } | 269 } |
192 | 270 |
193 // Adds an overlay to an element, which is probably a Flash object | 271 // Adds an overlay to an element, which is probably a Flash object |
194 function addElementOverlay(elt) { | 272 function addElementOverlay(elt) { |
195 // If this element is enclosed in an object tag, we prefer to block that inste ad | 273 // If this element is enclosed in an object tag, we prefer to block that inste ad |
196 if(!elt) | 274 if(!elt) |
197 return null; | 275 return null; |
198 | 276 |
199 // If element doesn't have at least one of class name, ID or URL, give up | 277 // If element doesn't have at least one of class name, ID or URL, give up |
200 // because we don't know how to construct a filter rule for it | 278 // because we don't know how to construct a filter rule for it |
201 var url = getElementURL(elt); | 279 if(!isBlockable(elt)) |
202 if(!elt.className && !elt.id && !url) | |
203 return; | 280 return; |
204 | 281 |
205 // If the element isn't rendered (since its or one of its ancestor's | 282 // If the element isn't rendered (since its or one of its ancestor's |
206 // "diplay" property is "none"), the overlay wouldn't match the element. | 283 // "diplay" property is "none"), the overlay wouldn't match the element. |
207 if (!elt.offsetParent) | 284 if (!elt.offsetParent) |
208 return; | 285 return; |
209 | 286 |
210 var thisStyle = getComputedStyle(elt, null); | 287 var thisStyle = getComputedStyle(elt, null); |
211 var overlay = document.createElement('div'); | 288 var overlay = document.createElement('div'); |
212 overlay.prisoner = elt; | 289 overlay.prisoner = elt; |
213 overlay.prisonerURL = url; | |
214 overlay.className = "__adblockplus__overlay"; | 290 overlay.className = "__adblockplus__overlay"; |
215 overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display: inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;'); | 291 overlay.setAttribute('style', 'opacity:0.4; background-color:#ffffff; display: inline-box; ' + 'width:' + thisStyle.width + '; height:' + thisStyle.height + '; position:absolute; overflow:hidden; -webkit-box-sizing:border-box;'); |
216 var pos = getAbsolutePosition(elt); | 292 var pos = getAbsolutePosition(elt); |
217 overlay.style.left = pos[0] + "px"; | 293 overlay.style.left = pos[0] + "px"; |
218 overlay.style.top = pos[1] + "px"; | 294 overlay.style.top = pos[1] + "px"; |
219 | 295 |
220 if (thisStyle.position != "static") | 296 if (thisStyle.position != "static") |
221 overlay.style.zIndex = thisStyle.zIndex; | 297 overlay.style.zIndex = thisStyle.zIndex; |
222 else | 298 else |
223 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; | 299 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 // Turn on the choose element to create filter thing | 346 // Turn on the choose element to create filter thing |
271 function clickHide_activate() { | 347 function clickHide_activate() { |
272 if(document == null) | 348 if(document == null) |
273 return; | 349 return; |
274 | 350 |
275 // If we are already selecting, abort now | 351 // If we are already selecting, abort now |
276 if (clickHide_activated || clickHideFiltersDialog) | 352 if (clickHide_activated || clickHideFiltersDialog) |
277 clickHide_deactivate(); | 353 clickHide_deactivate(); |
278 | 354 |
279 // Add overlays for elements with URLs so user can easily click them | 355 // Add overlays for elements with URLs so user can easily click them |
280 var elts = document.querySelectorAll('object,embed,img,iframe'); | 356 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure'); |
281 for(var i=0; i<elts.length; i++) | 357 for(var i=0; i<elts.length; i++) |
282 addElementOverlay(elts[i]); | 358 addElementOverlay(elts[i]); |
283 | 359 |
284 clickHide_activated = true; | 360 clickHide_activated = true; |
285 document.addEventListener("mouseover", clickHide_mouseOver, true); | 361 document.addEventListener("mouseover", clickHide_mouseOver, true); |
286 document.addEventListener("mouseout", clickHide_mouseOut, true); | 362 document.addEventListener("mouseout", clickHide_mouseOut, true); |
287 document.addEventListener("click", clickHide_mouseClick, true); | 363 document.addEventListener("click", clickHide_mouseClick, true); |
288 document.addEventListener("keydown", clickHide_keyDown, true); | 364 document.addEventListener("keydown", clickHide_keyDown, true); |
289 } | 365 } |
290 | 366 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
338 clickHide_mouseClick(ev); | 414 clickHide_mouseClick(ev); |
339 } | 415 } |
340 | 416 |
341 // Hovering over an element so highlight it | 417 // Hovering over an element so highlight it |
342 function clickHide_mouseOver(e) | 418 function clickHide_mouseOver(e) |
343 { | 419 { |
344 if (clickHide_activated == false) | 420 if (clickHide_activated == false) |
345 return; | 421 return; |
346 | 422 |
347 var target = e.target; | 423 var target = e.target; |
348 while (target.parentNode && !(target.id || target.className || target.src || / :.+:/.test(target.getAttribute("style")))) | 424 while (target.parentNode && !isBlockable(target)) |
349 target = target.parentNode; | 425 target = target.parentNode; |
350 if (target == document.documentElement || target == document.body) | 426 if (target == document.documentElement || target == document.body) |
351 target = null; | 427 target = null; |
352 | 428 |
353 if (target && target instanceof HTMLElement) | 429 if (target && target instanceof HTMLElement) |
354 { | 430 { |
355 currentElement = target; | 431 currentElement = target; |
356 | 432 |
357 highlightElement(target, "#d6d84b", "#f8fa47"); | 433 highlightElement(target, "#d6d84b", "#f8fa47"); |
358 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 434 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 | 467 |
392 // When the user clicks, the currentElement is the one we want. | 468 // When the user clicks, the currentElement is the one we want. |
393 // We should have ABP rules ready for when the | 469 // We should have ABP rules ready for when the |
394 // popup asks for them. | 470 // popup asks for them. |
395 function clickHide_mouseClick(e) | 471 function clickHide_mouseClick(e) |
396 { | 472 { |
397 if (!currentElement || !clickHide_activated) | 473 if (!currentElement || !clickHide_activated) |
398 return; | 474 return; |
399 | 475 |
400 var elt = currentElement; | 476 var elt = currentElement; |
401 var url = null; | |
402 if (currentElement.classList.contains("__adblockplus__overlay")) | 477 if (currentElement.classList.contains("__adblockplus__overlay")) |
403 { | |
404 elt = currentElement.prisoner; | 478 elt = currentElement.prisoner; |
405 url = currentElement.prisonerURL; | |
406 } | |
407 else if (elt.src) | |
408 url = elt.src; | |
409 | 479 |
410 clickHideFilters = new Array(); | 480 clickHideFilters = new Array(); |
411 selectorList = new Array(); | 481 selectorList = new Array(); |
412 | 482 |
413 var addSelector = function(selector) | 483 var addSelector = function(selector) |
414 { | 484 { |
485 if (selectorList.indexOf(selector) != -1) | |
486 return; | |
487 | |
415 clickHideFilters.push(document.domain + "##" + selector); | 488 clickHideFilters.push(document.domain + "##" + selector); |
416 selectorList.push(selector); | 489 selectorList.push(selector); |
417 }; | 490 }; |
418 | 491 |
419 if (elt.id) | 492 if (elt.id) |
420 addSelector("#" + escapeCSS(elt.id)); | 493 addSelector("#" + escapeCSS(elt.id)); |
421 | 494 |
422 if (elt.classList.length > 0) | 495 if (elt.classList.length > 0) |
423 { | 496 { |
424 var selector = ""; | 497 var selector = ""; |
425 | 498 |
426 for (var i = 0; i < elt.classList.length; i++) | 499 for (var i = 0; i < elt.classList.length; i++) |
427 selector += "." + escapeCSS(elt.classList[i]); | 500 selector += "." + escapeCSS(elt.classList[i]); |
428 | 501 |
429 addSelector(selector); | 502 addSelector(selector); |
430 } | 503 } |
431 | 504 |
432 if (url) | 505 var urls = getElementURLs(elt); |
506 for (var i = 0; i < urls.length; i++) | |
433 { | 507 { |
434 var src = elt.getAttribute("src"); | 508 var url = urls[i]; |
435 var selector = src && escapeCSS(elt.localName) + '[src=' + quote(src) + ']'; | |
436 | 509 |
Sebastian Noack
2014/11/26 14:01:22
A fair amount of complexity here, only came from g
| |
437 if (/^https?:/i.test(url)) | 510 if (/^https?:/i.test(url)) |
438 { | 511 { |
439 clickHideFilters.push(url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||")); | 512 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
440 | 513 |
441 if (selector) | 514 if (clickHideFilters.indexOf(filter) == -1) |
442 selectorList.push(selector); | 515 clickHideFilters.push(filter); |
516 | |
517 continue; | |
443 } | 518 } |
444 else if (selector) | 519 |
445 addSelector(selector); | 520 if (url == elt.src) |
521 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']'); | |
446 } | 522 } |
447 | 523 |
448 // restore the original style, before generating the fallback filter that | 524 // restore the original style, before generating the fallback filter that |
449 // will include the style, and to prevent highlightElements from saving those | 525 // will include the style, and to prevent highlightElements from saving those |
450 unhighlightElement(currentElement); | 526 unhighlightElement(currentElement); |
451 | 527 |
452 // as last resort, create a filter based on inline styles | 528 // as last resort, create a filter based on inline styles |
453 if (clickHideFilters.length == 0) | 529 if (clickHideFilters.length == 0) |
454 { | 530 { |
455 var style = elt.getAttribute("style"); | 531 var style = elt.getAttribute("style"); |
456 if (style) | 532 if (style) |
457 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 533 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); |
458 } | 534 } |
459 | 535 |
460 // Show popup | 536 // Show popup |
461 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 537 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
462 | 538 |
463 // Highlight the elements specified by selector in yellow | 539 // Highlight the elements specified by selector in yellow |
464 highlightElements(selectorList.join(",")); | 540 highlightElements(selectorList.join(",")); |
465 // Now, actually highlight the element the user clicked on in red | 541 // Now, actually highlight the element the user clicked on in red |
466 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 542 highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
467 | 543 |
468 // Make sure the browser doesn't handle this click | 544 // Make sure the browser doesn't handle this click |
469 e.preventDefault(); | 545 e.preventDefault(); |
470 e.stopPropagation(); | 546 e.stopPropagation(); |
471 } | 547 } |
472 | 548 |
473 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME | 549 function parseSrcSet(element) |
474 function getElementURL(elt) { | 550 { |
475 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL | 551 if (!element.srcset) |
476 // in value attribute | 552 return []; |
477 var url; | |
478 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data") )) { | |
479 // No data attribute, look in PARAM child tags for a URL for the swf file | |
480 var params = elt.querySelectorAll("param[name=\"movie\"]"); | |
481 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL | |
482 if(params[0]) | |
483 url = params[0].getAttribute("value"); | |
484 else { | |
485 params = elt.querySelectorAll("param[name=\"src\"]"); | |
486 if(params[0]) | |
487 url = params[0].getAttribute("value"); | |
488 } | |
489 | 553 |
554 var urls = element.srcset.split(","); | |
555 for (var i = 0; i < urls.length; i++) | |
556 { | |
557 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, ""); | |
Wladimir Palant
2014/12/08 11:43:00
Use urls[i].trim()? According to http://kangax.git
Sebastian Noack
2014/12/08 16:45:04
Done.
| |
490 if (url) | 558 if (url) |
491 url = resolveURL(url); | 559 urls[i] = resolveURL(url); |
Wladimir Palant
2014/12/08 11:43:00
What about descriptions? See http://html5hub.com/s
Sebastian Noack
2014/12/08 16:45:04
Those are stripped by the regex above.
| |
492 } else if(!url) { | 560 else |
493 url = elt.src || elt.href; | 561 urls.splice(i--, 1); |
494 } | 562 } |
495 return url; | 563 |
564 return urls; | |
496 } | 565 } |
497 | 566 |
498 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 567 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js |
499 // and licensed under the MIT license. See jquery-*.min.js for details. | 568 // and licensed under the MIT license. See jquery-*.min.js for details. |
500 function removeDotSegments(u) { | 569 function removeDotSegments(u) { |
501 var r = '', m = []; | 570 var r = '', m = []; |
502 if (/\./.test(u)) { | 571 if (/\./.test(u)) { |
503 while (u !== undefined && u !== '') { | 572 while (u !== undefined && u !== '') { |
504 if (u === '.' || u === '..') { | 573 if (u === '.' || u === '..') { |
505 u = ''; | 574 u = ''; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
686 break; | 755 break; |
687 default: | 756 default: |
688 sendResponse({}); | 757 sendResponse({}); |
689 break; | 758 break; |
690 } | 759 } |
691 }); | 760 }); |
692 | 761 |
693 if (window == window.top) | 762 if (window == window.top) |
694 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 763 ext.backgroundPage.sendMessage({type: "report-html-page"}); |
695 } | 764 } |
OLD | NEW |