| 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, false); | 271 document.addEventListener("mouseover", clickHide_mouseOver, false); |
| 274 document.addEventListener("mouseout", clickHide_mouseOut, false); | 272 document.addEventListener("mouseout", clickHide_mouseOut, false); |
| 275 document.addEventListener("click", clickHide_mouseClick, false); | 273 document.addEventListener("click", clickHide_mouseClick, false); |
| 276 document.addEventListener("keydown", clickHide_keyDown, false); | 274 document.addEventListener("keydown", clickHide_keyDown, false); |
| 277 } | 275 } |
| 278 | 276 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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, false) ; | 344 target.addEventListener("contextmenu", clickHide_elementClickHandler, false) ; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 370 payload: | 368 payload: |
| 371 { | 369 { |
| 372 type: "clickhide-deactivate" | 370 type: "clickhide-deactivate" |
| 373 } | 371 } |
| 374 }); | 372 }); |
| 375 e.preventDefault(); | 373 e.preventDefault(); |
| 376 e.stopPropagation(); | 374 e.stopPropagation(); |
| 377 } | 375 } |
| 378 } | 376 } |
| 379 | 377 |
| 378 | |
| 379 | |
| 380 // When the user clicks, the currentElement is the one we want. | 380 // When the user clicks, the currentElement is the one we want. |
| 381 // We should have ABP rules ready for when the | 381 // We should have ABP rules ready for when the |
| 382 // popup asks for them. | 382 // popup asks for them. |
| 383 function clickHide_mouseClick(e) | 383 function clickHide_mouseClick(e) |
| 384 { | 384 { |
| 385 if (!currentElement || !clickHide_activated) | 385 if (!currentElement || !clickHide_activated) |
| 386 return; | 386 return; |
| 387 | 387 |
| 388 var elt = currentElement; | 388 var elt = currentElement; |
| 389 var url = null; | |
| 390 if (currentElement.classList.contains("__adblockplus__overlay")) | 389 if (currentElement.classList.contains("__adblockplus__overlay")) |
| 391 { | |
| 392 elt = currentElement.prisoner; | 390 elt = currentElement.prisoner; |
| 393 url = currentElement.prisonerURL; | |
| 394 } | |
| 395 else if (elt.src) | |
| 396 url = elt.src; | |
| 397 | 391 |
| 398 clickHideFilters = new Array(); | 392 clickHideFilters = new Array(); |
| 399 selectorList = new Array(); | 393 selectorList = new Array(); |
| 400 | 394 |
| 401 var addSelector = function(selector) | 395 var addSelector = function(selector) |
|
kzar
2014/11/25 18:10:11
Why we don't just do "function addSelector(selecto
Sebastian Noack
2014/11/25 19:01:15
The only reason that comes to my mind would be tha
| |
| 402 { | 396 { |
| 397 if (selectorList.indexOf(selector) != -1) | |
| 398 return; | |
| 399 | |
| 403 clickHideFilters.push(document.domain + "##" + selector); | 400 clickHideFilters.push(document.domain + "##" + selector); |
| 404 selectorList.push(selector); | 401 selectorList.push(selector); |
| 405 }; | 402 }; |
| 406 | 403 |
| 407 if (elt.id) | 404 if (elt.id) |
| 408 addSelector("#" + escapeCSS(elt.id)); | 405 addSelector("#" + escapeCSS(elt.id)); |
| 409 | 406 |
| 410 if (elt.classList.length > 0) | 407 if (elt.classList.length > 0) |
| 411 { | 408 { |
| 412 var selector = ""; | 409 var selector = ""; |
| 413 | 410 |
| 414 for (var i = 0; i < elt.classList.length; i++) | 411 for (var i = 0; i < elt.classList.length; i++) |
| 415 selector += "." + escapeCSS(elt.classList[i]); | 412 selector += "." + escapeCSS(elt.classList[i]); |
| 416 | 413 |
| 417 addSelector(selector); | 414 addSelector(selector); |
| 418 } | 415 } |
| 419 | 416 |
| 420 if (url) | 417 var urls = getElementURLs(elt); |
| 418 for (var i = 0; i < urls.length; i++) | |
| 421 { | 419 { |
| 422 var src = elt.getAttribute("src"); | 420 var url = urls[i]; |
| 423 var selector = src && escapeCSS(elt.localName) + '[src=' + quote(src) + ']'; | 421 var isHTTP = /^https?:/i.test(url); |
| 424 | 422 |
| 425 if (/^https?:/i.test(url)) | 423 if (isHTTP) |
|
kzar
2014/11/25 18:10:11
I found this line a little bit confusing to start
Sebastian Noack
2014/11/25 19:01:15
What I actually want, is excluding URLs that can't
| |
| 426 { | 424 { |
| 427 clickHideFilters.push(url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||")); | 425 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
| 428 | 426 |
| 429 if (selector) | 427 if (clickHideFilters.indexOf(filter) != -1) |
| 428 continue; | |
| 429 | |
| 430 clickHideFilters.push(filter); | |
| 431 } | |
| 432 | |
| 433 if (url == elt.src) | |
| 434 { | |
| 435 var selector = escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute ("src")) + ']'; | |
| 436 | |
| 437 if (isHTTP) | |
| 430 selectorList.push(selector); | 438 selectorList.push(selector); |
| 439 else | |
| 440 addSelector(selector); | |
| 431 } | 441 } |
| 432 else if (selector) | |
| 433 addSelector(selector); | |
| 434 } | 442 } |
| 435 | 443 |
| 436 // restore the original style, before generating the fallback filter that | 444 // restore the original style, before generating the fallback filter that |
| 437 // will include the style, and to prevent highlightElements from saving those | 445 // will include the style, and to prevent highlightElements from saving those |
| 438 unhighlightElement(currentElement); | 446 unhighlightElement(currentElement); |
| 439 | 447 |
| 440 // as last resort, create a filter based on inline styles | 448 // as last resort, create a filter based on inline styles |
| 441 if (clickHideFilters.length == 0) | 449 if (clickHideFilters.length == 0) |
| 442 { | 450 { |
| 443 var style = elt.getAttribute("style"); | 451 var style = elt.getAttribute("style"); |
| 444 if (style) | 452 if (style) |
| 445 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 453 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); |
| 446 } | 454 } |
| 447 | 455 |
| 448 // Show popup | 456 // Show popup |
| 449 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 457 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); |
| 450 | 458 |
| 451 // Highlight the elements specified by selector in yellow | 459 // Highlight the elements specified by selector in yellow |
| 452 highlightElements(selectorList.join(",")); | 460 highlightElements(selectorList.join(",")); |
| 453 // Now, actually highlight the element the user clicked on in red | 461 // Now, actually highlight the element the user clicked on in red |
| 454 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 462 highlightElement(currentElement, "#fd1708", "#f6a1b5"); |
| 455 | 463 |
| 456 // Make sure the browser doesn't handle this click | 464 // Make sure the browser doesn't handle this click |
| 457 e.preventDefault(); | 465 e.preventDefault(); |
| 458 e.stopPropagation(); | 466 e.stopPropagation(); |
| 459 } | 467 } |
| 460 | 468 |
| 461 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME | 469 function parseSrcSet(element) |
| 462 function getElementURL(elt) { | 470 { |
| 463 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL | 471 if (!element.srcset) |
| 464 // in value attribute | 472 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 | 473 |
| 474 var urls = element.srcset.split(","); | |
| 475 for (var i = 0; i < urls.length; i++) | |
| 476 { | |
| 477 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, ""); | |
| 478 if (url) | 478 if (url) |
| 479 url = resolveURL(url); | 479 urls[i] = resolveURL(url); |
| 480 } else if(!url) { | 480 else |
| 481 url = elt.src || elt.href; | 481 urls.splice(i--, 1); |
|
kzar
2014/11/25 18:10:11
Does removing an element from the array you're ite
Sebastian Noack
2014/11/25 19:01:15
Not as long as you decrease the iteration counter
Sebastian Noack
2014/11/25 19:03:11
s/is problamatic/isn't problamatic/
| |
| 482 } | 482 } |
| 483 return url; | 483 |
| 484 return urls; | |
| 485 } | |
| 486 | |
| 487 function getElementURLs(elt) { | |
| 488 var urls = []; | |
| 489 | |
| 490 if (elt.src) | |
| 491 urls.push(elt.src); | |
| 492 | |
| 493 switch (elt.localName) | |
| 494 { | |
| 495 case "object": | |
| 496 var url = elt.getAttribute("data"); | |
| 497 if (url) | |
| 498 return [resolveURL(url)]; | |
| 499 | |
| 500 for (var i = 0; i < elt.children.length; i++) | |
| 501 { | |
| 502 var child = elt.children[i]; | |
| 503 if (child.localName != "param") | |
| 504 continue; | |
| 505 | |
| 506 var name = child.getAttribute("name"); | |
| 507 if (name != "movie" && name != "src") | |
| 508 continue; | |
| 509 | |
| 510 var value = child.getAttribute("value"); | |
| 511 if (!value) | |
| 512 continue; | |
| 513 | |
| 514 return [resolveURL(value)]; | |
| 515 } | |
| 516 | |
| 517 return []; | |
| 518 | |
| 519 case "video": | |
| 520 case "audio": | |
| 521 case "picture": | |
| 522 for (var i = 0; i < elt.children.length; i++) | |
| 523 { | |
| 524 var child = elt.children[i]; | |
| 525 | |
| 526 if (child.localName != "source") | |
| 527 continue; | |
| 528 | |
| 529 if (child.src) | |
| 530 urls.push(child.src); | |
| 531 | |
| 532 urls = urls.concat(parseSrcSet(child)); | |
| 533 } | |
| 534 | |
| 535 break; | |
| 536 | |
| 537 case "img": | |
| 538 urls = urls.concat(parseSrcSet(elt)); | |
| 539 } | |
| 540 | |
| 541 return urls; | |
| 542 } | |
| 543 | |
| 544 function hasFilters(element) | |
|
kzar
2014/11/26 10:51:22
Maybe a name like "isFilterable" would be better t
kzar
2014/11/26 10:51:22
How come you don't put this function above where i
Sebastian Noack
2014/11/26 11:08:14
As discussed on IRC, it's called "isBlockable" now
Sebastian Noack
2014/11/26 11:08:14
Since it relies on "getElementURLs()", I just put
| |
| 545 { | |
| 546 if (element.id) | |
| 547 return true; | |
| 548 if (element.classList.length > 0) | |
| 549 return true; | |
| 550 if (getElementURLs(element).length > 0) | |
| 551 return true; | |
| 552 if (/:.+:/.test(element.getAttribute("style"))) | |
|
kzar
2014/11/26 10:51:22
Maybe comment this line to explain what you told m
Sebastian Noack
2014/11/26 11:08:14
Well, this logic isn't new. But I guess I can add
| |
| 553 return true; | |
| 554 | |
| 555 return false; | |
| 484 } | 556 } |
| 485 | 557 |
| 486 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 558 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js |
| 487 // and licensed under the MIT license. See jquery-*.min.js for details. | 559 // and licensed under the MIT license. See jquery-*.min.js for details. |
| 488 function removeDotSegments(u) { | 560 function removeDotSegments(u) { |
| 489 var r = '', m = []; | 561 var r = '', m = []; |
| 490 if (/\./.test(u)) { | 562 if (/\./.test(u)) { |
| 491 while (u !== undefined && u !== '') { | 563 while (u !== undefined && u !== '') { |
| 492 if (u === '.' || u === '..') { | 564 if (u === '.' || u === '..') { |
| 493 u = ''; | 565 u = ''; |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 674 break; | 746 break; |
| 675 default: | 747 default: |
| 676 sendResponse({}); | 748 sendResponse({}); |
| 677 break; | 749 break; |
| 678 } | 750 } |
| 679 }); | 751 }); |
| 680 | 752 |
| 681 if (window == window.top) | 753 if (window == window.top) |
| 682 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 754 ext.backgroundPage.sendMessage({type: "report-html-page"}); |
| 683 } | 755 } |
| OLD | NEW |