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

Delta Between Two Patch Sets: include.postload.js

Issue 5468762555809792: Issue 1601 - Generate blocking filters for all URLs associated with the selected element (Closed)
Left Patch Set: Created Nov. 25, 2014, 2:16 p.m.
Right Patch Set: Fixed wrong comparision operator Created Dec. 8, 2014, 9:12 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « no previous file | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
69 // author created shadow roots, but ignore insertion points. 69 // author created shadow roots, but ignore insertion points.
70 var child = document.createTextNode(""); 70 var child = document.createTextNode("");
71 clone.appendChild(child); 71 clone.appendChild(child);
72 72
73 var shadow = document.createElement("shadow"); 73 var shadow = document.createElement("shadow");
74 clone.shadowRoot.appendChild(shadow); 74 clone.shadowRoot.appendChild(shadow);
75 75
76 return shadow.getDistributedNodes()[0] == child; 76 return shadow.getDistributedNodes()[0] == child;
77 } 77 }
78 78
79 function getOriginalStyle(element)
80 {
81 if ("_originalStyle" in element)
82 return element._originalStyle;
83
84 return element.getAttribute("style");
85 }
86
79 function highlightElement(element, shadowColor, backgroundColor) 87 function highlightElement(element, shadowColor, backgroundColor)
80 { 88 {
81 unhighlightElement(element); 89 unhighlightElement(element);
82 90
83 var originalBoxShadowPriority = element.style.getPropertyPriority("box-shadow" ); 91 var originalBoxShadowPriority = element.style.getPropertyPriority("box-shadow" );
84 var originalBackgroundColorPriority = element.style.getPropertyPriority("backg round-color"); 92 var originalBackgroundColorPriority = element.style.getPropertyPriority("backg round-color");
85 93
86 var boxShadow = "inset 0px 0px 5px " + shadowColor; 94 var boxShadow = "inset 0px 0px 5px " + shadowColor;
87 95
88 var highlightWithShadowDOM = function() 96 var highlightWithShadowDOM = function()
(...skipping 11 matching lines...) Expand all
100 element._unhighlight = function() 108 element._unhighlight = function()
101 { 109 {
102 root.removeChild(style); 110 root.removeChild(style);
103 }; 111 };
104 }; 112 };
105 113
106 var highlightWithStyleAttribute = function() 114 var highlightWithStyleAttribute = function()
107 { 115 {
108 var originalBoxShadow = element.style.getPropertyValue("box-shadow"); 116 var originalBoxShadow = element.style.getPropertyValue("box-shadow");
109 var originalBackgroundColor = element.style.getPropertyValue("background-col or"); 117 var originalBackgroundColor = element.style.getPropertyValue("background-col or");
118
119 element._originalStyle = getOriginalStyle(element);
110 120
111 element.style.setProperty("box-shadow", boxShadow, "important"); 121 element.style.setProperty("box-shadow", boxShadow, "important");
112 element.style.setProperty("background-color", backgroundColor, "important"); 122 element.style.setProperty("background-color", backgroundColor, "important");
113 123
114 element._unhighlight = function() 124 element._unhighlight = function()
115 { 125 {
116 this.style.removeProperty("box-shadow"); 126 this.style.removeProperty("box-shadow");
117 this.style.setProperty( 127 this.style.setProperty(
118 "box-shadow", 128 "box-shadow",
119 originalBoxShadow, 129 originalBoxShadow,
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 function unhighlightElements() { 176 function unhighlightElements() {
167 if (highlightedElementsSelector) 177 if (highlightedElementsSelector)
168 { 178 {
169 Array.prototype.forEach.call( 179 Array.prototype.forEach.call(
170 document.querySelectorAll(highlightedElementsSelector), 180 document.querySelectorAll(highlightedElementsSelector),
171 unhighlightElement 181 unhighlightElement
172 ); 182 );
173 183
174 highlightedElementsSelector = null; 184 highlightedElementsSelector = null;
175 } 185 }
186 }
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")
246 urls.push.apply(urls, getURLsFromAttributes(child));
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;
176 } 286 }
177 287
178 // 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,
179 // adding up offsets. 289 // adding up offsets.
180 // 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
181 // 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
182 // has hundreds and hundreds of other methods that do random junk. 292 // has hundreds and hundreds of other methods that do random junk.
183 function getAbsolutePosition(elt) { 293 function getAbsolutePosition(elt) {
184 var l = 0; 294 var l = 0;
185 var t = 0; 295 var t = 0;
186 for(; elt; elt = elt.offsetParent) { 296 for(; elt; elt = elt.offsetParent) {
187 l += elt.offsetLeft; 297 l += elt.offsetLeft;
188 t += elt.offsetTop; 298 t += elt.offsetTop;
189 } 299 }
190 return [l, t]; 300 return [l, t];
191 } 301 }
192 302
193 // 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
194 function addElementOverlay(elt) { 304 function addElementOverlay(elt) {
195 // 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
196 if(!elt) 306 if(!elt)
197 return null; 307 return null;
198 308
199 // 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
200 // 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
201 if(!hasFilters(elt)) 311 if(!isBlockable(elt))
202 return; 312 return;
313
314 // If the element isn't rendered (since its or one of its ancestor's
315 // "display" property is "none"), the overlay wouldn't match the element.
316 if (!elt.offsetParent)
317 return;
318
203 var thisStyle = getComputedStyle(elt, null); 319 var thisStyle = getComputedStyle(elt, null);
204 var overlay = document.createElement('div'); 320 var overlay = document.createElement('div');
205 overlay.prisoner = elt; 321 overlay.prisoner = elt;
206 overlay.className = "__adblockplus__overlay"; 322 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'); 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;');
208 var pos = getAbsolutePosition(elt); 324 var pos = getAbsolutePosition(elt);
209 overlay.style.left = pos[0] + "px"; 325 overlay.style.left = pos[0] + "px";
210 overlay.style.top = pos[1] + "px"; 326 overlay.style.top = pos[1] + "px";
327
328 if (thisStyle.position != "static")
329 overlay.style.zIndex = thisStyle.zIndex;
330 else
331 overlay.style.zIndex = getComputedStyle(elt.offsetParent).zIndex;
332
211 // elt.parentNode.appendChild(overlay, elt); 333 // elt.parentNode.appendChild(overlay, elt);
212 document.body.appendChild(overlay); 334 document.body.appendChild(overlay);
213 return overlay; 335 return overlay;
214 } 336 }
215 337
216 // Show dialog asking user whether she wants to add the proposed filters derived 338 // Show dialog asking user whether she wants to add the proposed filters derived
217 // from selected page element 339 // from selected page element
218 function clickHide_showDialog(left, top, filters) 340 function clickHide_showDialog(left, top, filters)
219 { 341 {
220 // If we are already selecting, abort now 342 // If we are already selecting, abort now
221 if (clickHide_activated || clickHideFiltersDialog) 343 if (clickHide_activated || clickHideFiltersDialog)
222 { 344 clickHide_deactivate(true);
223 var savedElement = (currentElement.prisoner ? currentElement.prisoner : curr entElement);
224 clickHide_deactivate();
225 currentElement = savedElement;
226 }
227 345
228 clickHide_filters = filters; 346 clickHide_filters = filters;
229 347
230 clickHideFiltersDialog = document.createElement("iframe"); 348 clickHideFiltersDialog = document.createElement("iframe");
231 clickHideFiltersDialog.src = ext.getURL("block.html"); 349 clickHideFiltersDialog.src = ext.getURL("block.html");
232 clickHideFiltersDialog.setAttribute("style", "position: fixed !important; visi bility: hidden; display: block !important; border: 0px !important;"); 350 clickHideFiltersDialog.setAttribute("style", "position: fixed !important; visi bility: hidden; display: block !important; border: 0px !important;");
233 clickHideFiltersDialog.style.WebkitBoxShadow = "5px 5px 20px rgba(0,0,0,0.5)"; 351 clickHideFiltersDialog.style.WebkitBoxShadow = "5px 5px 20px rgba(0,0,0,0.5)";
234 clickHideFiltersDialog.style.zIndex = 0x7FFFFFFF; 352 clickHideFiltersDialog.style.zIndex = 0x7FFFFFFF;
235 353
236 // Position in upper-left all the time 354 // Position in upper-left all the time
(...skipping 24 matching lines...) Expand all
261 // If we are already selecting, abort now 379 // If we are already selecting, abort now
262 if (clickHide_activated || clickHideFiltersDialog) 380 if (clickHide_activated || clickHideFiltersDialog)
263 clickHide_deactivate(); 381 clickHide_deactivate();
264 382
265 // 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
266 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure'); 384 var elts = document.querySelectorAll('object,embed,img,iframe,video,audio,pict ure');
267 for(var i=0; i<elts.length; i++) 385 for(var i=0; i<elts.length; i++)
268 addElementOverlay(elts[i]); 386 addElementOverlay(elts[i]);
269 387
270 clickHide_activated = true; 388 clickHide_activated = true;
271 document.addEventListener("mouseover", clickHide_mouseOver, false); 389 document.addEventListener("mouseover", clickHide_mouseOver, true);
272 document.addEventListener("mouseout", clickHide_mouseOut, false); 390 document.addEventListener("mouseout", clickHide_mouseOut, true);
273 document.addEventListener("click", clickHide_mouseClick, false); 391 document.addEventListener("click", clickHide_mouseClick, true);
274 document.addEventListener("keydown", clickHide_keyDown, false); 392 document.addEventListener("keydown", clickHide_keyDown, true);
275 } 393 }
276 394
277 // Called when user has clicked on something and we are waiting for confirmation 395 // Called when user has clicked on something and we are waiting for confirmation
278 // on whether the user actually wants these filters 396 // on whether the user actually wants these filters
279 function clickHide_rulesPending() { 397 function clickHide_rulesPending() {
280 clickHide_activated = false; 398 clickHide_activated = false;
281 document.removeEventListener("mouseover", clickHide_mouseOver, false); 399 document.removeEventListener("mouseover", clickHide_mouseOver, true);
282 document.removeEventListener("mouseout", clickHide_mouseOut, false); 400 document.removeEventListener("mouseout", clickHide_mouseOut, true);
283 document.removeEventListener("click", clickHide_mouseClick, false); 401 document.removeEventListener("click", clickHide_mouseClick, true);
284 document.removeEventListener("keydown", clickHide_keyDown, false); 402 document.removeEventListener("keydown", clickHide_keyDown, true);
285 } 403 }
286 404
287 // Turn off click-to-hide 405 // Turn off click-to-hide
288 function clickHide_deactivate() 406 function clickHide_deactivate(keepOverlays)
289 { 407 {
290 if (clickHideFiltersDialog) 408 if (clickHideFiltersDialog)
291 { 409 {
292 document.body.removeChild(clickHideFiltersDialog); 410 document.body.removeChild(clickHideFiltersDialog);
293 clickHideFiltersDialog = null; 411 clickHideFiltersDialog = null;
294 } 412 }
295
296 if(currentElement) {
297 currentElement.removeEventListener("contextmenu", clickHide_elementClickHand ler, false);
298 unhighlightElements();
299 unhighlightElement(currentElement);
300 currentElement = null;
301 clickHideFilters = null;
302 }
303 unhighlightElements();
304 413
305 clickHide_activated = false; 414 clickHide_activated = false;
306 clickHide_filters = null; 415 clickHide_filters = null;
307 if(!document) 416 if(!document)
308 return; // This can happen inside a nuked iframe...I think 417 return; // This can happen inside a nuked iframe...I think
309 document.removeEventListener("mouseover", clickHide_mouseOver, false); 418 document.removeEventListener("mouseover", clickHide_mouseOver, true);
310 document.removeEventListener("mouseout", clickHide_mouseOut, false); 419 document.removeEventListener("mouseout", clickHide_mouseOut, true);
311 document.removeEventListener("click", clickHide_mouseClick, false); 420 document.removeEventListener("click", clickHide_mouseClick, true);
312 document.removeEventListener("keydown", clickHide_keyDown, false); 421 document.removeEventListener("keydown", clickHide_keyDown, true);
313 422
314 // Remove overlays 423 if (!keepOverlays)
315 // For some reason iterating over the array returend by getElementsByClassName () doesn't work 424 {
316 var elt; 425 if (currentElement) {
317 while(elt = document.querySelector('.__adblockplus__overlay')) 426 currentElement.removeEventListener("contextmenu", clickHide_elementClickH andler, true);
318 elt.parentNode.removeChild(elt); 427 unhighlightElements();
428 unhighlightElement(currentElement);
429 currentElement = null;
430 clickHideFilters = null;
431 }
432 unhighlightElements();
433
434 var overlays = document.getElementsByClassName("__adblockplus__overlay");
435 while (overlays.length > 0)
436 overlays[0].parentNode.removeChild(overlays[0]);
437 }
319 } 438 }
320 439
321 function clickHide_elementClickHandler(ev) { 440 function clickHide_elementClickHandler(ev) {
322 ev.preventDefault(); 441 ev.preventDefault();
323 ev.stopPropagation(); 442 ev.stopPropagation();
324 clickHide_mouseClick(ev); 443 clickHide_mouseClick(ev);
325 } 444 }
326 445
327 // Hovering over an element so highlight it 446 // Hovering over an element so highlight it
328 function clickHide_mouseOver(e) 447 function clickHide_mouseOver(e)
329 { 448 {
330 if (clickHide_activated == false) 449 if (clickHide_activated == false)
331 return; 450 return;
332 451
333 var target = e.target; 452 var target = e.target;
334 while (target.parentNode && !hasFilters(target)) 453 while (target.parentNode && !isBlockable(target))
335 target = target.parentNode; 454 target = target.parentNode;
336 if (target == document.documentElement || target == document.body) 455 if (target == document.documentElement || target == document.body)
337 target = null; 456 target = null;
338 457
339 if (target && target instanceof HTMLElement) 458 if (target && target instanceof HTMLElement)
340 { 459 {
341 currentElement = target; 460 currentElement = target;
342 461
343 highlightElement(target, "#d6d84b", "#f8fa47"); 462 highlightElement(target, "#d6d84b", "#f8fa47");
344 target.addEventListener("contextmenu", clickHide_elementClickHandler, false) ; 463 target.addEventListener("contextmenu", clickHide_elementClickHandler, true);
345 } 464 }
346 } 465 }
347 466
348 // No longer hovering over this element so unhighlight it 467 // No longer hovering over this element so unhighlight it
349 function clickHide_mouseOut(e) 468 function clickHide_mouseOut(e)
350 { 469 {
351 if (!clickHide_activated || !currentElement) 470 if (!clickHide_activated || !currentElement)
352 return; 471 return;
353 472
354 unhighlightElement(currentElement); 473 unhighlightElement(currentElement);
355 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle r, false); 474 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle r, true);
356 } 475 }
357 476
358 // Selects the currently hovered-over filter or cancels selection 477 // Selects the currently hovered-over filter or cancels selection
359 function clickHide_keyDown(e) 478 function clickHide_keyDown(e)
360 { 479 {
361 if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 13 /*DOM_VK_RETURN* /) 480 if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 13 /*DOM_VK_RETURN* /)
362 clickHide_mouseClick(e); 481 clickHide_mouseClick(e);
363 else if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 27 /*DOM_VK_ES CAPE*/) 482 else if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 27 /*DOM_VK_ES CAPE*/)
364 { 483 {
365 ext.backgroundPage.sendMessage( 484 ext.backgroundPage.sendMessage(
366 { 485 {
367 type: "forward", 486 type: "forward",
368 payload: 487 payload:
369 { 488 {
370 type: "clickhide-deactivate" 489 type: "clickhide-deactivate"
371 } 490 }
372 }); 491 });
373 e.preventDefault(); 492 e.preventDefault();
374 e.stopPropagation(); 493 e.stopPropagation();
375 } 494 }
376 } 495 }
377 496
378
379
380 // When the user clicks, the currentElement is the one we want. 497 // When the user clicks, the currentElement is the one we want.
381 // We should have ABP rules ready for when the 498 // We should have ABP rules ready for when the
382 // popup asks for them. 499 // popup asks for them.
383 function clickHide_mouseClick(e) 500 function clickHide_mouseClick(e)
384 { 501 {
385 if (!currentElement || !clickHide_activated) 502 if (!currentElement || !clickHide_activated)
386 return; 503 return;
387 504
388 var elt = currentElement; 505 var elt = currentElement;
389 if (currentElement.classList.contains("__adblockplus__overlay")) 506 if (currentElement.classList.contains("__adblockplus__overlay"))
390 elt = currentElement.prisoner; 507 elt = currentElement.prisoner;
391 508
392 clickHideFilters = new Array(); 509 clickHideFilters = new Array();
393 selectorList = new Array(); 510 selectorList = new Array();
394 511
395 var addSelector = function(selector) 512 var addSelector = function(selector)
kzar 2014/11/25 18:10:11 Why we don't just do "function addSelector(selecto
Sebastian Noack 2014/11/25 19:01:15 The only reason that comes to my mind would be tha
396 { 513 {
397 if (selectorList.indexOf(selector) != -1) 514 if (selectorList.indexOf(selector) != -1)
398 return; 515 return;
399 516
400 clickHideFilters.push(document.domain + "##" + selector); 517 clickHideFilters.push(document.domain + "##" + selector);
401 selectorList.push(selector); 518 selectorList.push(selector);
402 }; 519 };
403 520
404 if (elt.id) 521 if (elt.id)
405 addSelector("#" + escapeCSS(elt.id)); 522 addSelector("#" + escapeCSS(elt.id));
406 523
407 if (elt.classList.length > 0) 524 if (elt.classList.length > 0)
408 { 525 {
409 var selector = ""; 526 var selector = "";
410 527
411 for (var i = 0; i < elt.classList.length; i++) 528 for (var i = 0; i < elt.classList.length; i++)
412 selector += "." + escapeCSS(elt.classList[i]); 529 selector += "." + escapeCSS(elt.classList[i]);
413 530
414 addSelector(selector); 531 addSelector(selector);
415 } 532 }
416 533
417 var urls = getElementURLs(elt); 534 var urls = getURLsFromElement(elt);
418 for (var i = 0; i < urls.length; i++) 535 for (var i = 0; i < urls.length; i++)
419 { 536 {
420 var url = urls[i]; 537 var url = urls[i];
421 var isHTTP = /^https?:/i.test(url); 538
422 539 if (/^https?:/i.test(url))
423 if (isHTTP)
kzar 2014/11/25 18:10:11 I found this line a little bit confusing to start
Sebastian Noack 2014/11/25 19:01:15 What I actually want, is excluding URLs that can't
424 { 540 {
425 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||"); 541 var filter = url.replace(/^[\w\-]+:\/+(?:www\.)?/, "||");
426 542
427 if (clickHideFilters.indexOf(filter) != -1) 543 if (clickHideFilters.indexOf(filter) == -1)
428 continue; 544 clickHideFilters.push(filter);
429 545
430 clickHideFilters.push(filter); 546 continue;
431 } 547 }
432 548
433 if (url == elt.src) 549 if (url == elt.src)
434 { 550 addSelector(escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute("s rc")) + ']');
435 var selector = escapeCSS(elt.localName) + '[src=' + quote(elt.getAttribute ("src")) + ']'; 551 }
436
437 if (isHTTP)
438 selectorList.push(selector);
439 else
440 addSelector(selector);
441 }
442 }
443
444 // restore the original style, before generating the fallback filter that
445 // will include the style, and to prevent highlightElements from saving those
446 unhighlightElement(currentElement);
447 552
448 // as last resort, create a filter based on inline styles 553 // as last resort, create a filter based on inline styles
449 if (clickHideFilters.length == 0) 554 if (clickHideFilters.length == 0)
450 { 555 {
451 var style = elt.getAttribute("style"); 556 var style = getOriginalStyle(elt);
452 if (style) 557 if (style)
453 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']'); 558 addSelector(escapeCSS(elt.localName) + '[style=' + quote(style) + ']');
454 } 559 }
455 560
456 // Show popup 561 // Show popup
457 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters); 562 clickHide_showDialog(e.clientX, e.clientY, clickHideFilters);
458 563
459 // Highlight the elements specified by selector in yellow 564 // Highlight the elements specified by selector in yellow
460 highlightElements(selectorList.join(",")); 565 if (selectorList.length > 0)
566 highlightElements(selectorList.join(","));
461 // Now, actually highlight the element the user clicked on in red 567 // Now, actually highlight the element the user clicked on in red
462 highlightElement(currentElement, "#fd1708", "#f6a1b5"); 568 highlightElement(currentElement, "#fd1708", "#f6a1b5");
463 569
464 // Make sure the browser doesn't handle this click 570 // Make sure the browser doesn't handle this click
465 e.preventDefault(); 571 e.preventDefault();
466 e.stopPropagation(); 572 e.stopPropagation();
467 }
468
469 function parseSrcSet(element)
470 {
471 if (!element.srcset)
472 return [];
473
474 var urls = element.srcset.split(",");
475 for (var i = 0; i < urls.length; i++)
476 {
477 var url = urls[i].replace(/^\s+/, "").replace(/(\s+\S+)?\s*$/, "");
478 if (url)
479 urls[i] = resolveURL(url);
480 else
481 urls.splice(i--, 1);
kzar 2014/11/25 18:10:11 Does removing an element from the array you're ite
Sebastian Noack 2014/11/25 19:01:15 Not as long as you decrease the iteration counter
Sebastian Noack 2014/11/25 19:03:11 s/is problamatic/isn't problamatic/
482 }
483
484 return urls;
485 }
486
487 function getElementURLs(elt) {
488 var urls = [];
489
490 if (elt.src)
491 urls.push(elt.src);
492
493 switch (elt.localName)
494 {
495 case "object":
496 var url = elt.getAttribute("data");
497 if (url)
498 return [resolveURL(url)];
499
500 for (var i = 0; i < elt.children.length; i++)
501 {
502 var child = elt.children[i];
503 if (child.localName != "param")
504 continue;
505
506 var name = child.getAttribute("name");
507 if (name != "movie" && name != "src")
508 continue;
509
510 var value = child.getAttribute("value");
511 if (!value)
512 continue;
513
514 return [resolveURL(value)];
515 }
516
517 return [];
518
519 case "video":
520 case "audio":
521 case "picture":
522 for (var i = 0; i < elt.children.length; i++)
523 {
524 var child = elt.children[i];
525
526 if (child.localName != "source")
527 continue;
528
529 if (child.src)
530 urls.push(child.src);
531
532 urls = urls.concat(parseSrcSet(child));
533 }
534
535 break;
536
537 case "img":
538 urls = urls.concat(parseSrcSet(elt));
539 }
540
541 return urls;
542 }
543
544 function hasFilters(element)
kzar 2014/11/26 10:51:22 Maybe a name like "isFilterable" would be better t
kzar 2014/11/26 10:51:22 How come you don't put this function above where i
Sebastian Noack 2014/11/26 11:08:14 As discussed on IRC, it's called "isBlockable" now
Sebastian Noack 2014/11/26 11:08:14 Since it relies on "getElementURLs()", I just put
545 {
546 if (element.id)
547 return true;
548 if (element.classList.length > 0)
549 return true;
550 if (getElementURLs(element).length > 0)
551 return true;
552 if (/:.+:/.test(element.getAttribute("style")))
kzar 2014/11/26 10:51:22 Maybe comment this line to explain what you told m
Sebastian Noack 2014/11/26 11:08:14 Well, this logic isn't new. But I guess I can add
553 return true;
554
555 return false;
556 } 573 }
557 574
558 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js 575 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js
559 // 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.
560 function removeDotSegments(u) { 577 function removeDotSegments(u) {
561 var r = '', m = []; 578 var r = '', m = [];
562 if (/\./.test(u)) { 579 if (/\./.test(u)) {
563 while (u !== undefined && u !== '') { 580 while (u !== undefined && u !== '') {
564 if (u === '.' || u === '..') { 581 if (u === '.' || u === '..') {
565 u = ''; 582 u = '';
(...skipping 23 matching lines...) Expand all
589 // exists before continuing to avoid "Uncaught ReferenceError: ext is not define d". 606 // exists before continuing to avoid "Uncaught ReferenceError: ext is not define d".
590 // See https://crbug.com/416907 607 // See https://crbug.com/416907
591 if ("ext" in window && document instanceof HTMLDocument) 608 if ("ext" in window && document instanceof HTMLDocument)
592 { 609 {
593 // Use a contextmenu handler to save the last element the user right-clicked o n. 610 // Use a contextmenu handler to save the last element the user right-clicked o n.
594 // To make things easier, we actually save the DOM event. 611 // To make things easier, we actually save the DOM event.
595 // We have to do this because the contextMenu API only provides a URL, not the actual 612 // We have to do this because the contextMenu API only provides a URL, not the actual
596 // DOM element. 613 // DOM element.
597 document.addEventListener('contextmenu', function(e) { 614 document.addEventListener('contextmenu', function(e) {
598 lastRightClickEvent = e; 615 lastRightClickEvent = e;
599 }, false); 616 }, true);
600 617
601 document.addEventListener("click", function(event) 618 document.addEventListener("click", function(event)
602 { 619 {
603 // Ignore right-clicks 620 // Ignore right-clicks
604 if (event.button == 2) 621 if (event.button == 2)
605 return; 622 return;
606 623
607 // Search the link associated with the click 624 // Search the link associated with the click
608 var link = event.target; 625 var link = event.target;
609 while (link && !(link instanceof HTMLAnchorElement)) 626 while (link && !(link instanceof HTMLAnchorElement))
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
729 } 746 }
730 break; 747 break;
731 case "clickhide-move": 748 case "clickhide-move":
732 if (clickHideFiltersDialog) 749 if (clickHideFiltersDialog)
733 { 750 {
734 clickHideFiltersDialog.style.left = (parseInt(clickHideFiltersDialog.s tyle.left, 10) + msg.x) + "px"; 751 clickHideFiltersDialog.style.left = (parseInt(clickHideFiltersDialog.s tyle.left, 10) + msg.x) + "px";
735 clickHideFiltersDialog.style.top = (parseInt(clickHideFiltersDialog.st yle.top, 10) + msg.y) + "px"; 752 clickHideFiltersDialog.style.top = (parseInt(clickHideFiltersDialog.st yle.top, 10) + msg.y) + "px";
736 } 753 }
737 break; 754 break;
738 case "clickhide-close": 755 case "clickhide-close":
739 if (clickHideFiltersDialog) 756 if (clickHideFiltersDialog && msg.remove)
740 { 757 {
741 // Explicitly get rid of currentElement 758 // Explicitly get rid of currentElement
742 if (msg.remove && currentElement && currentElement.parentNode) 759 var element = currentElement.prisoner || currentElement;
743 currentElement.parentNode.removeChild(currentElement); 760 if (element && element.parentNode)
761 element.parentNode.removeChild(element);
744 } 762 }
745 clickHide_deactivate(); 763 clickHide_deactivate();
746 break; 764 break;
747 default: 765 default:
748 sendResponse({}); 766 sendResponse({});
749 break; 767 break;
750 } 768 }
751 }); 769 });
752 770
753 if (window == window.top) 771 if (window == window.top)
754 ext.backgroundPage.sendMessage({type: "report-html-page"}); 772 ext.backgroundPage.sendMessage({type: "report-html-page"});
755 } 773 }
LEFTRIGHT
« no previous file | no next file » | Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Toggle Comments ('s')

Powered by Google App Engine
This is Rietveld