| 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 |