| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * This file is part of Adblock Plus <https://adblockplus.org/>, | |
| 3 * Copyright (C) 2006-2016 Eyeo GmbH | |
| 4 * | |
| 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 | |
| 7 * published by the Free Software Foundation. | |
| 8 * | |
| 9 * Adblock Plus is distributed in the hope that it will be useful, | |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 12 * GNU General Public License for more details. | |
| 13 * | |
| 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/>. | |
| 16 */ | |
| 17 | |
| 18 // Click-to-hide stuff | |
| 19 var clickHide_activated = false; | |
| 20 var clickHide_filters = null; | |
| 21 var currentElement = null; | |
| 22 var highlightedElementsSelector = null; | |
| 23 var highlightedElementsInterval = null; | |
| 24 var clickHideFiltersDialog = null; | |
| 25 var lastRightClickEvent = null; | |
| 26 var lastRightClickEventValid = false; | |
| 27 var lastMouseOverEvent = null; | |
| 28 | |
| 29 function highlightElement(element, shadowColor, backgroundColor) | |
| 30 { | |
| 31 unhighlightElement(element); | |
| 32 | |
| 33 var highlightWithOverlay = function() | |
| 34 { | |
| 35 var overlay = addElementOverlay(element); | |
| 36 | |
| 37 // If the element isn't displayed no overlay will be added. | |
| 38 // Moreover, we don't need to highlight anything then. | |
| 39 if (!overlay) | |
| 40 return; | |
| 41 | |
| 42 highlightElement(overlay, shadowColor, backgroundColor); | |
| 43 overlay.style.pointerEvents = "none"; | |
| 44 | |
| 45 element._unhighlight = function() | |
| 46 { | |
| 47 overlay.parentNode.removeChild(overlay); | |
| 48 }; | |
| 49 }; | |
| 50 | |
| 51 var highlightWithStyleAttribute = function() | |
| 52 { | |
| 53 var originalBoxShadow = element.style.getPropertyValue("box-shadow"); | |
| 54 var originalBoxShadowPriority = element.style.getPropertyPriority("box-shado
w"); | |
| 55 var originalBackgroundColor = element.style.getPropertyValue("background-col
or"); | |
| 56 var originalBackgroundColorPriority = element.style.getPropertyPriority("bac
kground-color"); | |
| 57 | |
| 58 element.style.setProperty("box-shadow", "inset 0px 0px 5px " + shadowColor,
"important"); | |
| 59 element.style.setProperty("background-color", backgroundColor, "important"); | |
| 60 | |
| 61 element._unhighlight = function() | |
| 62 { | |
| 63 this.style.removeProperty("box-shadow"); | |
| 64 this.style.setProperty( | |
| 65 "box-shadow", | |
| 66 originalBoxShadow, | |
| 67 originalBoxShadowPriority | |
| 68 ); | |
| 69 | |
| 70 this.style.removeProperty("background-color"); | |
| 71 this.style.setProperty( | |
| 72 "background-color", | |
| 73 originalBackgroundColor, | |
| 74 originalBackgroundColorPriority | |
| 75 ); | |
| 76 }; | |
| 77 }; | |
| 78 | |
| 79 if ("prisoner" in element) | |
| 80 highlightWithStyleAttribute(); | |
| 81 else | |
| 82 highlightWithOverlay(); | |
| 83 } | |
| 84 | |
| 85 | |
| 86 function unhighlightElement(element) | |
| 87 { | |
| 88 if ("_unhighlight" in element) | |
| 89 { | |
| 90 element._unhighlight(); | |
| 91 delete element._unhighlight; | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 // Highlight elements according to selector string. This would include | |
| 96 // all elements that would be affected by proposed filters. | |
| 97 function highlightElements(selectorString) { | |
| 98 unhighlightElements(); | |
| 99 | |
| 100 var elements = Array.prototype.slice.call(document.querySelectorAll(selectorSt
ring)); | |
| 101 highlightedElementsSelector = selectorString; | |
| 102 | |
| 103 // Highlight elements progressively. Otherwise the page freezes | |
| 104 // when a lot of elements get highlighted at the same time. | |
| 105 highlightedElementsInterval = setInterval(function() | |
| 106 { | |
| 107 if (elements.length > 0) | |
| 108 { | |
| 109 var element = elements.shift(); | |
| 110 if (element != currentElement) | |
| 111 highlightElement(element, "#fd6738", "#f6e1e5"); | |
| 112 } | |
| 113 else | |
| 114 { | |
| 115 clearInterval(highlightedElementsInterval); | |
| 116 highlightedElementsInterval = null; | |
| 117 } | |
| 118 }, 0); | |
| 119 } | |
| 120 | |
| 121 // Unhighlight all elements, including those that would be affected by | |
| 122 // the proposed filters | |
| 123 function unhighlightElements() { | |
| 124 if (highlightedElementsInterval) | |
| 125 { | |
| 126 clearInterval(highlightedElementsInterval) | |
| 127 highlightedElementsInterval = null; | |
| 128 } | |
| 129 | |
| 130 if (highlightedElementsSelector) | |
| 131 { | |
| 132 Array.prototype.forEach.call( | |
| 133 document.querySelectorAll(highlightedElementsSelector), | |
| 134 unhighlightElement | |
| 135 ); | |
| 136 | |
| 137 highlightedElementsSelector = null; | |
| 138 } | |
| 139 } | |
| 140 | |
| 141 // Adds an overlay to an element, which is probably a Flash object | |
| 142 function addElementOverlay(elt) { | |
| 143 var position = "absolute"; | |
| 144 var offsetX = window.scrollX; | |
| 145 var offsetY = window.scrollY; | |
| 146 | |
| 147 for (var e = elt; e; e = e.parentElement) | |
| 148 { | |
| 149 var style = getComputedStyle(e); | |
| 150 | |
| 151 // If the element isn't rendered (since its or one of its ancestor's | |
| 152 // "display" property is "none"), the overlay wouldn't match the element. | |
| 153 if (style.display == "none") | |
| 154 return null; | |
| 155 | |
| 156 // If the element or one of its ancestors uses fixed postioning, the overlay | |
| 157 // has to use fixed postioning too. Otherwise it might not match the element
. | |
| 158 if (style.position == "fixed") | |
| 159 { | |
| 160 position = "fixed"; | |
| 161 offsetX = offsetY = 0; | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 var overlay = document.createElement('div'); | |
| 166 overlay.prisoner = elt; | |
| 167 overlay.className = "__adblockplus__overlay"; | |
| 168 overlay.setAttribute('style', 'opacity:0.4; display:inline-box; overflow:hidde
n; box-sizing:border-box;'); | |
| 169 var rect = elt.getBoundingClientRect(); | |
| 170 overlay.style.width = rect.width + "px"; | |
| 171 overlay.style.height = rect.height + "px"; | |
| 172 overlay.style.left = (rect.left + offsetX) + "px"; | |
| 173 overlay.style.top = (rect.top + offsetY) + "px"; | |
| 174 overlay.style.position = position; | |
| 175 overlay.style.zIndex = 0x7FFFFFFE; | |
| 176 | |
| 177 // elt.parentNode.appendChild(overlay, elt); | |
| 178 document.documentElement.appendChild(overlay); | |
| 179 return overlay; | |
| 180 } | |
| 181 | |
| 182 // Show dialog asking user whether she wants to add the proposed filters derived | |
| 183 // from selected page element | |
| 184 function clickHide_showDialog(filters) | |
| 185 { | |
| 186 clickHide_filters = filters; | |
| 187 | |
| 188 clickHideFiltersDialog = document.createElement("iframe"); | |
| 189 clickHideFiltersDialog.src = ext.getURL("block.html"); | |
| 190 clickHideFiltersDialog.setAttribute("style", "position: fixed !important; visi
bility: hidden; display: block !important; border: 0px !important;"); | |
| 191 clickHideFiltersDialog.style.WebkitBoxShadow = "5px 5px 20px rgba(0,0,0,0.5)"; | |
| 192 clickHideFiltersDialog.style.zIndex = 0x7FFFFFFF; | |
| 193 | |
| 194 // Position in upper-left all the time | |
| 195 clickHideFiltersDialog.style.left = "50px"; | |
| 196 clickHideFiltersDialog.style.top = "50px"; | |
| 197 | |
| 198 // Make dialog partly transparent when mouse isn't over it so user has a bette
r | |
| 199 // view of what's going to be blocked | |
| 200 clickHideFiltersDialog.onmouseout = function() | |
| 201 { | |
| 202 if (clickHideFiltersDialog) | |
| 203 clickHideFiltersDialog.style.setProperty("opacity", "0.7"); | |
| 204 }; | |
| 205 clickHideFiltersDialog.onmouseover = function() | |
| 206 { | |
| 207 if (clickHideFiltersDialog) | |
| 208 clickHideFiltersDialog.style.setProperty("opacity", "1.0"); | |
| 209 }; | |
| 210 | |
| 211 document.documentElement.appendChild(clickHideFiltersDialog); | |
| 212 } | |
| 213 | |
| 214 // Turn on the choose element to create filter thing | |
| 215 function clickHide_activate() { | |
| 216 if(document == null) | |
| 217 return; | |
| 218 | |
| 219 // If we are already selecting, abort now | |
| 220 if (clickHide_activated || clickHideFiltersDialog) | |
| 221 clickHide_deactivate(); | |
| 222 | |
| 223 // Add overlays for blockable elements that don't emit mouse events, | |
| 224 // so that they can still be selected. | |
| 225 [].forEach.call( | |
| 226 document.querySelectorAll('object,embed,iframe,frame'), | |
| 227 function(element) | |
| 228 { | |
| 229 getFiltersForElement(element, function(filters) | |
| 230 { | |
| 231 if (filters.length > 0) | |
| 232 addElementOverlay(element); | |
| 233 }); | |
| 234 } | |
| 235 ); | |
| 236 | |
| 237 clickHide_activated = true; | |
| 238 document.addEventListener("mousedown", clickHide_stopPropagation, true); | |
| 239 document.addEventListener("mouseup", clickHide_stopPropagation, true); | |
| 240 document.addEventListener("mouseenter", clickHide_stopPropagation, true); | |
| 241 document.addEventListener("mouseleave", clickHide_stopPropagation, true); | |
| 242 document.addEventListener("mouseover", clickHide_mouseOver, true); | |
| 243 document.addEventListener("mouseout", clickHide_mouseOut, true); | |
| 244 document.addEventListener("click", clickHide_mouseClick, true); | |
| 245 document.addEventListener("keydown", clickHide_keyDown, true); | |
| 246 | |
| 247 ext.onExtensionUnloaded.addListener(clickHide_deactivate); | |
| 248 } | |
| 249 | |
| 250 // Called when user has clicked on something and we are waiting for confirmation | |
| 251 // on whether the user actually wants these filters | |
| 252 function clickHide_rulesPending() { | |
| 253 clickHide_activated = false; | |
| 254 | |
| 255 if (clickHideFiltersDialog) | |
| 256 { | |
| 257 document.documentElement.removeChild(clickHideFiltersDialog); | |
| 258 clickHideFiltersDialog = null; | |
| 259 } | |
| 260 | |
| 261 document.removeEventListener("mousedown", clickHide_stopPropagation, true); | |
| 262 document.removeEventListener("mouseup", clickHide_stopPropagation, true); | |
| 263 document.removeEventListener("mouseenter", clickHide_stopPropagation, true); | |
| 264 document.removeEventListener("mouseleave", clickHide_stopPropagation, true); | |
| 265 document.removeEventListener("mouseover", clickHide_mouseOver, true); | |
| 266 document.removeEventListener("mouseout", clickHide_mouseOut, true); | |
| 267 document.removeEventListener("click", clickHide_mouseClick, true); | |
| 268 document.removeEventListener("keydown", clickHide_keyDown, true); | |
| 269 } | |
| 270 | |
| 271 function clickHide_deactivate() | |
| 272 { | |
| 273 clickHide_rulesPending(); | |
| 274 | |
| 275 clickHide_filters = null; | |
| 276 lastRightClickEvent = null; | |
| 277 | |
| 278 if (currentElement) | |
| 279 { | |
| 280 currentElement.removeEventListener("contextmenu", clickHide_elementClickHan
dler, true); | |
| 281 unhighlightElement(currentElement); | |
| 282 currentElement = null; | |
| 283 } | |
| 284 unhighlightElements(); | |
| 285 | |
| 286 var overlays = document.getElementsByClassName("__adblockplus__overlay"); | |
| 287 while (overlays.length > 0) | |
| 288 overlays[0].parentNode.removeChild(overlays[0]); | |
| 289 | |
| 290 ext.onExtensionUnloaded.removeListener(clickHide_deactivate); | |
| 291 } | |
| 292 | |
| 293 function clickHide_stopPropagation(e) | |
| 294 { | |
| 295 e.stopPropagation(); | |
| 296 } | |
| 297 | |
| 298 function clickHide_elementClickHandler(e) { | |
| 299 e.preventDefault(); | |
| 300 e.stopPropagation(); | |
| 301 clickHide_mouseClick(e); | |
| 302 } | |
| 303 | |
| 304 function getBlockableElementOrAncestor(element, callback) | |
| 305 { | |
| 306 // We assume that the user doesn't want to block the whole page. | |
| 307 // So we never consider the <html> or <body> element. | |
| 308 while (element && element != document.documentElement | |
| 309 && element != document.body) | |
| 310 { | |
| 311 // We can't handle non-HTML (like SVG) elements, as well as | |
| 312 // <area> elements (see below). So fall back to the parent element. | |
| 313 if (!(element instanceof HTMLElement) || element.localName == "area") | |
| 314 element = element.parentElement; | |
| 315 | |
| 316 // If image maps are used mouse events occur for the <area> element. | |
| 317 // But we have to block the image associated with the <map> element. | |
| 318 else if (element.localName == "map") | |
| 319 { | |
| 320 var images = document.querySelectorAll("img[usemap]"); | |
| 321 var image = null; | |
| 322 | |
| 323 for (var i = 0; i < images.length; i++) | |
| 324 { | |
| 325 var usemap = images[i].getAttribute("usemap"); | |
| 326 var index = usemap.indexOf("#"); | |
| 327 | |
| 328 if (index != -1 && usemap.substr(index + 1) == element.name) | |
| 329 { | |
| 330 image = images[i]; | |
| 331 break; | |
| 332 } | |
| 333 } | |
| 334 | |
| 335 element = image; | |
| 336 } | |
| 337 | |
| 338 // Finally, if none of the above is true, check whether we can generate | |
| 339 // any filters for this element. Otherwise fall back to its parent element. | |
| 340 else | |
| 341 { | |
| 342 getFiltersForElement(element, function(filters) | |
| 343 { | |
| 344 if (filters.length > 0) | |
| 345 callback(element); | |
| 346 else | |
| 347 getBlockableElementOrAncestor(element.parentElement, callback); | |
| 348 }); | |
| 349 | |
| 350 return; | |
| 351 } | |
| 352 } | |
| 353 | |
| 354 // We reached the document root without finding a blockable element. | |
| 355 callback(null); | |
| 356 } | |
| 357 | |
| 358 // Hovering over an element so highlight it | |
| 359 function clickHide_mouseOver(e) | |
| 360 { | |
| 361 lastMouseOverEvent = e; | |
| 362 | |
| 363 getBlockableElementOrAncestor(e.target, function(element) | |
| 364 { | |
| 365 if (e == lastMouseOverEvent) | |
| 366 { | |
| 367 lastMouseOverEvent = null; | |
| 368 | |
| 369 if (clickHide_activated) | |
| 370 { | |
| 371 if (currentElement) | |
| 372 unhighlightElement(currentElement); | |
| 373 | |
| 374 if (element) | |
| 375 { | |
| 376 highlightElement(element, "#d6d84b", "#f8fa47"); | |
| 377 element.addEventListener("contextmenu", clickHide_elementClickHandler,
true); | |
| 378 } | |
| 379 | |
| 380 currentElement = element; | |
| 381 } | |
| 382 } | |
| 383 }); | |
| 384 | |
| 385 e.stopPropagation(); | |
| 386 } | |
| 387 | |
| 388 // No longer hovering over this element so unhighlight it | |
| 389 function clickHide_mouseOut(e) | |
| 390 { | |
| 391 if (!clickHide_activated || currentElement != e.target) | |
| 392 return; | |
| 393 | |
| 394 unhighlightElement(currentElement); | |
| 395 currentElement.removeEventListener("contextmenu", clickHide_elementClickHandle
r, true); | |
| 396 e.stopPropagation(); | |
| 397 } | |
| 398 | |
| 399 // Selects the currently hovered-over filter or cancels selection | |
| 400 function clickHide_keyDown(e) | |
| 401 { | |
| 402 if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 13 /*DOM_VK_RETURN*
/) | |
| 403 clickHide_mouseClick(e); | |
| 404 else if (!e.ctrlKey && !e.altKey && !e.shiftKey && e.keyCode == 27 /*DOM_VK_ES
CAPE*/) | |
| 405 { | |
| 406 ext.backgroundPage.sendMessage( | |
| 407 { | |
| 408 type: "forward", | |
| 409 payload: | |
| 410 { | |
| 411 type: "clickhide-deactivate" | |
| 412 } | |
| 413 }); | |
| 414 e.preventDefault(); | |
| 415 e.stopPropagation(); | |
| 416 } | |
| 417 } | |
| 418 | |
| 419 function getFiltersForElement(element, callback) | |
| 420 { | |
| 421 ext.backgroundPage.sendMessage( | |
| 422 { | |
| 423 type: "compose-filters", | |
| 424 tagName: element.localName, | |
| 425 id: element.id, | |
| 426 src: element.getAttribute("src"), | |
| 427 style: element.getAttribute("style"), | |
| 428 classes: [].slice.call(element.classList), | |
| 429 urls: getURLsFromElement(element), | |
| 430 mediatype: typeMap[element.localName], | |
| 431 baseURL: document.location.href | |
| 432 }, | |
| 433 function(response) | |
| 434 { | |
| 435 callback(response.filters, response.selectors); | |
| 436 } | |
| 437 ); | |
| 438 } | |
| 439 | |
| 440 // When the user clicks, the currentElement is the one we want. | |
| 441 // We should have ABP rules ready for when the | |
| 442 // popup asks for them. | |
| 443 function clickHide_mouseClick(e) | |
| 444 { | |
| 445 if (!currentElement || !clickHide_activated) | |
| 446 return; | |
| 447 | |
| 448 var elt = currentElement; | |
| 449 if (currentElement.classList.contains("__adblockplus__overlay")) | |
| 450 elt = currentElement.prisoner; | |
| 451 | |
| 452 getFiltersForElement(elt, function(filters, selectors) | |
| 453 { | |
| 454 ext.backgroundPage.sendMessage( | |
| 455 { | |
| 456 type: "forward", | |
| 457 payload: | |
| 458 { | |
| 459 type: "clickhide-show-dialog", | |
| 460 clickHideFilters: filters | |
| 461 } | |
| 462 }); | |
| 463 | |
| 464 if (selectors.length > 0) | |
| 465 highlightElements(selectors.join(",")); | |
| 466 | |
| 467 highlightElement(currentElement, "#fd1708", "#f6a1b5"); | |
| 468 }); | |
| 469 | |
| 470 // Make sure the browser doesn't handle this click | |
| 471 e.preventDefault(); | |
| 472 e.stopPropagation(); | |
| 473 } | |
| 474 | |
| 475 // This function Copyright (c) 2008 Jeni Tennison, from jquery.uri.js | |
| 476 // and licensed under the MIT license. See jquery-*.min.js for details. | |
| 477 function removeDotSegments(u) { | |
| 478 var r = '', m = []; | |
| 479 if (/\./.test(u)) { | |
| 480 while (u !== undefined && u !== '') { | |
| 481 if (u === '.' || u === '..') { | |
| 482 u = ''; | |
| 483 } else if (/^\.\.\//.test(u)) { // starts with ../ | |
| 484 u = u.substring(3); | |
| 485 } else if (/^\.\//.test(u)) { // starts with ./ | |
| 486 u = u.substring(2); | |
| 487 } else if (/^\/\.(\/|$)/.test(u)) { // starts with /./ or consists of /. | |
| 488 u = '/' + u.substring(3); | |
| 489 } else if (/^\/\.\.(\/|$)/.test(u)) { // starts with /../ or consists of /
.. | |
| 490 u = '/' + u.substring(4); | |
| 491 r = r.replace(/\/?[^\/]+$/, ''); | |
| 492 } else { | |
| 493 m = u.match(/^(\/?[^\/]*)(\/.*)?$/); | |
| 494 u = m[2]; | |
| 495 r = r + m[1]; | |
| 496 } | |
| 497 } | |
| 498 return r; | |
| 499 } else { | |
| 500 return u; | |
| 501 } | |
| 502 } | |
| 503 | |
| 504 // In Chrome 37-40, the document_end content script (this one) runs properly, wh
ile the | |
| 505 // document_start content scripts (that defines ext) might not. Check whether va
riable ext | |
| 506 // exists before continuing to avoid "Uncaught ReferenceError: ext is not define
d". | |
| 507 // See https://crbug.com/416907 | |
| 508 if ("ext" in window && document instanceof HTMLDocument) | |
| 509 { | |
| 510 // Use a contextmenu handler to save the last element the user right-clicked o
n. | |
| 511 // To make things easier, we actually save the DOM event. | |
| 512 // We have to do this because the contextMenu API only provides a URL, not the
actual | |
| 513 // DOM element. | |
| 514 document.addEventListener('contextmenu', function(e) | |
| 515 { | |
| 516 lastRightClickEvent = e; | |
| 517 // We also need to ensure any old lastRightClickEvent variables in other | |
| 518 // frames are cleared. | |
| 519 lastRightClickEventValid = true; | |
| 520 ext.backgroundPage.sendMessage( | |
| 521 { | |
| 522 type: "forward", | |
| 523 payload: | |
| 524 { | |
| 525 type: "clickhide-clear-last-right-click-event" | |
| 526 } | |
| 527 }); | |
| 528 }, true); | |
| 529 | |
| 530 document.addEventListener("click", function(event) | |
| 531 { | |
| 532 // Ignore right-clicks | |
| 533 if (event.button == 2) | |
| 534 return; | |
| 535 | |
| 536 // Search the link associated with the click | |
| 537 var link = event.target; | |
| 538 while (!(link instanceof HTMLAnchorElement)) | |
| 539 { | |
| 540 link = link.parentNode; | |
| 541 | |
| 542 if (!link) | |
| 543 return; | |
| 544 } | |
| 545 | |
| 546 if (link.protocol == "http:" || link.protocol == "https:") | |
| 547 { | |
| 548 if (link.host != "subscribe.adblockplus.org" || link.pathname != "/") | |
| 549 return; | |
| 550 } | |
| 551 else if (!/^abp:\/*subscribe\/*\?/i.test(link.href)) | |
| 552 return; | |
| 553 | |
| 554 // This is our link - make sure the browser doesn't handle it | |
| 555 event.preventDefault(); | |
| 556 event.stopPropagation(); | |
| 557 | |
| 558 // Decode URL parameters | |
| 559 var params = link.search.substr(1).split("&"); | |
| 560 var title = null; | |
| 561 var url = null; | |
| 562 for (var i = 0; i < params.length; i++) | |
| 563 { | |
| 564 var parts = params[i].split("=", 2); | |
| 565 if (parts.length != 2 || !/\S/.test(parts[1])) | |
| 566 continue; | |
| 567 switch (parts[0]) | |
| 568 { | |
| 569 case "title": | |
| 570 title = decodeURIComponent(parts[1]); | |
| 571 break; | |
| 572 case "location": | |
| 573 url = decodeURIComponent(parts[1]); | |
| 574 break; | |
| 575 } | |
| 576 } | |
| 577 if (!url) | |
| 578 return; | |
| 579 | |
| 580 // Default title to the URL | |
| 581 if (!title) | |
| 582 title = url; | |
| 583 | |
| 584 // Trim spaces in title and URL | |
| 585 title = title.trim(); | |
| 586 url = url.trim(); | |
| 587 if (!/^(https?|ftp):/.test(url)) | |
| 588 return; | |
| 589 | |
| 590 ext.backgroundPage.sendMessage({ | |
| 591 type: "add-subscription", | |
| 592 title: title, | |
| 593 url: url | |
| 594 }); | |
| 595 }, true); | |
| 596 | |
| 597 ext.onMessage.addListener(function(msg, sender, sendResponse) | |
| 598 { | |
| 599 switch (msg.type) | |
| 600 { | |
| 601 case "get-clickhide-state": | |
| 602 sendResponse({active: clickHide_activated}); | |
| 603 break; | |
| 604 case "clickhide-activate": | |
| 605 clickHide_activate(); | |
| 606 break; | |
| 607 case "clickhide-deactivate": | |
| 608 clickHide_deactivate(); | |
| 609 break; | |
| 610 case "clickhide-new-filter": | |
| 611 if(lastRightClickEvent) | |
| 612 { | |
| 613 var event = lastRightClickEvent; | |
| 614 getBlockableElementOrAncestor(event.target, function(element) | |
| 615 { | |
| 616 clickHide_activate(); | |
| 617 currentElement = element; | |
| 618 clickHide_mouseClick(event); | |
| 619 }); | |
| 620 } | |
| 621 break; | |
| 622 case "clickhide-init": | |
| 623 if (clickHideFiltersDialog) | |
| 624 { | |
| 625 sendResponse({filters: clickHide_filters}); | |
| 626 | |
| 627 clickHideFiltersDialog.style.width = msg.width + "px"; | |
| 628 clickHideFiltersDialog.style.height = msg.height + "px"; | |
| 629 clickHideFiltersDialog.style.visibility = "visible"; | |
| 630 } | |
| 631 break; | |
| 632 case "clickhide-move": | |
| 633 if (clickHideFiltersDialog) | |
| 634 { | |
| 635 var rect = clickHideFiltersDialog.getBoundingClientRect(); | |
| 636 var x = Math.max(0, Math.min(rect.left + msg.x, window.innerWidth - re
ct.width)); | |
| 637 var y = Math.max(0, Math.min(rect.top + msg.y, window.innerHeight - re
ct.height)); | |
| 638 | |
| 639 clickHideFiltersDialog.style.left = x + "px"; | |
| 640 clickHideFiltersDialog.style.top = y + "px"; | |
| 641 } | |
| 642 break; | |
| 643 case "clickhide-close": | |
| 644 if (currentElement && msg.remove) | |
| 645 { | |
| 646 // Hide the selected element itself if an added blocking | |
| 647 // filter is causing it to collapse. Note that this | |
| 648 // behavior is incomplete, but the best we can do here, | |
| 649 // e.g. if an added blocking filter matches other elements, | |
| 650 // the effect won't be visible until the page is is reloaded. | |
| 651 checkCollapse(currentElement.prisoner || currentElement); | |
| 652 | |
| 653 // Apply added element hiding filters. | |
| 654 updateStylesheet(); | |
| 655 } | |
| 656 clickHide_deactivate(); | |
| 657 break; | |
| 658 case "clickhide-show-dialog": | |
| 659 clickHide_rulesPending(); | |
| 660 if (window.self == window.top) | |
| 661 clickHide_showDialog(msg.clickHideFilters); | |
| 662 break; | |
| 663 case "clickhide-clear-last-right-click-event": | |
| 664 if (lastRightClickEventValid) | |
| 665 lastRightClickEventValid = false; | |
| 666 else | |
| 667 lastRightClickEvent = null; | |
| 668 break; | |
| 669 } | |
| 670 }); | |
| 671 | |
| 672 if (window == window.top) | |
| 673 ext.backgroundPage.sendMessage({type: "report-html-page"}); | |
| 674 } | |
| OLD | NEW |