| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 2  * This file is part of Adblock Plus <https://adblockplus.org/>, | 
| 3  * Copyright (C) 2006-2015 Eyeo GmbH | 3  * Copyright (C) 2006-2015 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 | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 12  * GNU General Public License for more details. | 12  * GNU General Public License for more details. | 
| 13  * | 13  * | 
| 14  * You should have received a copy of the GNU General Public License | 14  * You should have received a copy of the GNU General Public License | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. | 
| 16  */ | 16  */ | 
| 17 | 17 | 
| 18 // Click-to-hide stuff | 18 // Click-to-hide stuff | 
| 19 var clickHide_activated = false; | 19 var clickHide_activated = false; | 
| 20 var clickHide_filters = null; | 20 var clickHide_filters = null; | 
| 21 var currentElement = null; | 21 var currentElement = null; | 
| 22 var highlightedElementsSelector = null; | 22 var highlightedElementsSelector = null; | 
| 23 var clickHideFiltersDialog = null; | 23 var clickHideFiltersDialog = null; | 
| 24 var lastRightClickEvent = null; | 24 var lastRightClickEvent = null; | 
| 25 var lastRightClickEventValid = false; | 25 var lastRightClickEventValid = false; | 
| 26 var lastMouseOverEvent = null; |  | 
| 27 | 26 | 
| 28 function highlightElement(element, shadowColor, backgroundColor) | 27 function highlightElement(element, shadowColor, backgroundColor) | 
| 29 { | 28 { | 
| 30   unhighlightElement(element); | 29   unhighlightElement(element); | 
| 31 | 30 | 
| 32   var highlightWithOverlay = function() | 31   var highlightWithOverlay = function() | 
| 33   { | 32   { | 
| 34     var overlay = addElementOverlay(element); | 33     var overlay = addElementOverlay(element); | 
| 35 | 34 | 
| 36     // If the element isn't displayed no overlay will be added. | 35     // If the element isn't displayed no overlay will be added. | 
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 192 | 191 | 
| 193     case "video": | 192     case "video": | 
| 194     case "audio": | 193     case "audio": | 
| 195     case "picture": | 194     case "picture": | 
| 196       return getURLsFromMediaElement(element); | 195       return getURLsFromMediaElement(element); | 
| 197   } | 196   } | 
| 198 | 197 | 
| 199   return getURLsFromAttributes(element); | 198   return getURLsFromAttributes(element); | 
| 200 } | 199 } | 
| 201 | 200 | 
|  | 201 function isBlockable(element) | 
|  | 202 { | 
|  | 203   if (element.id) | 
|  | 204     return true; | 
|  | 205   if (element.classList.length > 0) | 
|  | 206     return true; | 
|  | 207   if (getURLsFromElement(element).length > 0) | 
|  | 208     return true; | 
|  | 209 | 
|  | 210   // We only generate filters based on the "style" attribute, | 
|  | 211   // if this is the only way we can generate a filter, and | 
|  | 212   // only if there are at least two CSS properties defined. | 
|  | 213   if (/:.+:/.test(element.getAttribute("style"))) | 
|  | 214     return true; | 
|  | 215 | 
|  | 216   return false; | 
|  | 217 } | 
|  | 218 | 
| 202 // Adds an overlay to an element, which is probably a Flash object | 219 // Adds an overlay to an element, which is probably a Flash object | 
| 203 function addElementOverlay(elt) { | 220 function addElementOverlay(elt) { | 
| 204   var zIndex = "auto"; | 221   var zIndex = "auto"; | 
| 205   var position = "absolute"; | 222   var position = "absolute"; | 
| 206 | 223 | 
| 207   for (var e = elt; e; e = e.parentElement) | 224   for (var e = elt; e; e = e.parentElement) | 
| 208   { | 225   { | 
| 209     var style = getComputedStyle(e); | 226     var style = getComputedStyle(e); | 
| 210 | 227 | 
| 211     // If the element isn't rendered (since its or one of its ancestor's | 228     // If the element isn't rendered (since its or one of its ancestor's | 
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 288 function clickHide_activate() { | 305 function clickHide_activate() { | 
| 289   if(document == null) | 306   if(document == null) | 
| 290     return; | 307     return; | 
| 291 | 308 | 
| 292   // If we are already selecting, abort now | 309   // If we are already selecting, abort now | 
| 293   if (clickHide_activated || clickHideFiltersDialog) | 310   if (clickHide_activated || clickHideFiltersDialog) | 
| 294     clickHide_deactivate(); | 311     clickHide_deactivate(); | 
| 295 | 312 | 
| 296   // Add overlays for blockable elements that don't emit mouse events, | 313   // Add overlays for blockable elements that don't emit mouse events, | 
| 297   // so that they can still be selected. | 314   // so that they can still be selected. | 
| 298   [].forEach.call( | 315   var elts = document.querySelectorAll('object,embed,iframe,frame'); | 
| 299     document.querySelectorAll('object,embed,iframe,frame'), | 316   for(var i=0; i<elts.length; i++) | 
| 300     function(element) | 317   { | 
| 301     { | 318     var element = elts[i]; | 
| 302       getFiltersForElement(element, function(filters) | 319     if (isBlockable(element)) | 
| 303       { | 320       addElementOverlay(element); | 
| 304         if (filters.length > 0) | 321   } | 
| 305           addElementOverlay(element); |  | 
| 306       }); |  | 
| 307     } |  | 
| 308   ); |  | 
| 309 | 322 | 
| 310   clickHide_activated = true; | 323   clickHide_activated = true; | 
| 311   document.addEventListener("mousedown", clickHide_stopPropagation, true); | 324   document.addEventListener("mousedown", clickHide_stopPropagation, true); | 
| 312   document.addEventListener("mouseup", clickHide_stopPropagation, true); | 325   document.addEventListener("mouseup", clickHide_stopPropagation, true); | 
| 313   document.addEventListener("mouseenter", clickHide_stopPropagation, true); | 326   document.addEventListener("mouseenter", clickHide_stopPropagation, true); | 
| 314   document.addEventListener("mouseleave", clickHide_stopPropagation, true); | 327   document.addEventListener("mouseleave", clickHide_stopPropagation, true); | 
| 315   document.addEventListener("mouseover", clickHide_mouseOver, true); | 328   document.addEventListener("mouseover", clickHide_mouseOver, true); | 
| 316   document.addEventListener("mouseout", clickHide_mouseOut, true); | 329   document.addEventListener("mouseout", clickHide_mouseOut, true); | 
| 317   document.addEventListener("click", clickHide_mouseClick, true); | 330   document.addEventListener("click", clickHide_mouseClick, true); | 
| 318   document.addEventListener("keydown", clickHide_keyDown, true); | 331   document.addEventListener("keydown", clickHide_keyDown, true); | 
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 381 { | 394 { | 
| 382   e.stopPropagation(); | 395   e.stopPropagation(); | 
| 383 } | 396 } | 
| 384 | 397 | 
| 385 function clickHide_elementClickHandler(e) { | 398 function clickHide_elementClickHandler(e) { | 
| 386   e.preventDefault(); | 399   e.preventDefault(); | 
| 387   e.stopPropagation(); | 400   e.stopPropagation(); | 
| 388   clickHide_mouseClick(e); | 401   clickHide_mouseClick(e); | 
| 389 } | 402 } | 
| 390 | 403 | 
| 391 function getBlockableElementOrAncestor(element, callback) | 404 function getBlockableElementOrAncestor(element) | 
| 392 { | 405 { | 
| 393   // We assume that the user doesn't want to block the whole page. |  | 
| 394   // So we never consider the <html> or <body> element. |  | 
| 395   while (element && element != document.documentElement | 406   while (element && element != document.documentElement | 
| 396                  && element != document.body) | 407                  && element != document.body) | 
| 397   { | 408   { | 
| 398     // We can't handle non-HTML (like SVG) elements, as well as | 409     if (element instanceof HTMLElement && element.localName != "area") | 
| 399     // <area> elements (see below). So fall back to the parent element. | 410     { | 
| 400     if (!(element instanceof HTMLElement) || element.localName == "area") | 411       // Handle <area> and their <map> elements specially, | 
| 401       element = element.parentElement; | 412       // blocking the image they are associated with | 
|  | 413       if (element.localName == "map") | 
|  | 414       { | 
|  | 415         var images = document.querySelectorAll("img[usemap]"); | 
|  | 416         for (var i = 0; i < images.length; i++) | 
|  | 417         { | 
|  | 418           var image = images[i]; | 
|  | 419           var usemap = image.getAttribute("usemap"); | 
|  | 420           var index = usemap.indexOf("#"); | 
| 402 | 421 | 
| 403     // If image maps are used mouse events occur for the <area> element. | 422           if (index != -1 && usemap.substr(index + 1) == element.name) | 
| 404     // But we have to block the image associated with the <map> element. | 423             return getBlockableElementOrAncestor(image); | 
| 405     else if (element.localName == "map") | 424         } | 
| 406     { |  | 
| 407       var images = document.querySelectorAll("img[usemap]"); |  | 
| 408       var image = null; |  | 
| 409 | 425 | 
| 410       for (var i = 0; i < images.length; i++) | 426         return null; | 
| 411       { |  | 
| 412         var usemap = image.getAttribute("usemap"); |  | 
| 413         var index = usemap.indexOf("#"); |  | 
| 414 |  | 
| 415         if (index != -1 && usemap.substr(index + 1) == element.name) |  | 
| 416         { |  | 
| 417           image = images[i]; |  | 
| 418           break; |  | 
| 419         } |  | 
| 420       } | 427       } | 
| 421 | 428 | 
| 422       element = image; | 429       if (isBlockable(element)) | 
|  | 430         return element; | 
| 423     } | 431     } | 
| 424 | 432 | 
| 425     // Finally, if none of the above is true, check whether we can generate | 433     element = element.parentElement; | 
| 426     // any filters for this element. Otherwise fall back to its parent element. |  | 
| 427     else |  | 
| 428     { |  | 
| 429       getFiltersForElement(element, function(filters) |  | 
| 430       { |  | 
| 431         if (filters.length > 0) |  | 
| 432           callback(element); |  | 
| 433         else |  | 
| 434           getBlockableElementOrAncestor(element.parentElement, callback); |  | 
| 435       }); |  | 
| 436 |  | 
| 437       return; |  | 
| 438     } |  | 
| 439   } | 434   } | 
| 440 | 435 | 
| 441   // We reached the document root without finding a blockable element. | 436   return null; | 
| 442   callback(null); |  | 
| 443 } | 437 } | 
| 444 | 438 | 
| 445 // Hovering over an element so highlight it | 439 // Hovering over an element so highlight it | 
| 446 function clickHide_mouseOver(e) | 440 function clickHide_mouseOver(e) | 
| 447 { | 441 { | 
| 448   lastMouseOverEvent = e; | 442   if (clickHide_activated == false) | 
|  | 443     return; | 
| 449 | 444 | 
| 450   getBlockableElementOrAncestor(e.target, function(element) | 445   var target = getBlockableElementOrAncestor(e.target); | 
|  | 446 | 
|  | 447   if (target) | 
| 451   { | 448   { | 
| 452     if (e == lastMouseOverEvent) | 449     currentElement = target; | 
| 453     { |  | 
| 454       lastMouseOverEvent = null; |  | 
| 455 | 450 | 
| 456       if (clickHide_activated) | 451     highlightElement(target, "#d6d84b", "#f8fa47"); | 
| 457       { | 452     target.addEventListener("contextmenu", clickHide_elementClickHandler, true); | 
| 458         if (currentElement) | 453   } | 
| 459           unhighlightElement(currentElement); |  | 
| 460 |  | 
| 461         if (element) |  | 
| 462         { |  | 
| 463           highlightElement(element, "#d6d84b", "#f8fa47"); |  | 
| 464           element.addEventListener("contextmenu", clickHide_elementClickHandler,
      true); |  | 
| 465         } |  | 
| 466 |  | 
| 467         currentElement = element; |  | 
| 468       } |  | 
| 469     } |  | 
| 470   }); |  | 
| 471 |  | 
| 472   e.stopPropagation(); | 454   e.stopPropagation(); | 
| 473 } | 455 } | 
| 474 | 456 | 
| 475 // No longer hovering over this element so unhighlight it | 457 // No longer hovering over this element so unhighlight it | 
| 476 function clickHide_mouseOut(e) | 458 function clickHide_mouseOut(e) | 
| 477 { | 459 { | 
| 478   if (!clickHide_activated || currentElement != e.target) | 460   if (!clickHide_activated || !currentElement) | 
| 479     return; | 461     return; | 
| 480 | 462 | 
| 481   unhighlightElement(currentElement); | 463   unhighlightElement(currentElement); | 
| 482   currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle
     r, true); | 464   currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle
     r, true); | 
| 483   e.stopPropagation(); | 465   e.stopPropagation(); | 
| 484 } | 466 } | 
| 485 | 467 | 
| 486 // Selects the currently hovered-over filter or cancels selection | 468 // Selects the currently hovered-over filter or cancels selection | 
| 487 function clickHide_keyDown(e) | 469 function clickHide_keyDown(e) | 
| 488 { | 470 { | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
| 507 { | 489 { | 
| 508   ext.backgroundPage.sendMessage( | 490   ext.backgroundPage.sendMessage( | 
| 509     { | 491     { | 
| 510       type: "compose-filters", | 492       type: "compose-filters", | 
| 511       tagName: element.localName, | 493       tagName: element.localName, | 
| 512       id: element.id, | 494       id: element.id, | 
| 513       src: element.getAttribute("src"), | 495       src: element.getAttribute("src"), | 
| 514       style: element.getAttribute("style"), | 496       style: element.getAttribute("style"), | 
| 515       classes: [].slice.call(element.classList), | 497       classes: [].slice.call(element.classList), | 
| 516       urls: getURLsFromElement(element), | 498       urls: getURLsFromElement(element), | 
| 517       mediatype: typeMap[element.localName], |  | 
| 518       baseURL: document.location.href | 499       baseURL: document.location.href | 
| 519     }, | 500     }, | 
| 520     function(response) | 501     function(response) | 
| 521     { | 502     { | 
| 522       callback(response.filters, response.selectors); | 503       callback(response.filters, response.selectors); | 
| 523     } | 504     } | 
| 524   ); | 505   ); | 
| 525 } | 506 } | 
| 526 | 507 | 
| 527 // When the user clicks, the currentElement is the one we want. | 508 // When the user clicks, the currentElement is the one we want. | 
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 686         break; | 667         break; | 
| 687       case "clickhide-activate": | 668       case "clickhide-activate": | 
| 688         clickHide_activate(); | 669         clickHide_activate(); | 
| 689         break; | 670         break; | 
| 690       case "clickhide-deactivate": | 671       case "clickhide-deactivate": | 
| 691         clickHide_deactivate(); | 672         clickHide_deactivate(); | 
| 692         break; | 673         break; | 
| 693       case "clickhide-new-filter": | 674       case "clickhide-new-filter": | 
| 694         if(lastRightClickEvent) | 675         if(lastRightClickEvent) | 
| 695         { | 676         { | 
| 696           getBlockableElementOrAncestor(lastRightClickEvent.target, function(ele
     ment) | 677           clickHide_activated = true; | 
| 697           { | 678           currentElement = getBlockableElementOrAncestor(lastRightClickEvent.tar
     get); | 
| 698             clickHide_activated = true; | 679           clickHide_mouseClick(lastRightClickEvent); | 
| 699             currentElement = element; |  | 
| 700             clickHide_mouseClick(lastRightClickEvent); |  | 
| 701           }); |  | 
| 702         } | 680         } | 
| 703         break; | 681         break; | 
| 704       case "clickhide-init": | 682       case "clickhide-init": | 
| 705         if (clickHideFiltersDialog) | 683         if (clickHideFiltersDialog) | 
| 706         { | 684         { | 
| 707           sendResponse({filters: clickHide_filters}); | 685           sendResponse({filters: clickHide_filters}); | 
| 708 | 686 | 
| 709           clickHideFiltersDialog.style.width = msg.width + "px"; | 687           clickHideFiltersDialog.style.width = msg.width + "px"; | 
| 710           clickHideFiltersDialog.style.height = msg.height + "px"; | 688           clickHideFiltersDialog.style.height = msg.height + "px"; | 
| 711           clickHideFiltersDialog.style.visibility = "visible"; | 689           clickHideFiltersDialog.style.visibility = "visible"; | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 739           lastRightClickEventValid = false; | 717           lastRightClickEventValid = false; | 
| 740         else | 718         else | 
| 741           lastRightClickEvent = null; | 719           lastRightClickEvent = null; | 
| 742         break; | 720         break; | 
| 743     } | 721     } | 
| 744   }); | 722   }); | 
| 745 | 723 | 
| 746   if (window == window.top) | 724   if (window == window.top) | 
| 747     ext.backgroundPage.sendMessage({type: "report-html-page"}); | 725     ext.backgroundPage.sendMessage({type: "report-html-page"}); | 
| 748 } | 726 } | 
| OLD | NEW | 
|---|