| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 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"); | |
| 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; | |
| 219 | |
| 220 if (child.src) | |
| 221 urls.push(child.src); | |
| 222 | |
| 223 urls = urls.concat(parseSrcSet(child)); | |
| 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 if(!hasFilters(elt)) | 279 if(!isBlockable(elt)) |
| 202 return; | 280 return; |
| 281 | |
| 282 // If the element isn't rendered (since its or one of its ancestor's | |
| 283 // "diplay" property is "none"), the overlay wouldn't match the element. | |
| 284 if (!elt.offsetParent) | |
| 285 return; | |
| 286 | |
| 203 var thisStyle = getComputedStyle(elt, null); | 287 var thisStyle = getComputedStyle(elt, null); |
| 204 var overlay = document.createElement('div'); | 288 var overlay = document.createElement('div'); |
| 205 overlay.prisoner = elt; | 289 overlay.prisoner = elt; |
| 206 overlay.className = "__adblockplus__overlay"; | 290 overlay.className = "__adblockplus__overlay"; |
| 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'); | 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;'); |
| 208 var pos = getAbsolutePosition(elt); | 292 var pos = getAbsolutePosition(elt); |
| 209 overlay.style.left = pos[0] + "px"; | 293 overlay.style.left = pos[0] + "px"; |
| 210 overlay.style.top = pos[1] + "px"; | 294 overlay.style.top = pos[1] + "px"; |
| 295 | |
| 296 if (thisStyle.position != "static") | |
| 297 overlay.style.zIndex = thisStyle.zIndex; | |
| 298 else | |
| 299 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex; | |
| 300 | |
| 211 // elt.parentNode.appendChild(overlay, elt); | 301 // elt.parentNode.appendChild(overlay, elt); |
| 212 document.body.appendChild(overlay); | 302 document.body.appendChild(overlay); |
| 213 return overlay; | 303 return overlay; |
| 214 } | 304 } |
| 215 | 305 |
| 216 // Show dialog asking user whether she wants to add the proposed filters derived | 306 // Show dialog asking user whether she wants to add the proposed filters derived |
| 217 // from selected page element | 307 // from selected page element |
| 218 function clickHide_showDialog(left, top, filters) | 308 function clickHide_showDialog(left, top, filters) |
| 219 { | 309 { |
| 220 // If we are already selecting, abort now | 310 // If we are already selecting, abort now |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 // on whether the user actually wants these filters | 364 // on whether the user actually wants these filters |
| 275 function clickHide_rulesPending() { | 365 function clickHide_rulesPending() { |
| 276 clickHide_activated = false; | 366 clickHide_activated = false; |
| 277 document.removeEventListener("mouseover", clickHide_mouseOver, true); | 367 document.removeEventListener("mouseover", clickHide_mouseOver, true); |
| 278 document.removeEventListener("mouseout", clickHide_mouseOut, true); | 368 document.removeEventListener("mouseout", clickHide_mouseOut, true); |
| 279 document.removeEventListener("click", clickHide_mouseClick, true); | 369 document.removeEventListener("click", clickHide_mouseClick, true); |
| 280 document.removeEventListener("keydown", clickHide_keyDown, true); | 370 document.removeEventListener("keydown", clickHide_keyDown, true); |
| 281 } | 371 } |
| 282 | 372 |
| 283 // Turn off click-to-hide | 373 // Turn off click-to-hide |
| 284 function clickHide_deactivate(keepOverlays) | 374 function clickHide_deactivate(keepOverlays) |
|
kzar
2014/11/26 14:14:04
We're relying on the legacy code not passing this
Sebastian Noack
2014/11/26 14:41:39
Correct. I tried to keep the patch as compact as p
| |
| 285 { | 375 { |
| 286 if (clickHideFiltersDialog) | 376 if (clickHideFiltersDialog) |
| 287 { | 377 { |
| 288 document.body.removeChild(clickHideFiltersDialog); | 378 document.body.removeChild(clickHideFiltersDialog); |
| 289 clickHideFiltersDialog = null; | 379 clickHideFiltersDialog = null; |
| 290 } | 380 } |
| 291 | 381 |
| 292 clickHide_activated = false; | 382 clickHide_activated = false; |
| 293 clickHide_filters = null; | 383 clickHide_filters = null; |
| 294 if(!document) | 384 if(!document) |
| 295 return; // This can happen inside a nuked iframe...I think | 385 return; // This can happen inside a nuked iframe...I think |
| 296 document.removeEventListener("mouseover", clickHide_mouseOver, true); | 386 document.removeEventListener("mouseover", clickHide_mouseOver, true); |
| 297 document.removeEventListener("mouseout", clickHide_mouseOut, true); | 387 document.removeEventListener("mouseout", clickHide_mouseOut, true); |
| 298 document.removeEventListener("click", clickHide_mouseClick, true); | 388 document.removeEventListener("click", clickHide_mouseClick, true); |
| 299 document.removeEventListener("keydown", clickHide_keyDown, true); | 389 document.removeEventListener("keydown", clickHide_keyDown, true); |
| 300 | 390 |
| 301 if (!keepOverlays) | 391 if (!keepOverlays) |
| 302 { | 392 { |
| 303 if(currentElement) { | 393 if (currentElement) { |
|
kzar
2014/11/26 14:14:04
Nitpick: Should be space between "if" and "("?
Sebastian Noack
2014/11/26 14:41:39
I just copied the code from above, but I have adde
| |
| 304 currentElement.removeEventListener("contextmenu", clickHide_elementClickHa ndler, false); | 394 currentElement.removeEventListener("contextmenu", clickHide_elementClickH andler, true); |
|
kzar
2014/11/26 14:14:04
Last parameter should be true?
Sebastian Noack
2014/11/26 14:41:39
Yes, this patch was created on top of a version, w
| |
| 305 unhighlightElements(); | 395 unhighlightElements(); |
| 306 unhighlightElement(currentElement); | 396 unhighlightElement(currentElement); |
| 307 currentElement = null; | 397 currentElement = null; |
| 308 clickHideFilters = null; | 398 clickHideFilters = null; |
| 309 } | 399 } |
| 310 unhighlightElements(); | 400 unhighlightElements(); |
| 311 | 401 |
| 312 var overlays = document.getElementsByClassName("__adblockplus__overlay"); | 402 var overlays = document.getElementsByClassName("__adblockplus__overlay"); |
| 313 while (overlays.length > 0) | 403 while (overlays.length > 0) |
| 314 overlays[0].parentNode.removeChild(overlays[0]); | 404 overlays[0].parentNode.removeChild(overlays[0]); |
| 315 } | 405 } |
| 316 } | 406 } |
| 317 | 407 |
| 318 function clickHide_elementClickHandler(ev) { | 408 function clickHide_elementClickHandler(ev) { |
| 319 ev.preventDefault(); | 409 ev.preventDefault(); |
| 320 ev.stopPropagation(); | 410 ev.stopPropagation(); |
| 321 clickHide_mouseClick(ev); | 411 clickHide_mouseClick(ev); |
| 322 } | 412 } |
| 323 | 413 |
| 324 // Hovering over an element so highlight it | 414 // Hovering over an element so highlight it |
| 325 function clickHide_mouseOver(e) | 415 function clickHide_mouseOver(e) |
| 326 { | 416 { |
| 327 if (clickHide_activated == false) | 417 if (clickHide_activated == false) |
| 328 return; | 418 return; |
| 329 | 419 |
| 330 var target = e.target; | 420 var target = e.target; |
| 331 while (target.parentNode && !hasFilters(target)) | 421 while (target.parentNode && !isBlockable(target)) |
| 332 target = target.parentNode; | 422 target = target.parentNode; |
| 333 if (target == document.documentElement || target == document.body) | 423 if (target == document.documentElement || target == document.body) |
| 334 target = null; | 424 target = null; |
| 335 | 425 |
| 336 if (target && target instanceof HTMLElement) | 426 if (target && target instanceof HTMLElement) |
| 337 { | 427 { |
| 338 currentElement = target; | 428 currentElement = target; |
| 339 | 429 |
| 340 highlightElement(target, "#d6d84b", "#f8fa47"); | 430 highlightElement(target, "#d6d84b", "#f8fa47"); |
| 341 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 431 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 365 payload: | 455 payload: |
| 366 { | 456 { |
| 367 type: "clickhide-deactivate" | 457 type: "clickhide-deactivate" |
| 368 } | 458 } |
| 369 }); | 459 }); |
| 370 e.preventDefault(); | 460 e.preventDefault(); |
| 371 e.stopPropagation(); | 461 e.stopPropagation(); |
| 372 } | 462 } |
| 373 } | 463 } |
| 374 | 464 |
| 375 | |
| 376 | |
| 377 // When the user clicks, the currentElement is the one we want. | 465 // When the user clicks, the currentElement is the one we want. |
| 378 // We should have ABP rules ready for when the | 466 // We should have ABP rules ready for when the |
| 379 // popup asks for them. | 467 // popup asks for them. |
| 380 function clickHide_mouseClick(e) | 468 function clickHide_mouseClick(e) |
| 381 { | 469 { |
| 382 if (!currentElement || !clickHide_activated) | 470 if (!currentElement || !clickHide_activated) |
| 383 return; | 471 return; |
| 384 | 472 |
| 385 var elt = currentElement; | 473 var elt = currentElement; |
| 386 if (currentElement.classList.contains("__adblockplus__overlay")) | 474 if (currentElement.classList.contains("__adblockplus__overlay")) |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 408 for (var i = 0; i < elt.classList.length; i++) | 496 for (var i = 0; i < elt.classList.length; i++) |
| 409 selector += "." + escapeCSS(elt.classList[i]); | 497 selector += "." + escapeCSS(elt.classList[i]); |
| 410 | 498 |
| 411 addSelector(selector); | 499 addSelector(selector); |
| 412 } | 500 } |
| 413 | 501 |
| 414 var urls = getElementURLs(elt); | 502 var urls = getElementURLs(elt); |
| 415 for (var i = 0; i < urls.length; i++) | 503 for (var i = 0; i < urls.length; i++) |
| 416 { | 504 { |
| 417 var url = urls[i]; | 505 var url = urls[i]; |
| 418 var isHTTP = /^https?:/i.test(url); | 506 |
| 419 | 507 if (/^https?:/i.test(url)) |
| 420 if (isHTTP) | |
| 421 { | 508 { |
| 422 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); | 509 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); |
| 423 | 510 |
| 424 if (clickHideFilters.indexOf(filter) != -1) | 511 if (clickHideFilters.indexOf(filter) == -1) |
| 425 continue; | 512 clickHideFilters.push(filter); |
| 426 | 513 |
| 427 clickHideFilters.push(filter); | 514 continue; |
| 428 } | 515 } |
| 429 | 516 |
| 430 if (url == elt.src) | 517 if (url == elt.src) |
| 431 { | 518 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']'); |
| 432 var selector = escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute ("src")) + ']'; | |
| 433 | |
| 434 if (isHTTP) | |
| 435 selectorList.push(selector); | |
| 436 else | |
| 437 addSelector(selector); | |
| 438 } | |
| 439 } | 519 } |
| 440 | 520 |
| 441 // restore the original style, before generating the fallback filter that | 521 // restore the original style, before generating the fallback filter that |
| 442 // will include the style, and to prevent highlightElements from saving those | 522 // will include the style, and to prevent highlightElements from saving those |
| 443 unhighlightElement(currentElement); | 523 unhighlightElement(currentElement); |
| 444 | 524 |
| 445 // as last resort, create a filter based on inline styles | 525 // as last resort, create a filter based on inline styles |
| 446 if (clickHideFilters.length == 0) | 526 if (clickHideFilters.length == 0) |
| 447 { | 527 { |
| 448 var style = elt.getAttribute("style"); | 528 var style = elt.getAttribute("style"); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 473 for (var i = 0; i < urls.length; i++) | 553 for (var i = 0; i < urls.length; i++) |
| 474 { | 554 { |
| 475 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, ""); | 555 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, ""); |
| 476 if (url) | 556 if (url) |
| 477 urls[i] = resolveURL(url); | 557 urls[i] = resolveURL(url); |
| 478 else | 558 else |
| 479 urls.splice(i--, 1); | 559 urls.splice(i--, 1); |
| 480 } | 560 } |
| 481 | 561 |
| 482 return urls; | 562 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; | |
| 557 } | 563 } |
| 558 | 564 |
| 559 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | 565 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js |
| 560 // and licensed under the MIT license. See jquery-*.min.js for details. | 566 // and licensed under the MIT license. See jquery-*.min.js for details. |
| 561 function removeDotSegments(u) { | 567 function removeDotSegments(u) { |
| 562 var r = '', m = []; | 568 var r = '', m = []; |
| 563 if (/\./.test(u)) { | 569 if (/\./.test(u)) { |
| 564 while (u !== undefined && u !== '') { | 570 while (u !== undefined && u !== '') { |
| 565 if (u === '.' || u === '..') { | 571 if (u === '.' || u === '..') { |
| 566 u = ''; | 572 u = ''; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 709 break; | 715 break; |
| 710 default: | 716 default: |
| 711 sendResponse({}); | 717 sendResponse({}); |
| 712 break; | 718 break; |
| 713 } | 719 } |
| 714 }); | 720 }); |
| 715 | 721 |
| 716 if (window == window.top) | 722 if (window == window.top) |
| 717 ext.backgroundPage.sendMessage({type: "report-html-page"}); | 723 ext.backgroundPage.sendMessage({type: "report-html-page"}); |
| 718 } | 724 } |
| LEFT | RIGHT |