| 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 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 { | 178 { | 
| 179 Array.prototype.forEach.call( | 179 Array.prototype.forEach.call( | 
| 180 document.querySelectorAll(highlightedElementsSelector), | 180 document.querySelectorAll(highlightedElementsSelector), | 
| 181 unhighlightElement | 181 unhighlightElement | 
| 182 ); | 182 ); | 
| 183 | 183 | 
| 184 highlightedElementsSelector = null; | 184 highlightedElementsSelector = null; | 
| 185 } | 185 } | 
| 186 } | 186 } | 
| 187 | 187 | 
| 188 function getURLsFromObjectElement(element) | |
| 189 { | |
| 190 var url = element.getAttribute("data"); | |
| 191 if (url) | |
| 192 return [resolveURL(url)]; | |
| 193 | |
| 194 for (var i = 0; i < element.children.length; i++) | |
| 195 { | |
| 196 var child = element.children[i]; | |
| 197 if (child.localName != "param") | |
| 198 continue; | |
| 199 | |
| 200 var name = child.getAttribute("name"); | |
| 201 if (name != "movie" && // Adobe Flash | |
| 202 name != "source" && // Silverlight | |
| 203 name != "src" && // Real Media + Quicktime | |
| 204 name != "FileName") // Windows Media | |
| 205 continue; | |
| 206 | |
| 207 var value = child.getAttribute("value"); | |
| 208 if (!value) | |
| 209 continue; | |
| 210 | |
| 211 return [resolveURL(value)]; | |
| 212 } | |
| 213 | |
| 214 return []; | |
| 215 } | |
| 216 | |
| 217 function getURLsFromAttributes(element) | |
| 218 { | |
| 219 var urls = []; | |
| 220 | |
| 221 if (element.src) | |
| 222 urls.push(element.src); | |
| 223 | |
| 224 if (element.srcset) | |
| 225 { | |
| 226 var candidates = element.srcset.split(","); | |
| 227 for (var i = 0; i < candidates.length; i++) | |
| 228 { | |
| 229 var url = candidates[i].trim().replace(/\s+\S+$/, ""); | |
| 230 if (url) | |
| 231 urls.push(resolveURL(url)); | |
| 232 } | |
| 233 } | |
| 234 | |
| 235 return urls; | |
| 236 } | |
| 237 | |
| 238 function getURLsFromMediaElement(element) | |
| 239 { | |
| 240 var urls = getURLsFromAttributes(element); | |
| 241 | |
| 242 for (var i = 0; i < element.children.length; i++) | |
| 243 { | |
| 244 var child = element.children[i]; | |
| 245 if (child.localName != "source" || child.localName != "track") | |
| 
 
Wladimir Palant
2014/12/08 20:31:09
This should be == rather than !=, right? Currently
 
Sebastian Noack
2014/12/08 21:12:49
Ouch, you are right. Originally, it was in the for
 
 | |
| 246 urls.push.apply(urls, getURLsFromAttributes(child)); | |
| 
 
Wladimir Palant
2014/12/08 20:31:09
I think for the <track> element you need to call g
 
Sebastian Noack
2014/12/08 21:12:49
If I didn't misread the standard, a <track> elemen
 
Wladimir Palant
2014/12/09 08:27:21
It seems that I indeed misunderstood the standard,
 
 | |
| 247 } | |
| 248 | |
| 249 if (element.poster) | |
| 250 urls.push(element.poster); | |
| 251 | |
| 252 return urls; | |
| 253 } | |
| 254 | |
| 255 function getURLsFromElement(element) { | |
| 256 switch (element.localName) | |
| 257 { | |
| 258 case "object": | |
| 259 return getURLsFromObjectElement(element); | |
| 260 | |
| 261 case "video": | |
| 262 case "audio": | |
| 263 case "picture": | |
| 264 return getURLsFromMediaElement(element); | |
| 265 } | |
| 266 | |
| 267 return getURLsFromAttributes(element); | |
| 268 } | |
| 269 | |
| 270 function isBlockable(element) | |
| 271 { | |
| 272 if (element.id) | |
| 273 return true; | |
| 274 if (element.classList.length > 0) | |
| 275 return true; | |
| 276 if (getURLsFromElement(element).length > 0) | |
| 277 return true; | |
| 278 | |
| 279 // We only generate filters based on the "style" attribute, | |
| 280 // if this is the only way we can generate a filter, and | |
| 281 // only if there are at least two CSS properties defined. | |
| 282 if (/:.+:/.test(getOriginalStyle(element))) | |
| 283 return true; | |
| 284 | |
| 285 return false; | |
| 286 } | |
| 287 | |
| 188 // Gets the absolute position of an element by walking up the DOM tree, | 288 // Gets the absolute position of an element by walking up the DOM tree, | 
| 189 // adding up offsets. | 289 // adding up offsets. | 
| 190 // I hope there's a better way because it just seems absolutely stupid | 290 // I hope there's a better way because it just seems absolutely stupid | 
| 191 // that the DOM wouldn't have a direct way to get this, given that it | 291 // that the DOM wouldn't have a direct way to get this, given that it | 
| 192 // has hundreds and hundreds of other methods that do random junk. | 292 // has hundreds and hundreds of other methods that do random junk. | 
| 193 function getAbsolutePosition(elt) { | 293 function getAbsolutePosition(elt) { | 
| 194 var l = 0; | 294 var l = 0; | 
| 195 var t = 0; | 295 var t = 0; | 
| 196 for(; elt; elt = elt.offsetParent) { | 296 for(; elt; elt = elt.offsetParent) { | 
| 197 l += elt.offsetLeft; | 297 l += elt.offsetLeft; | 
| 198 t += elt.offsetTop; | 298 t += elt.offsetTop; | 
| 199 } | 299 } | 
| 200 return [l, t]; | 300 return [l, t]; | 
| 201 } | 301 } | 
| 202 | 302 | 
| 203 // Adds an overlay to an element, which is probably a Flash object | 303 // Adds an overlay to an element, which is probably a Flash object | 
| 204 function addElementOverlay(elt) { | 304 function addElementOverlay(elt) { | 
| 205 // If this element is enclosed in an object tag, we prefer to block that inste ad | 305 // If this element is enclosed in an object tag, we prefer to block that inste ad | 
| 206 if(!elt) | 306 if(!elt) | 
| 207 return null; | 307 return null; | 
| 208 | 308 | 
| 209 // If element doesn't have at least one of class name, ID or URL, give up | 309 // If element doesn't have at least one of class name, ID or URL, give up | 
| 210 // because we don't know how to construct a filter rule for it | 310 // because we don't know how to construct a filter rule for it | 
| 211 var url = getElementURL(elt); | 311 if(!isBlockable(elt)) | 
| 212 if(!elt.className && !elt.id && !url) | |
| 213 return; | 312 return; | 
| 214 | 313 | 
| 215 // If the element isn't rendered (since its or one of its ancestor's | 314 // If the element isn't rendered (since its or one of its ancestor's | 
| 216 // "display" property is "none"), the overlay wouldn't match the element. | 315 // "display" property is "none"), the overlay wouldn't match the element. | 
| 217 if (!elt.offsetParent) | 316 if (!elt.offsetParent) | 
| 218 return; | 317 return; | 
| 219 | 318 | 
| 220 var thisStyle = getComputedStyle(elt, null); | 319 var thisStyle = getComputedStyle(elt, null); | 
| 221 var overlay = document.createElement('div'); | 320 var overlay = document.createElement('div'); | 
| 222 overlay.prisoner = elt; | 321 overlay.prisoner = elt; | 
| 223 overlay.prisonerURL = url; | |
| 224 overlay.className = "__adblockplus__overlay"; | 322 overlay.className = "__adblockplus__overlay"; | 
| 225 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;'); | 323 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;'); | 
| 226 var pos = getAbsolutePosition(elt); | 324 var pos = getAbsolutePosition(elt); | 
| 227 overlay.style.left = pos[0] + "px"; | 325 overlay.style.left = pos[0] + "px"; | 
| 228 overlay.style.top = pos[1] + "px"; | 326 overlay.style.top = pos[1] + "px"; | 
| 229 | 327 | 
| 230 if (thisStyle.position != "static") | 328 if (thisStyle.position != "static") | 
| 231 overlay.style.zIndex = thisStyle.zIndex; | 329 overlay.style.zIndex = thisStyle.zIndex; | 
| 232 else | 330 else | 
| 233 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; | 331 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; | 
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 // Turn on the choose element to create filter thing | 374 // Turn on the choose element to create filter thing | 
| 277 function clickHide_activate() { | 375 function clickHide_activate() { | 
| 278 if(document == null) | 376 if(document == null) | 
| 279 return; | 377 return; | 
| 280 | 378 | 
| 281 // If we are already selecting, abort now | 379 // If we are already selecting, abort now | 
| 282 if (clickHide_activated || clickHideFiltersDialog) | 380 if (clickHide_activated || clickHideFiltersDialog) | 
| 283 clickHide_deactivate(); | 381 clickHide_deactivate(); | 
| 284 | 382 | 
| 285 // Add overlays for elements with URLs so user can easily click them | 383 // Add overlays for elements with URLs so user can easily click them | 
| 286 var elts = document.querySelectorAll('object,embed,img,iframe'); | 384 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure'); | 
| 287 for(var i=0; i<elts.length; i++) | 385 for(var i=0; i<elts.length; i++) | 
| 288 addElementOverlay(elts[i]); | 386 addElementOverlay(elts[i]); | 
| 289 | 387 | 
| 290 clickHide_activated = true; | 388 clickHide_activated = true; | 
| 291 document.addEventListener("mouseover", clickHide_mouseOver, true); | 389 document.addEventListener("mouseover", clickHide_mouseOver, true); | 
| 292 document.addEventListener("mouseout", clickHide_mouseOut, true); | 390 document.addEventListener("mouseout", clickHide_mouseOut, true); | 
| 293 document.addEventListener("click", clickHide_mouseClick, true); | 391 document.addEventListener("click", clickHide_mouseClick, true); | 
| 294 document.addEventListener("keydown", clickHide_keyDown, true); | 392 document.addEventListener("keydown", clickHide_keyDown, true); | 
| 295 } | 393 } | 
| 296 | 394 | 
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 345 clickHide_mouseClick(ev); | 443 clickHide_mouseClick(ev); | 
| 346 } | 444 } | 
| 347 | 445 | 
| 348 // Hovering over an element so highlight it | 446 // Hovering over an element so highlight it | 
| 349 function clickHide_mouseOver(e) | 447 function clickHide_mouseOver(e) | 
| 350 { | 448 { | 
| 351 if (clickHide_activated == false) | 449 if (clickHide_activated == false) | 
| 352 return; | 450 return; | 
| 353 | 451 | 
| 354 var target = e.target; | 452 var target = e.target; | 
| 355 while (target.parentNode && !(target.id || target.className || target.src || / :.+:/.test(getOriginalStyle(target)))) | 453 while (target.parentNode && !isBlockable(target)) | 
| 356 target = target.parentNode; | 454 target = target.parentNode; | 
| 357 if (target == document.documentElement || target == document.body) | 455 if (target == document.documentElement || target == document.body) | 
| 358 target = null; | 456 target = null; | 
| 359 | 457 | 
| 360 if (target && target instanceof HTMLElement) | 458 if (target && target instanceof HTMLElement) | 
| 361 { | 459 { | 
| 362 currentElement = target; | 460 currentElement = target; | 
| 363 | 461 | 
| 364 highlightElement(target, "#d6d84b", "#f8fa47"); | 462 highlightElement(target, "#d6d84b", "#f8fa47"); | 
| 365 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 463 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 398 | 496 | 
| 399 // When the user clicks, the currentElement is the one we want. | 497 // When the user clicks, the currentElement is the one we want. | 
| 400 // We should have ABP rules ready for when the | 498 // We should have ABP rules ready for when the | 
| 401 // popup asks for them. | 499 // popup asks for them. | 
| 402 function clickHide_mouseClick(e) | 500 function clickHide_mouseClick(e) | 
| 403 { | 501 { | 
| 404 if (!currentElement || !clickHide_activated) | 502 if (!currentElement || !clickHide_activated) | 
| 405 return; | 503 return; | 
| 406 | 504 | 
| 407 var elt = currentElement; | 505 var elt = currentElement; | 
| 408 var url = null; | |
| 409 if (currentElement.classList.contains("__adblockplus__overlay")) | 506 if (currentElement.classList.contains("__adblockplus__overlay")) | 
| 410 { | |
| 411 elt = currentElement.prisoner; | 507 elt = currentElement.prisoner; | 
| 412 url = currentElement.prisonerURL; | |
| 413 } | |
| 414 else if (elt.src) | |
| 415 url = elt.src; | |
| 416 | 508 | 
| 417 clickHideFilters = new Array(); | 509 clickHideFilters = new Array(); | 
| 418 selectorList = new Array(); | 510 selectorList = new Array(); | 
| 419 | 511 | 
| 420 var addSelector = function(selector) | 512 var addSelector = function(selector) | 
| 421 { | 513 { | 
| 514 if (selectorList.indexOf(selector) != -1) | |
| 515 return; | |
| 516 | |
| 422 clickHideFilters.push(document.domain + "##" + selector); | 517 clickHideFilters.push(document.domain + "##" + selector); | 
| 423 selectorList.push(selector); | 518 selectorList.push(selector); | 
| 424 }; | 519 }; | 
| 425 | 520 | 
| 426 if (elt.id) | 521 if (elt.id) | 
| 427 addSelector("#" + escapeCSS(elt.id)); | 522 addSelector("#" + escapeCSS(elt.id)); | 
| 428 | 523 | 
| 429 if (elt.classList.length > 0) | 524 if (elt.classList.length > 0) | 
| 430 { | 525 { | 
| 431 var selector = ""; | 526 var selector = ""; | 
| 432 | 527 | 
| 433 for (var i = 0; i < elt.classList.length; i++) | 528 for (var i = 0; i < elt.classList.length; i++) | 
| 434 selector += "." + escapeCSS(elt.classList[i]); | 529 selector += "." + escapeCSS(elt.classList[i]); | 
| 435 | 530 | 
| 436 addSelector(selector); | 531 addSelector(selector); | 
| 437 } | 532 } | 
| 438 | 533 | 
| 439 if (url) | 534 var urls = getURLsFromElement(elt); | 
| 535 for (var i = 0; i < urls.length; i++) | |
| 440 { | 536 { | 
| 441 var src = elt.getAttribute("src"); | 537 var url = urls[i]; | 
| 442 var selector = src && escapeCSS(elt.localName) + '[src=' + quote(src) + ']'; | |
| 443 | 538 | 
| 444 if (/^https?:/i.test(url)) | 539 if (/^https?:/i.test(url)) | 
| 445 { | 540 { | 
| 446 clickHideFilters.push(url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||")); | 541 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); | 
| 447 | 542 | 
| 448 if (selector) | 543 if (clickHideFilters.indexOf(filter) == -1) | 
| 449 selectorList.push(selector); | 544 clickHideFilters.push(filter); | 
| 545 | |
| 546 continue; | |
| 450 } | 547 } | 
| 451 else if (selector) | 548 | 
| 452 addSelector(selector); | 549 if (url == elt.src) | 
| 550 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']'); | |
| 453 } | 551 } | 
| 454 | 552 | 
| 455 // as last resort, create a filter based on inline styles | 553 // as last resort, create a filter based on inline styles | 
| 456 if (clickHideFilters.length == 0) | 554 if (clickHideFilters.length == 0) | 
| 457 { | 555 { | 
| 458 var style = getOriginalStyle(elt); | 556 var style = getOriginalStyle(elt); | 
| 459 if (style) | 557 if (style) | 
| 460 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 558 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); | 
| 461 } | 559 } | 
| 462 | 560 | 
| 463 // Show popup | 561 // Show popup | 
| 464 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 562 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); | 
| 465 | 563 | 
| 466 // Highlight the elements specified by selector in yellow | 564 // Highlight the elements specified by selector in yellow | 
| 467 if (selectorList.length > 0) | 565 if (selectorList.length > 0) | 
| 468 highlightElements(selectorList.join(",")); | 566 highlightElements(selectorList.join(",")); | 
| 469 // Now, actually highlight the element the user clicked on in red | 567 // Now, actually highlight the element the user clicked on in red | 
| 470 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 568 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | 
| 471 | 569 | 
| 472 // Make sure the browser doesn't handle this click | 570 // Make sure the browser doesn't handle this click | 
| 473 e.preventDefault(); | 571 e.preventDefault(); | 
| 474 e.stopPropagation(); | 572 e.stopPropagation(); | 
| 475 } | 573 } | 
| 476 | 574 | 
| 477 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME | |
| 478 function getElementURL(elt) { | |
| 479 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL | |
| 480 // in value attribute | |
| 481 var url; | |
| 482 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data") )) { | |
| 483 // No data attribute, look in PARAM child tags for a URL for the swf file | |
| 484 var params = elt.querySelectorAll("param[name=\"movie\"]"); | |
| 485 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL | |
| 486 if(params[0]) | |
| 487 url = params[0].getAttribute("value"); | |
| 488 else { | |
| 489 params = elt.querySelectorAll("param[name=\"src\"]"); | |
| 490 if(params[0]) | |
| 491 url = params[0].getAttribute("value"); | |
| 492 } | |
| 493 | |
| 494 if (url) | |
| 495 url = resolveURL(url); | |
| 496 } else if(!url) { | |
| 497 url = elt.src || elt.href; | |
| 498 } | |
| 499 return url; | |
| 500 } | |
| 501 | |
| 502 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 575 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 
| 503 // and licensed under the MIT license. See jquery-*.min.js for details. | 576 // and licensed under the MIT license. See jquery-*.min.js for details. | 
| 504 function removeDotSegments(u) { | 577 function removeDotSegments(u) { | 
| 505 var r = '', m = []; | 578 var r = '', m = []; | 
| 506 if (/\./.test(u)) { | 579 if (/\./.test(u)) { | 
| 507 while (u !== undefined && u !== '') { | 580 while (u !== undefined && u !== '') { | 
| 508 if (u === '.' || u === '..') { | 581 if (u === '.' || u === '..') { | 
| 509 u = ''; | 582 u = ''; | 
| 510 } else if (/^\.\.\//.test(u)) { // starts with ../ | 583 } else if (/^\.\.\//.test(u)) { // starts with ../ | 
| 511 u = u.substring(3); | 584 u = u.substring(3); | 
| (...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 break; | 764 break; | 
| 692 default: | 765 default: | 
| 693 sendResponse({}); | 766 sendResponse({}); | 
| 694 break; | 767 break; | 
| 695 } | 768 } | 
| 696 }); | 769 }); | 
| 697 | 770 | 
| 698 if (window == window.top) | 771 if (window == window.top) | 
| 699 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 772 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 
| 700 } | 773 } | 
| OLD | NEW |