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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
191 } | 191 } |
192 | 192 |
193 // Adds an overlay to an element, which is probably a Flash object | 193 // Adds an overlay to an element, which is probably a Flash object |
194 function addElementOverlay(elt) { | 194 function addElementOverlay(elt) { |
195 // If this element is enclosed in an object tag, we prefer to block that inste ad | 195 // If this element is enclosed in an object tag, we prefer to block that inste ad |
196 if(!elt) | 196 if(!elt) |
197 return null; | 197 return null; |
198 | 198 |
199 // If element doesn't have at least one of class name, ID or URL, give up | 199 // 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 | 200 // because we don't know how to construct a filter rule for it |
201 var url = getElementURL(elt); | 201 if(!hasFilters(elt)) |
202 if(!elt.className && !elt.id && !url) | |
203 return; | 202 return; |
204 var thisStyle = getComputedStyle(elt, null); | 203 var thisStyle = getComputedStyle(elt, null); |
205 var overlay = document.createElement('div'); | 204 var overlay = document.createElement('div'); |
206 overlay.prisoner = elt; | 205 overlay.prisoner = elt; |
207 overlay.prisonerURL = url; | |
208 overlay.className = "__adblockplus__overlay"; | 206 overlay.className = "__adblockplus__overlay"; |
209 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; z-index: 999 99'); | 207 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; z-index: 999 99'); |
210 var pos = getAbsolutePosition(elt); | 208 var pos = getAbsolutePosition(elt); |
211 overlay.style.left = pos[0] + "px"; | 209 overlay.style.left = pos[0] + "px"; |
212 overlay.style.top = pos[1] + "px"; | 210 overlay.style.top = pos[1] + "px"; |
213 // elt.parentNode.appendChild(overlay, elt); | 211 // elt.parentNode.appendChild(overlay, elt); |
214 document.body.appendChild(overlay); | 212 document.body.appendChild(overlay); |
215 return overlay; | 213 return overlay; |
216 } | 214 } |
217 | 215 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
258 // Turn on the choose element to create filter thing | 256 // Turn on the choose element to create filter thing |
259 function clickHide_activate() { | 257 function clickHide_activate() { |
260 if(document == null) | 258 if(document == null) |
261 return; | 259 return; |
262 | 260 |
263 // If we are already selecting, abort now | 261 // If we are already selecting, abort now |
264 if (clickHide_activated || clickHideFiltersDialog) | 262 if (clickHide_activated || clickHideFiltersDialog) |
265 clickHide_deactivate(); | 263 clickHide_deactivate(); |
266 | 264 |
267 // Add overlays for elements with URLs so user can easily click them | 265 // Add overlays for elements with URLs so user can easily click them |
268 var elts = document.querySelectorAll('object,embed,img,iframe'); | 266 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure'); |
269 for(var i=0; i<elts.length; i++) | 267 for(var i=0; i<elts.length; i++) |
270 addElementOverlay(elts[i]); | 268 addElementOverlay(elts[i]); |
271 | 269 |
272 clickHide_activated = true; | 270 clickHide_activated = true; |
273 document.addEventListener("mouseover", clickHide_mouseOver, true); | 271 document.addEventListener("mouseover", clickHide_mouseOver, true); |
274 document.addEventListener("mouseout", clickHide_mouseOut, true); | 272 document.addEventListener("mouseout", clickHide_mouseOut, true); |
275 document.addEventListener("click", clickHide_mouseClick, true); | 273 document.addEventListener("click", clickHide_mouseClick, true); |
276 document.addEventListener("keydown", clickHide_keyDown, true); | 274 document.addEventListener("keydown", clickHide_keyDown, true); |
277 } | 275 } |
278 | 276 |
(...skipping 25 matching lines...) Expand all Loading... | |
304 } | 302 } |
305 unhighlightElements(); | 303 unhighlightElements(); |
306 | 304 |
307 clickHide_activated = false; | 305 clickHide_activated = false; |
308 clickHide_filters = null; | 306 clickHide_filters = null; |
309 if(!document) | 307 if(!document) |
310 return; // This can happen inside a nuked iframe...I think | 308 return; // This can happen inside a nuked iframe...I think |
311 document.removeEventListener("mouseover", clickHide_mouseOver, true); | 309 document.removeEventListener("mouseover", clickHide_mouseOver, true); |
312 document.removeEventListener("mouseout", clickHide_mouseOut, true); | 310 document.removeEventListener("mouseout", clickHide_mouseOut, true); |
313 document.removeEventListener("click", clickHide_mouseClick, true); | 311 document.removeEventListener("click", clickHide_mouseClick, true); |
314 document.removeEventListener("keydown", clickHide_keyDown, true); | 312 document.removeEventListener("keydown", clickHide_keyDown, true); |
kzar
2014/11/26 11:36:17
I think the capturing / bubbling changes from the
Sebastian Noack
2014/11/26 11:42:48
They are not part of this patch. However, they sho
| |
315 | 313 |
316 // Remove overlays | 314 // Remove overlays |
317 // For some reason iterating over the array returend by getElementsByClassName () doesn't work | 315 // For some reason iterating over the array returend by getElementsByClassName () doesn't work |
318 var elt; | 316 var elt; |
319 while(elt = document.querySelector('.__adblockplus__overlay')) | 317 while(elt = document.querySelector('.__adblockplus__overlay')) |
320 elt.parentNode.removeChild(elt); | 318 elt.parentNode.removeChild(elt); |
321 } | 319 } |
322 | 320 |
323 function clickHide_elementClickHandler(ev) { | 321 function clickHide_elementClickHandler(ev) { |
324 ev.preventDefault(); | 322 ev.preventDefault(); |
325 ev.stopPropagation(); | 323 ev.stopPropagation(); |
326 clickHide_mouseClick(ev); | 324 clickHide_mouseClick(ev); |
327 } | 325 } |
328 | 326 |
329 // Hovering over an element so highlight it | 327 // Hovering over an element so highlight it |
330 function clickHide_mouseOver(e) | 328 function clickHide_mouseOver(e) |
331 { | 329 { |
332 if (clickHide_activated == false) | 330 if (clickHide_activated == false) |
333 return; | 331 return; |
334 | 332 |
335 var target = e.target; | 333 var target = e.target; |
336 while (target.parentNode && !(target.id || target.className || target.src || / :.+:/.test(target.getAttribute("style")))) | 334 while (target.parentNode && !hasFilters(target)) |
337 target = target.parentNode; | 335 target = target.parentNode; |
338 if (target == document.documentElement || target == document.body) | 336 if (target == document.documentElement || target == document.body) |
339 target = null; | 337 target = null; |
340 | 338 |
341 if (target && target instanceof HTMLElement) | 339 if (target && target instanceof HTMLElement) |
342 { | 340 { |
343 currentElement = target; | 341 currentElement = target; |
344 | 342 |
345 highlightElement(target, "#d6d84b", "#f8fa47"); | 343 highlightElement(target, "#d6d84b", "#f8fa47"); |
346 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 344 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 | 377 |
380 // When the user clicks, the currentElement is the one we want. | 378 // When the user clicks, the currentElement is the one we want. |
381 // We should have ABP rules ready for when the | 379 // We should have ABP rules ready for when the |
382 // popup asks for them. | 380 // popup asks for them. |
383 function clickHide_mouseClick(e) | 381 function clickHide_mouseClick(e) |
384 { | 382 { |
385 if (!currentElement || !clickHide_activated) | 383 if (!currentElement || !clickHide_activated) |
386 return; | 384 return; |
387 | 385 |
388 var elt = currentElement; | 386 var elt = currentElement; |
389 var url = null; | |
390 if (currentElement.classList.contains("__adblockplus__overlay")) | 387 if (currentElement.classList.contains("__adblockplus__overlay")) |
391 { | |
392 elt = currentElement.prisoner; | 388 elt = currentElement.prisoner; |
393 url = currentElement.prisonerURL; | |
394 } | |
395 else if (elt.src) | |
396 url = elt.src; | |
397 | 389 |
398 clickHideFilters = new Array(); | 390 clickHideFilters = new Array(); |
399 selectorList = new Array(); | 391 selectorList = new Array(); |
400 | 392 |
401 var addSelector = function(selector) | 393 var addSelector = function(selector) |
402 { | 394 { |
395 if (selectorList.indexOf(selector) != -1) | |
396 return; | |
397 | |
403 clickHideFilters.push(document.domain + "##" + selector); | 398 clickHideFilters.push(document.domain + "##" + selector); |
404 selectorList.push(selector); | 399 selectorList.push(selector); |
405 }; | 400 }; |
406 | 401 |
407 if (elt.id) | 402 if (elt.id) |
408 addSelector("#" + escapeCSS(elt.id)); | 403 addSelector("#" + escapeCSS(elt.id)); |
409 | 404 |
410 if (elt.classList.length > 0) | 405 if (elt.classList.length > 0) |
411 { | 406 { |
412 var selector = ""; | 407 var selector = ""; |
413 | 408 |
414 for (var i = 0; i < elt.classList.length; i++) | 409 for (var i = 0; i < elt.classList.length; i++) |
415 selector += "." + escapeCSS(elt.classList[i]); | 410 selector += "." + escapeCSS(elt.classList[i]); |
416 | 411 |
417 addSelector(selector); | 412 addSelector(selector); |
418 } | 413 } |
419 | 414 |
420 if (url) | 415 var urls = getElementURLs(elt); |
416 for (var i = 0; i < urls.length; i++) | |
421 { | 417 { |
422 var src = elt.getAttribute("src"); | 418 var url = urls[i]; |
423 var selector = src && escapeCSS(elt.localName) + '[src=' + quote(src) + ']'; | 419 var isHTTP = /^https?:/i.test(url); |
424 | 420 |
425 if (/^https?:/i.test(url)) | 421 if (isHTTP) |
426 { | 422 { |
427 clickHideFilters.push(url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||")); | 423 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
428 | 424 |
429 if (selector) | 425 if (clickHideFilters.indexOf(filter) != -1) |
426 continue; | |
427 | |
428 clickHideFilters.push(filter); | |
429 } | |
430 | |
431 if (url == elt.src) | |
432 { | |
433 var selector = escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute ("src")) + ']'; | |
434 | |
435 if (isHTTP) | |
430 selectorList.push(selector); | 436 selectorList.push(selector); |
437 else | |
438 addSelector(selector); | |
431 } | 439 } |
432 else if (selector) | |
433 addSelector(selector); | |
434 } | 440 } |
435 | 441 |
436 // restore the original style, before generating the fallback filter that | 442 // restore the original style, before generating the fallback filter that |
437 // will include the style, and to prevent highlightElements from saving those | 443 // will include the style, and to prevent highlightElements from saving those |
438 unhighlightElement(currentElement); | 444 unhighlightElement(currentElement); |
439 | 445 |
440 // as last resort, create a filter based on inline styles | 446 // as last resort, create a filter based on inline styles |
441 if (clickHideFilters.length == 0) | 447 if (clickHideFilters.length == 0) |
442 { | 448 { |
443 var style = elt.getAttribute("style"); | 449 var style = elt.getAttribute("style"); |
444 if (style) | 450 if (style) |
445 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 451 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); |
446 } | 452 } |
447 | 453 |
448 // Show popup | 454 // Show popup |
449 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 455 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
450 | 456 |
451 // Highlight the elements specified by selector in yellow | 457 // Highlight the elements specified by selector in yellow |
452 highlightElements(selectorList.join(",")); | 458 highlightElements(selectorList.join(",")); |
453 // Now, actually highlight the element the user clicked on in red | 459 // Now, actually highlight the element the user clicked on in red |
454 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 460 highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
455 | 461 |
456 // Make sure the browser doesn't handle this click | 462 // Make sure the browser doesn't handle this click |
457 e.preventDefault(); | 463 e.preventDefault(); |
458 e.stopPropagation(); | 464 e.stopPropagation(); |
459 } | 465 } |
460 | 466 |
461 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME | 467 function parseSrcSet(element) |
462 function getElementURL(elt) { | 468 { |
463 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL | 469 if (!element.srcset) |
464 // in value attribute | 470 return []; |
465 var url; | |
466 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data") )) { | |
467 // No data attribute, look in PARAM child tags for a URL for the swf file | |
468 var params = elt.querySelectorAll("param[name=\"movie\"]"); | |
469 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL | |
470 if(params[0]) | |
471 url = params[0].getAttribute("value"); | |
472 else { | |
473 params = elt.querySelectorAll("param[name=\"src\"]"); | |
474 if(params[0]) | |
475 url = params[0].getAttribute("value"); | |
476 } | |
477 | 471 |
472 var urls = element.srcset.split(","); | |
473 for (var i = 0; i < urls.length; i++) | |
474 { | |
475 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, ""); | |
478 if (url) | 476 if (url) |
479 url = resolveURL(url); | 477 urls[i] = resolveURL(url); |
480 } else if(!url) { | 478 else |
481 url = elt.src || elt.href; | 479 urls.splice(i--, 1); |
482 } | 480 } |
483 return url; | 481 |
482 return urls; | |
483 } | |
484 | |
485 function getElementURLs(elt) { | |
486 var urls = []; | |
487 | |
488 if (elt.src) | |
489 urls.push(elt.src); | |
490 | |
491 switch (elt.localName) | |
492 { | |
493 case "object": | |
494 var url = elt.getAttribute("data"); | |
495 if (url) | |
496 return [resolveURL(url)]; | |
497 | |
498 for (var i = 0; i < elt.children.length; i++) | |
499 { | |
500 var child = elt.children[i]; | |
501 if (child.localName != "param") | |
502 continue; | |
503 | |
504 var name = child.getAttribute("name"); | |
505 if (name != "movie" && name != "src") | |
506 continue; | |
507 | |
508 var value = child.getAttribute("value"); | |
509 if (!value) | |
510 continue; | |
511 | |
512 return [resolveURL(value)]; | |
513 } | |
514 | |
515 return []; | |
516 | |
517 case "video": | |
518 case "audio": | |
519 case "picture": | |
520 for (var i = 0; i < elt.children.length; i++) | |
521 { | |
522 var child = elt.children[i]; | |
523 | |
524 if (child.localName != "source") | |
525 continue; | |
526 | |
527 if (child.src) | |
528 urls.push(child.src); | |
529 | |
530 urls = urls.concat(parseSrcSet(child)); | |
531 } | |
532 | |
533 if (elt.poster) | |
534 urls.push(elt.poster); | |
535 | |
536 break; | |
537 | |
538 case "img": | |
539 urls = urls.concat(parseSrcSet(elt)); | |
540 } | |
541 | |
542 return urls; | |
543 } | |
544 | |
545 function hasFilters(element) | |
546 { | |
547 if (element.id) | |
548 return true; | |
549 if (element.classList.length > 0) | |
550 return true; | |
551 if (getElementURLs(element).length > 0) | |
552 return true; | |
553 if (/:.+:/.test(element.getAttribute("style"))) | |
554 return true; | |
555 | |
556 return false; | |
484 } | 557 } |
485 | 558 |
486 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 559 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js |
487 // and licensed under the MIT license. See jquery-*.min.js for details. | 560 // and licensed under the MIT license. See jquery-*.min.js for details. |
488 function removeDotSegments(u) { | 561 function removeDotSegments(u) { |
489 var r = '', m = []; | 562 var r = '', m = []; |
490 if (/\./.test(u)) { | 563 if (/\./.test(u)) { |
491 while (u !== undefined && u !== '') { | 564 while (u !== undefined && u !== '') { |
492 if (u === '.' || u === '..') { | 565 if (u === '.' || u === '..') { |
493 u = ''; | 566 u = ''; |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
674 break; | 747 break; |
675 default: | 748 default: |
676 sendResponse({}); | 749 sendResponse({}); |
677 break; | 750 break; |
678 } | 751 } |
679 }); | 752 }); |
680 | 753 |
681 if (window == window.top) | 754 if (window == window.top) |
682 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 755 ext.backgroundPage.sendMessage({type: "report-html-page"}); |
683 } | 756 } |
OLD | NEW |