Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: include.postload.js

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

Powered by Google App Engine
This is Rietveld