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

Side by Side Diff: include.postload.js

Issue 5468762555809792: Issue 1601 - Generate blocking filters for all URLs associated with the selected element (Closed)
Patch Set: Also consider "poster" attribute Created Nov. 26, 2014, 10:55 a.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 | « no previous file | no next file » | 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 <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 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
191 } 191 }
192 192
193 // Adds an overlay to an element, which is probably a Flash object 193 // Adds an overlay to an element, which is probably a Flash object
194 function addElementOverlay(elt) { 194 function addElementOverlay(elt) {
195 // If this element is enclosed in an object tag, we prefer to block that inste ad 195 // If this element is enclosed in an object tag, we prefer to block that inste ad
196 if(!elt) 196 if(!elt)
197 return null; 197 return null;
198 198
199 // If element doesn't have at least one of class name, ID or URL, give up 199 // 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 200 // because we don't know how to construct a filter rule for it
201 var url = getElementURL(elt); 201 if(!hasFilters(elt))
202 if(!elt.className && !elt.id && !url)
203 return; 202 return;
204 var thisStyle = getComputedStyle(elt, null); 203 var thisStyle = getComputedStyle(elt, null);
205 var overlay = document.createElement('div'); 204 var overlay = document.createElement('div');
206 overlay.prisoner = elt; 205 overlay.prisoner = elt;
207 overlay.prisonerURL = url;
208 overlay.className = "__adblockplus__overlay"; 206 overlay.className = "__adblockplus__overlay";
209 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'); 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');
210 var pos = getAbsolutePosition(elt); 208 var pos = getAbsolutePosition(elt);
211 overlay.style.left = pos[0] + "px"; 209 overlay.style.left = pos[0] + "px";
212 overlay.style.top = pos[1] + "px"; 210 overlay.style.top = pos[1] + "px";
213 // elt.parentNode.appendChild(overlay, elt); 211 // elt.parentNode.appendChild(overlay, elt);
214 document.body.appendChild(overlay); 212 document.body.appendChild(overlay);
215 return overlay; 213 return overlay;
216 } 214 }
217 215
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 // Turn on the choose element to create filter thing 256 // Turn on the choose element to create filter thing
259 function clickHide_activate() { 257 function clickHide_activate() {
260 if(document == null) 258 if(document == null)
261 return; 259 return;
262 260
263 // If we are already selecting, abort now 261 // If we are already selecting, abort now
264 if (clickHide_activated || clickHideFiltersDialog) 262 if (clickHide_activated || clickHideFiltersDialog)
265 clickHide_deactivate(); 263 clickHide_deactivate();
266 264
267 // Add overlays for elements with URLs so user can easily click them 265 // Add overlays for elements with URLs so user can easily click them
268 var elts = document.querySelectorAll('object,embed,img,iframe'); 266 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure');
269 for(var i=0; i<elts.length; i++) 267 for(var i=0; i<elts.length; i++)
270 addElementOverlay(elts[i]); 268 addElementOverlay(elts[i]);
271 269
272 clickHide_activated = true; 270 clickHide_activated = true;
273 document.addEventListener("mouseover", clickHide_mouseOver, true); 271 document.addEventListener("mouseover", clickHide_mouseOver, true);
274 document.addEventListener("mouseout", clickHide_mouseOut, true); 272 document.addEventListener("mouseout", clickHide_mouseOut, true);
275 document.addEventListener("click", clickHide_mouseClick, true); 273 document.addEventListener("click", clickHide_mouseClick, true);
276 document.addEventListener("keydown", clickHide_keyDown, true); 274 document.addEventListener("keydown", clickHide_keyDown, true);
277 } 275 }
278 276
(...skipping 25 matching lines...) Expand all
304 } 302 }
305 unhighlightElements(); 303 unhighlightElements();
306 304
307 clickHide_activated = false; 305 clickHide_activated = false;
308 clickHide_filters = null; 306 clickHide_filters = null;
309 if(!document) 307 if(!document)
310 return; // This can happen inside a nuked iframe...I think 308 return; // This can happen inside a nuked iframe...I think
311 document.removeEventListener("mouseover", clickHide_mouseOver, true); 309 document.removeEventListener("mouseover", clickHide_mouseOver, true);
312 document.removeEventListener("mouseout", clickHide_mouseOut, true); 310 document.removeEventListener("mouseout", clickHide_mouseOut, true);
313 document.removeEventListener("click", clickHide_mouseClick, true); 311 document.removeEventListener("click", clickHide_mouseClick, true);
314 document.removeEventListener("keydown", clickHide_keyDown, true); 312 document.removeEventListener("keydown", clickHide_keyDown, true);
kzar 2014/11/26 11:36:17 I think the capturing / bubbling changes from the
Sebastian Noack 2014/11/26 11:42:48 They are not part of this patch. However, they sho
315 313
316 // Remove overlays 314 // Remove overlays
317 // For some reason iterating over the array returend by getElementsByClassName () doesn't work 315 // For some reason iterating over the array returend by getElementsByClassName () doesn't work
318 var elt; 316 var elt;
319 while(elt = document.querySelector('.__adblockplus__overlay')) 317 while(elt = document.querySelector('.__adblockplus__overlay'))
320 elt.parentNode.removeChild(elt); 318 elt.parentNode.removeChild(elt);
321 } 319 }
322 320
323 function clickHide_elementClickHandler(ev) { 321 function clickHide_elementClickHandler(ev) {
324 ev.preventDefault(); 322 ev.preventDefault();
325 ev.stopPropagation(); 323 ev.stopPropagation();
326 clickHide_mouseClick(ev); 324 clickHide_mouseClick(ev);
327 } 325 }
328 326
329 // Hovering over an element so highlight it 327 // Hovering over an element so highlight it
330 function clickHide_mouseOver(e) 328 function clickHide_mouseOver(e)
331 { 329 {
332 if (clickHide_activated == false) 330 if (clickHide_activated == false)
333 return; 331 return;
334 332
335 var target = e.target; 333 var target = e.target;
336 while (target.parentNode && !(target.id || target.className || target.src || / :.+:/.test(target.getAttribute("style")))) 334 while (target.parentNode && !hasFilters(target))
337 target = target.parentNode; 335 target = target.parentNode;
338 if (target == document.documentElement || target == document.body) 336 if (target == document.documentElement || target == document.body)
339 target = null; 337 target = null;
340 338
341 if (target && target instanceof HTMLElement) 339 if (target && target instanceof HTMLElement)
342 { 340 {
343 currentElement = target; 341 currentElement = target;
344 342
345 highlightElement(target, "#d6d84b", "#f8fa47"); 343 highlightElement(target, "#d6d84b", "#f8fa47");
346 target.addEventListener("contextmenu", clickHide_elementClickHandler, true); 344 target.addEventListener("contextmenu", clickHide_elementClickHandler, true);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 377
380 // When the user clicks, the currentElement is the one we want. 378 // When the user clicks, the currentElement is the one we want.
381 // We should have ABP rules ready for when the 379 // We should have ABP rules ready for when the
382 // popup asks for them. 380 // popup asks for them.
383 function clickHide_mouseClick(e) 381 function clickHide_mouseClick(e)
384 { 382 {
385 if (!currentElement || !clickHide_activated) 383 if (!currentElement || !clickHide_activated)
386 return; 384 return;
387 385
388 var elt = currentElement; 386 var elt = currentElement;
389 var url = null;
390 if (currentElement.classList.contains("__adblockplus__overlay")) 387 if (currentElement.classList.contains("__adblockplus__overlay"))
391 {
392 elt = currentElement.prisoner; 388 elt = currentElement.prisoner;
393 url = currentElement.prisonerURL;
394 }
395 else if (elt.src)
396 url = elt.src;
397 389
398 clickHideFilters = new Array(); 390 clickHideFilters = new Array();
399 selectorList = new Array(); 391 selectorList = new Array();
400 392
401 var addSelector = function(selector) 393 var addSelector = function(selector)
402 { 394 {
395 if (selectorList.indexOf(selector) != -1)
396 return;
397
403 clickHideFilters.push(document.domain + "##" + selector); 398 clickHideFilters.push(document.domain + "##" + selector);
404 selectorList.push(selector); 399 selectorList.push(selector);
405 }; 400 };
406 401
407 if (elt.id) 402 if (elt.id)
408 addSelector("#" + escapeCSS(elt.id)); 403 addSelector("#" + escapeCSS(elt.id));
409 404
410 if (elt.classList.length > 0) 405 if (elt.classList.length > 0)
411 { 406 {
412 var selector = ""; 407 var selector = "";
413 408
414 for (var i = 0; i < elt.classList.length; i++) 409 for (var i = 0; i < elt.classList.length; i++)
415 selector += "." + escapeCSS(elt.classList[i]); 410 selector += "." + escapeCSS(elt.classList[i]);
416 411
417 addSelector(selector); 412 addSelector(selector);
418 } 413 }
419 414
420 if (url) 415 var urls = getElementURLs(elt);
416 for (var i = 0; i < urls.length; i++)
421 { 417 {
422 var src = elt.getAttribute("src"); 418 var url = urls[i];
423 var selector = src && escapeCSS(elt.localName) + '[src=' + quote(src) + ']'; 419 var isHTTP = /^https?:/i.test(url);
424 420
425 if (/^https?:/i.test(url)) 421 if (isHTTP)
426 { 422 {
427 clickHideFilters.push(url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||")); 423 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||");
428 424
429 if (selector) 425 if (clickHideFilters.indexOf(filter) != -1)
426 continue;
427
428 clickHideFilters.push(filter);
429 }
430
431 if (url == elt.src)
432 {
433 var selector = escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute ("src")) + ']';
434
435 if (isHTTP)
430 selectorList.push(selector); 436 selectorList.push(selector);
437 else
438 addSelector(selector);
431 } 439 }
432 else if (selector)
433 addSelector(selector);
434 } 440 }
435 441
436 // restore the original style, before generating the fallback filter that 442 // restore the original style, before generating the fallback filter that
437 // will include the style, and to prevent highlightElements from saving those 443 // will include the style, and to prevent highlightElements from saving those
438 unhighlightElement(currentElement); 444 unhighlightElement(currentElement);
439 445
440 // as last resort, create a filter based on inline styles 446 // as last resort, create a filter based on inline styles
441 if (clickHideFilters.length == 0) 447 if (clickHideFilters.length == 0)
442 { 448 {
443 var style = elt.getAttribute("style"); 449 var style = elt.getAttribute("style");
444 if (style) 450 if (style)
445 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); 451 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']');
446 } 452 }
447 453
448 // Show popup 454 // Show popup
449 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); 455 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters);
450 456
451 // Highlight the elements specified by selector in yellow 457 // Highlight the elements specified by selector in yellow
452 highlightElements(selectorList.join(",")); 458 highlightElements(selectorList.join(","));
453 // Now, actually highlight the element the user clicked on in red 459 // Now, actually highlight the element the user clicked on in red
454 highlightElement(currentElement, "#fd1708", "#f6a1b5"); 460 highlightElement(currentElement, "#fd1708", "#f6a1b5");
455 461
456 // Make sure the browser doesn't handle this click 462 // Make sure the browser doesn't handle this click
457 e.preventDefault(); 463 e.preventDefault();
458 e.stopPropagation(); 464 e.stopPropagation();
459 } 465 }
460 466
461 // Extracts source URL from an IMG, OBJECT, EMBED, or IFRAME 467 function parseSrcSet(element)
462 function getElementURL(elt) { 468 {
463 // Check children of object nodes for "param" nodes with name="movie" that spe cify a URL 469 if (!element.srcset)
464 // in value attribute 470 return [];
465 var url;
466 if(elt.localName.toUpperCase() == "OBJECT" && !(url = elt.getAttribute("data") )) {
467 // No data attribute, look in PARAM child tags for a URL for the swf file
468 var params = elt.querySelectorAll("param[name=\"movie\"]");
469 // This OBJECT could contain an EMBED we already nuked, in which case there' s no URL
470 if(params[0])
471 url = params[0].getAttribute("value");
472 else {
473 params = elt.querySelectorAll("param[name=\"src\"]");
474 if(params[0])
475 url = params[0].getAttribute("value");
476 }
477 471
472 var urls = element.srcset.split(",");
473 for (var i = 0; i < urls.length; i++)
474 {
475 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, "");
478 if (url) 476 if (url)
479 url = resolveURL(url); 477 urls[i] = resolveURL(url);
480 } else if(!url) { 478 else
481 url = elt.src || elt.href; 479 urls.splice(i--, 1);
482 } 480 }
483 return url; 481
482 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;
484 } 557 }
485 558
486 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js 559 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js
487 // and licensed under the MIT license. See jquery-*.min.js for details. 560 // and licensed under the MIT license. See jquery-*.min.js for details.
488 function removeDotSegments(u) { 561 function removeDotSegments(u) {
489 var r = '', m = []; 562 var r = '', m = [];
490 if (/\./.test(u)) { 563 if (/\./.test(u)) {
491 while (u !== undefined && u !== '') { 564 while (u !== undefined && u !== '') {
492 if (u === '.' || u === '..') { 565 if (u === '.' || u === '..') {
493 u = ''; 566 u = '';
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 break; 747 break;
675 default: 748 default:
676 sendResponse({}); 749 sendResponse({});
677 break; 750 break;
678 } 751 }
679 }); 752 });
680 753
681 if (window == window.top) 754 if (window == window.top)
682 ext.backgroundPage.sendMessage({type: "report-html-page"}); 755 ext.backgroundPage.sendMessage({type: "report-html-page"});
683 } 756 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld