home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Adblock for Mozilla. * * The Initial Developer of the Original Code is * Henrik Aasted Sorensen. * Portions created by the Initial Developer are Copyright (C) 2002 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Henrik Aasted Sorensen * Stefan Kinitz * Wladimir Palant * rue * * ***** END LICENSE BLOCK ***** */ // Bool: did adblock successfully load (set by adblock.xul) -- global var. var Loaded; // Bool: is adblock enabled (set by pref-observer) -- global var. var Enabled; // Bool: quickblock background-images (set by pref-observer) -- global var. var QuickblockBackground; // binary array-search -- returns lowest-matching element if found; false otherwise // -- Requires a SORTED array // -- note: sorting with a compareFunction defines ordering -> return: zero::unchanged, pos::first value, neg::second value function abBinSearchArray(array, searchItem) { var low = 0; var high = this.length-1; var searchPoint = 0; var match = false; while ((high-low > 1) && !match) { searchPoint = Math.floor((high-low)/2+low); if (array[pos] == searchItem) match = array[searchPoint]; else { if (searchItem < array[curr]) high = searchPoint; else { if (searchItem > array[curr]) low = searchPoint; } } } return match; } // Status element drag-n-drop var abDrag = function(evt) { clearTimeout(window.abDragCleanup); if (!adblockStatusDrag.statusbar.abDrag) { adblockStatusDrag.statusbar.setAttribute("abdrag", true); // css takes care of stylin' adblockStatusDrag.statusbar.abDrag = true; } //adblockStatusDrag.showBorders(); /*window.addEventListener("dragexit", function(evt, session) { if (adblockStatusDrag.statusbar.abDrag) adblockStatusDrag.scheduleCleanup(); }, true);*/ // these are lost after the drop if (!evt.target.dragLoaded) { evt.target.dragLoaded = true; evt.target.addEventListener("mouseup", function() { setTimeout('adblockStatusDrag.dragCleanup();',5); }, true); } var modEvt = { originalTarget:evt.originalTarget, target:evt.target, preventBubble:function(){} }; evt.preventBubble(); setTimeout(function(modEvt) {nsDragAndDrop.startDrag(modEvt, adblockStatusDrag);}, 50, modEvt); }; var adblockStatusDrag = { load: function() { var loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader); loader.loadSubScript('chrome://global/content/nsDragAndDrop.js'); loader.loadSubScript('chrome://global/content/nsTransferable.js'); dragEnter = function(evt) { nsDragAndDrop.dragEnter(evt, adblockStatusDrag); }; dragOver = function(evt) { nsDragAndDrop.dragOver(evt, adblockStatusDrag); }; // required for drop dragDrop = function(evt) { nsDragAndDrop.drop(evt, adblockStatusDrag); }; dragExit = function(evt) { nsDragAndDrop.dragExit(evt, adblockStatusDrag); }; dragCleanup = function() { adblockStatusDrag.dragCleanup(); }; // adblock status-element this.status = document.getElementById("adblock-status"); this.status.addEventListener("draggesture", abDrag, true); // statusbar this.statusbar = document.getElementById("status-bar"); var child = this.statusbar.firstChild, x = 0, defaultDropArray = new Array(); while (child) { if (child != this.status) { if (!child.id) { var newId = "statusbarpanel-noID"+x; while (document.getElementById(newId)) newId += "x"+x; child.id = newId; child.setAttribute("persist", new String("id" + (child.persist ? " "+child.persist : "")) ); x++; } if (child.childNodes.length == 0 && document.getAnonymousNodes(child).length == 0) child.setAttribute("abnochildren", true); child.addEventListener("dragenter", dragEnter, true); child.addEventListener("dragover", dragOver, true); child.addEventListener("dragdrop", dragDrop, true); //child.addEventListener("dragexit", dragExit, true); } defaultDropArray.unshift(child.id); child = child.nextSibling; } // global window.addEventListener("dragexit", dragExit, true); return defaultDropArray; // so our load-call (prefObserver) can Right-align against these, by default }, /* statusbar drag-notifier */ onDragStart: function (evt, transferData, action) { transferData.data = new TransferData(); transferData.data.addDataForFlavour("adblock-status-id", this.status.id); }, /* statusbar drag-listener */ getSupportedFlavours: function () { var flavours = new FlavourSet(); flavours.appendFlavour("adblock-status-id"); return flavours; }, onDragEnter: function(evt, session) { /*"mouseover"*/ if (session.sourceNode == this.status) this.showBorders(); //logfile(unlimitedListObject(session)); }, onDragOver: function (evt, flavour, session) { /*"mousemove"*/ /*evt.target.setAttribute("style", "-moz-outline: #AB0000 dotted 2px !important");*/ }, xxcanDrop: function(evt, mDragSession) { return true; }, // whoa- there can be ABSOLUTELY NO DELAYS INLINE: no throw(), alert(), etc. onDrop: function (evt, dropdata, session) { this.scheduleCleanup(); var parent = this.statusbar; var prev = evt.target; while (prev.nodeName.toLowerCase() != "statusbarpanel") prev = prev.parentNode; var midPointCoord = prev.boxObject.x + (prev.boxObject.width/2); // the offset + midpoint midPointCoord += !prev.previousSibling ? (prev.boxObject.width/4) // + additional quarter-coverage for left-most panel : (!prev.nextSibling ? (-prev.boxObject.width/4) : 0); // - less quarter-coverage for right-most panel if (evt.clientX < midPointCoord) prev = prev.previousSibling; var next = (!prev) ? parent.firstChild : (prev.nextSibling != this.status) ? prev.nextSibling : prev.nextSibling.nextSibling; prevString = new Array(); for (var i=0, children=parent.childNodes; i<children.length && children[i]!=next; i++) if (children[i].id && children[i] != this.status && children[i].boxObject.width != 0 // ignore undisplayed elements || children[i].boxObject.x+(0.75*children[i].boxObject.width) > (this.statusbar.boxObject.width/2)) // offset+.75width is over the statusbar midpoint prevString.push(children[i].id); prevString = prevString.reverse().join(","); //adblockPrefObserver.Branch.setCharPref("statusdrop", prevString); // pref-observer will relocate element var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var adblockBranch = "adblock."; var Branch = prefService.getBranch(adblockBranch); Branch.setCharPref("statusdrop", prevString); // pref-observer will relocate element prefService.savePrefFile(null); // save the prefs to disk }, onDragExit: function(evt, session) { /*"mouseout"*/ if (session.sourceNode == this.status) this.scheduleCleanup(); //logfile(unlimitedListObject(session)); }, showBorders: function() { clearTimeout(window.abDragCleanup); if (!this.statusbar.abDrag) { this.statusbar.setAttribute("abdrag", true); // css takes care of stylin' this.statusbar.abDrag = true; } }, scheduleCleanup: function(evt) { clearTimeout(window.abDragCleanup); window.abDragCleanup = setTimeout('adblockStatusDrag.dragCleanup();',700); }, dragCleanup: function(debug) { this.statusbar.setAttribute("abdrag", false); this.statusbar.abDrag = false; //setTimeout("throw('exit: "+debug+"');", 0); } }; // Preferences observer object; implements nsIObserver var adblockPrefObserver = { // Called on window-load load: function() { window.removeEventListener("load", abLoad, true); // remove startup-check -- only run once // load component if (typeof(Components.classes["@mozilla.org/adblock;1"]) == 'undefined') { var appShell = Components.classes["@mozilla.org/appshell/appShellService;1"].getService(Components.interfaces.nsIAppShellService); var hiddenWnd = appShell.hiddenDOMWindow; //wnd.setTimeout('Components.classes["@mozilla.org/moz/jssubscript-loader;1"].getService(Components.interfaces.mozIJSSubScriptLoader).loadSubScript("chrome://adblock/content/component.js")', 0); Components.classes["@mozilla.org/moz/jssubscript-loader;1"].createInstance(Components.interfaces.mozIJSSubScriptLoader).loadSubScript("chrome://adblock/content/component.js", hiddenWnd); Loaded = true; } // we should use an array in the hidden-window to set this when *really* loaded else Loaded = true; var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService); observerService.notifyObservers(null, "Adblock-LoadAPIConstants", null); // copy the apiConstants to the hidden-window, in case we loaded from the root-component window.document.AdblockQuickblocked = false; // initialize quickblock tag -- *before* pref-observer window.document.addEventListener("popupshown", adblockSetContext, true); // sets the context-menu items window.document.addEventListener("adblock-pageblock", adblockPageBlockListener, true); // sets the url / uri for pageblocked tabs // the global arrays for flashblocking -- tracks our overlay divs // -- some pages don't correctly return these with the 'getElementsByTagName' method window.flashblockOverlayArray = new Object(); // the global hash-table of of corresponding flashblock-overlays window.flashblockCounter = 0; // global counter for the identifying the flashblock-overlayed browsers -- starts at zero, never looks back -! var prefService = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); this.adblockBranch = "adblock."; this.Branch = prefService.getBranch(this.adblockBranch); this.windowInit = false; this.statusElement = null, this.statusText = null; this.mainRe = /^adblock\.(enabled|quickblock|quickblockbackground|statusdrop)/; var pref = prefService.getBranch(null); // preferences root node this.pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranchInternal); this.pbi.addObserver(this.adblockBranch, this, true); // keep this last, in case we hit an error. this.observe(null, null, null); }, // nsISupports interface implementation -- for weak-reference by pref-observer service QueryInterface: function(iid) { if (!iid.equals(Components.interfaces.nsISupports) && !iid.equals(Components.interfaces.nsISupportsWeakReference) && !iid.equals(Components.interfaces.nsIObserver)) { dump("Adblock Window Pref-Observer factory object: QI unknown interface: " + iid + "\n"); throw Components.results.NS_ERROR_NO_INTERFACE; } return this; }, // removes the observer-object from service -- called when the window is no longer open removeObserver: function() { this.pbi.removeObserver(this.adblockBranch, this); delete this; }, // observer-function /* subject: [wrapped nsISupports :: nsIPrefBranch], nsIPrefBranchInternal topic: "changed"*/ observe: function(subject, topic, prefName) { // if we don't have a valid window (closed) if ( !(typeof(document) == 'object' && document) ) { this.removeObserver(); // remove the observer.. return; } // ..and don't continue // on window-init, OR a status-critical pref change if (!this.windowInit || this.mainRe.test(prefName)) { /* Globals and Status-Element */ // Create status-element pointers if (!this.windowInit) { this.statusElement = document.getElementById("adblock-status"); this.statusText = document.getAnonymousNodes(this.statusElement)[1]; this.defaultDropArray = window.adblockStatusDrag.load(); // load drag-listeners + default right-alignment } // Status drag-insertion if (!this.windowInit || prefName == "adblock.statusdrop") { if (this.Branch.prefHasUserValue("statusdrop")) var dropArray = this.Branch.getCharPref("statusdrop").split(","); else dropArray = this.defaultDropArray; //else dropArray = "statusbar-updates,progressmeter-statusbar,statusbarpanel-progress,page-theme-button,page-report-button,security-button,privacy-button,offline-status,popupIcon,statusbar-display,component-bar".split(","); var dropPoint = null; while (dropArray.length>0 && !dropPoint) dropPoint = document.getElementById(dropArray.shift()); var parent = this.statusElement.parentNode; var next = (!dropPoint) ? parent.firstChild : (dropPoint.nextSibling != this.statusElement) ? dropPoint.nextSibling : this.statusElement.nextSibling; this.statusElement.removeEventListener("draggesture", abDrag, true); if (next) parent.insertBefore(parent.removeChild(this.statusElement), next); else parent.appendChild(parent.removeChild(this.statusElement)); this.statusElement.addEventListener("draggesture", abDrag, true); this.statusElement.dragLoaded = false; this.statusText = document.getAnonymousNodes(this.statusElement)[1]; // element is rebound on insertion if (this.windowInit) this.observe(null, null, "adblock.enabled"); // we have to reload the status-text } // Enabled / Disabled if (!this.windowInit || prefName == "adblock.enabled") { Enabled = (!this.Branch.prefHasUserValue("enabled") || this.Branch.getBoolPref("enabled")); // default:true if (!Loaded) { this.statusText.value = "Unloaded"; this.statusElement.setAttribute("status", "unloaded"); } else if (!Enabled) { this.statusText.value = "Disabled"; this.statusElement.setAttribute("status", "notlistening"); } else { this.statusText.value = "Adblock"; this.statusElement.setAttribute("status", "enabled"); } } // Quickblock if (!this.windowInit || prefName == "adblock.quickblock") { if (this.Branch.prefHasUserValue("quickblock") && this.Branch.getPrefType("quickblock") == Components.interfaces.nsIPrefBranch.PREF_BOOL) var quickLevel = this.Branch.getBoolPref("quickblock") ? "partial" : "off"; // convert old bool-type pref to new else quickLevel = this.Branch.prefHasUserValue("quickblock") ? this.Branch.getCharPref("quickblock") : "partial"; // default:partial this.statusElement.setAttribute("quickblock", quickLevel); loadQuickblock(quickLevel); } // QuickblockBackground if (!this.windowInit || prefName == "adblock.quickblockbackground") QuickblockBackground = (this.Branch.prefHasUserValue("quickblockbackground") && this.Branch.getBoolPref("quickblockbackground")); // default:false // window-init if (!this.windowInit) { // disable conflicting key-bindings var conflictingKeys, adblockKeys = ["b", "a", "f", "p", "k"]; for (var n = 0 ; n < adblockKeys.length ; n++) { conflictingKeys = document.getElementsByAttribute("key", adblockKeys[n]); for (var q = 0 ; q < conflictingKeys.length ; q++) if (!( /adblock/.test(conflictingKeys[q].getAttribute("id")) ) && conflictingKeys[q].hasAttribute("modifiers")) if (/accel/.test(conflictingKeys[q].getAttribute("modifiers")) && /shift/.test(conflictingKeys[q].getAttribute("modifiers")) ) conflictingKeys[q].parentNode.removeChild(conflictingKeys[q]); } // flag as initialized this.windowInit = true; } } } }; // runs the pref-observer once, by changing a dummy-pref // -- called by the status-element's binding 'onconstruct' (adblock.xml) function initAdblockPrefObserver() { try { var prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var Branch = prefObj.getBranch("adblock."); var tempPref = (Branch.prefHasUserValue("observer")) ? Branch.getCharPref("observer") : "-"; // default:'-' :P switch (tempPref) { case "-": Branch.setCharPref("observer", "*"); break; case "*": Branch.setCharPref("observer", "-"); break; } } catch(e) {} } // toggles the adblock-enable pref -- enabling / disabling blocking function toggleAdblockEnable() { if (!Loaded) return; var prefObj, Branch; if (Enabled) try { prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); Branch = prefObj.getBranch("adblock."); Branch.setBoolPref("enabled", false); } catch(e) { alert("Adblock could not be disabled:\n\n" + e); } else try { prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); Branch = prefObj.getBranch("adblock."); Branch.setBoolPref("enabled", true); } catch(e) { alert("Adblock could not be enabled:\n\n" + e); } } // Checks an element and its children recursively for an attribute. function adblockFindAttribute(element, name) { if (element.hasAttribute(name)) { return element.getAttribute(name); } if (element.hasChildNodes()) { for (var i = 0 ; i < element.childNodes.length ; i++) { var res = adblockFindAttribute(element.childNodes[i], name); if (res != false) return res; } } return false; // Didn't find it! } // sets the url / uri for pageblocked tabs function adblockPageBlockListener(evt) { var pageElementLocal = evt.target; var browsers = window.getBrowser().browsers; // the .getBrowser method resolves tabbed vs. non-tabbed modes -- otherwise, we'd just get .browsers directly // contentWindow: local window - contentDocument: local document for (var i = 0, match = false; i < browsers.length &! match; i++) { try { if (browsers[i].contentDocument == pageElementLocal.ownerDocument) match = browsers[i]; } // end loop catch(e) {alert("Adblock: unable to access browsers[" + i + "].contentWindow:\n\n" + e);} } if (!match) return; //match.webNavigation.stop(Components.interfaces.nsIWebNavigation.STOP_ALL); // no further loading var curHistory = match.webNavigation.sessionHistory; var blockedURL = pageElementLocal.adblockURI.spec; // the url we blocked // if a different page was already loaded if (curHistory.index == -1 || curHistory.getEntryAtIndex(curHistory.index, false).URI.spec != blockedURL) { var ioService = Components.classes['@mozilla.org/network/io-service;1'].getService(Components.interfaces.nsIIOService); var newEntry = Components.classes['@mozilla.org/browser/session-history-entry;1'].createInstance(Components.interfaces.nsISHEntry); var newURI = ioService.newURI(blockedURL, null, null); var origIndex = curHistory.index; var title = "Adblocked: "+pageElementLocal.adblockURI.host.replace(/^www\./, ""); newEntry.SetURI(newURI); newEntry.SetTitle(title); curHistory.QueryInterface(Components.interfaces.nsISHistoryInternal); curHistory.addEntry(newEntry, true); // add a history-item for the unblocked-page curHistory.index = origIndex++; //alert(origIndex+" "+curHistory.index); //match.webNavigation.gotoIndex(origIndex+1); //match.contentDocument.title = "Adblocked: "+title; } //match.currentURI.spec = pageElementLocal.adblockURI.spec; // initialize the blocked-uri, so the urlbar displays proper on tab-switch if (match == window.getBrowser().selectedBrowser) gURLBar.value = pageElementLocal.adblockURI.spec; // set the urlbar manually, if this is the current browser } // sets quickblock pref -- pref-observer catches this function toggleQuickblockEnable() { try { var prefObj = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService); var Branch = prefObj.getBranch("adblock."); } catch(e) { alert("Quickblock could not be toggled:\n\n" + e); return; } if (Branch.prefHasUserValue("quickblock") && Branch.getPrefType("quickblock") == Components.interfaces.nsIPrefBranch.PREF_BOOL) { var quickLevel = Branch.getBoolPref("quickblock") ? "partial" : "off"; // convert old bool-type pref to new Branch.deleteBranch("quickblock"); } else quickLevel = Branch.prefHasUserValue("quickblock") ? Branch.getCharPref("quickblock") : "partial"; // default:partial var nextLevel; switch (quickLevel) { case "off": nextLevel = "partial"; break; case "partial": nextLevel = "full"; break; case "full": nextLevel = "off"; break; } Branch.setCharPref("quickblock", nextLevel); // set the pref } // loads appropriate level of quickblock -- called by pref-observer function loadQuickblock(quickLevel) { switch (quickLevel) { case "full": if (typeof(window._Quickblock) != 'undefined') break; // the listeners are already attached, from 'partial' case "partial": window.document.addEventListener("dblclick", adblockQuickblock, true); // disable link-clicks.. window.document.addEventListener("click", adblockQuickblock, true); // ..and again window.document.addEventListener("mousedown", adblockQuickblock, true); // quickblock listener break case "off": window.document.removeEventListener("mousedown", adblockQuickblock, true); // remove listener window.document.removeEventListener("click", adblockQuickblock, true); window.document.removeEventListener("dblclick", adblockQuickblock, true); try{ window.document.removeEventListener("mousemove", adblockQuickblock, true); window.document.removeEventListener("mouseup", adblockQuickblock, true); } catch(e) {} break; } window._Quickblock = quickLevel; // store the level, so quickblock-listeners know what to do } // intercepts mouse-clicks and hides the dom-elements beneath function adblockQuickblock(evt) { var evType = evt.type, evButton = evt.button, evShift = evt.shiftKey, evCount = evt.detail; var fullBlock = (window._Quickblock == "full") ? true : false; // bool: trap single-clicks too? var item = evt.originalTarget; var itemContainer = evt.target; var deepItem = evt.explicitOriginalTarget; var deepReplacement, deepStyle, itemTag, tagRe; // if quickdrag is ending (mouseup), or the event is new (mouse left the window-area while dragging) // ..disable quickdrag and return if (window._Quickdrag && (evType == "mouseup" || evType == "mousedown" || (evType == "mousemove" &! evShift))) { delete window._Quickdrag; window.document.removeEventListener("mousemove", adblockQuickblock, true); window.document.removeEventListener("mouseup", adblockQuickblock, true); return; } // from here on, only shifted / non-form-submission events matter -- evCount registers at max for form-submission keypresses if (!evShift || (evType == "click" && evCount > 3)) return; // if this is a webpage-element -- for now, all xul-elements remain unblocked (because of window-scrollbars) if ((item != itemContainer) && (item.ownerDocument.baseURI) && (item.prefix != "xul")) { // if we shift-(double)clicked ( +~ drag) if ( ((evType == "dblclick" || (evType == "click" && fullBlock) || (evType == "mousedown" && (evCount > 1 || fullBlock) )) && evButton == 0) || evType == "mousemove" || evType == "mouseup") { evt.preventDefault(); // prevents tripping the context-menu evt.stopPropagation(); // prevents launching hyperlinks evt.preventBubble(); // ditto ? evt.preventCapture(); // double-ditto ? // if we didn't doubleclick if ((evType == "click" || evType == "mousedown") && evCount < 2) return; if (evType == "mouseup") { window.document.removeEventListener("mousemove", adblockQuickblock, true); window.document.removeEventListener("mouseup", adblockQuickblock, true); return; } // ignore further movement, after cancelling if (evType != "click" && evType != "dblclick") { if (evType == "mousedown" &! window.Quickdrag) { // if quickdrag isn't activated, make it so window._Quickdrag = true; window.document.addEventListener("mousemove", adblockQuickblock, true); window.document.addEventListener("mouseup", adblockQuickblock, true); } if (item.tagName) itemTag = item.tagName.toLowerCase(); else itemTag = item.nodeName.toLowerCase(); // background-image removal if (QuickblockBackground) adblockQuickBackground(item, itemTag); // element hiding adblockQuickElement(deepItem, item, itemTag); } } } } // removes background-images from an element and all parent-table elements above it // -- for quickblock function adblockQuickBackground(item, itemTag) { var itemTest, tableItem, tableItemLast, tableChildRe, tableRe; var parentNode1 = false, parentNode2 = false, parentNode3 = false; var domDocNode = Components.interfaces.nsIDOMNode.DOCUMENT_NODE; tableChildRe = /td|tr/; itemTest = tableChildRe.test(itemTag); if (!itemTest && item.parentNode) { // failed; if there's a parent /* parentNode1 = tableChildRe.test(item.parentNode); if (!parentNode1 && item.parentNode.parentNode) { // failed; if there's a grandparent parentNode2 = tableChildRe.test(item.parentNode.parentNode); if (!parentNode2 && item.parentNode.parentNode.parentNode) parentNode3 = tableChildRe.test(item.parentNode.parentNode.parentNode); //failed; if there's a great-grandparent } */ } if ((itemTest || parentNode1 || parentNode2 || parentNode3) && (item.nodeType != domDocNode)) { tableItemLast = item, tableItem = item; tableRe = new RegExp("table"); while ( ! tableRe.test(tableItemLast.nodeName.toLowerCase())) { // crawl to the tabletop :P //tableItem.setAttribute("QuickblockTableBackground", document.defaultView.getComputedStyle(tableItem, null).getPropertyValue("background-image")); tableItem.style.setProperty("background-image", "none", "important"); // kill parent-tableitem's background-image if (tableItem.hasAttribute("background")) tableItem.removeAttribute("background"); if (!tableItem.parentNode || tableItem.parentNode.nodeType == domDocNode) break; tableItemLast = tableItem, tableItem = tableItem.parentNode; } // kill parent-table's parent-container background-image (*whew*) tableItem.style.setProperty("background-image", "none", "important"); if (tableItem.hasAttribute("background")) tableItem.removeAttribute("background"); } else { //if (document.defaultView.getComputedStyle(item, null).backgroundImage != "none") // <- fails item.style.setProperty("background-image", "none", "important"); // kill parent-table-container's background-image if (item.hasAttribute("background")) item.removeAttribute("background"); } } // quick-hides an element function adblockQuickElement(deepItem, item, itemTag) { var tagRe; if (itemTag == "area") { disableMapArea(item); // let adblock handle area-maps.. return; // ..don't continue } tagRe = new RegExp("table|tbody|tr|td|div|span|form|body|html|ul|ol|dl"); // ,"i" to make case-insensitive -- removed for speed if ( ! tagRe.test(itemTag)) { // don't hide block elements.. item.style.visibility = "hidden"; } else { // ..rather, hide what they contain if (item != deepItem) { // if there's a deeper node (usually text) if (deepItem.setAttribute) { deepItem.style.visibility = "hidden"; // hide directly, if possible } else // text has no setAttribute-method.. deepItem.parentNode.style.setProperty("visibility", "hidden", "important"); // ..so hide the parent } } } // toggles the object-override -- ("flashblocking") function toggleObjectOverride() { var selectedPage = document.getElementById("content").selectedBrowser; var page = document.getElementById("content").contentDocument; var pageElement = page.documentElement; var flashblockPosition; if (typeof(page.oncontextmenu) != 'undefined') delete page.oncontextmenu; // <- thehulk.com :P if (pageElement) { if (pageElement.hasAttribute("AdblockFlashblocked")) { objectRemoveOverride(page); // removes all overrides registered in the global array flashblockPosition = pageElement.getAttribute("flashblockPosition"); delete flashblockOverlayArray[flashblockPosition]; // remove our entry from global flashblock hashtable pageElement.removeAttribute("flashblockPosition"); delete page.onunload; pageElement.removeAttribute("AdblockFlashblocked"); } else { pageElement.setAttribute("AdblockFlashblocked", true); // tags the page as "flashblocked" :) page.onunload = "objectRemoveOverride(this)"; // unloads flashblock on page-close -- so the global hashtable doesn't fill up flashblockPosition = new String("smooth" + flashblockCounter); // converts the unique-index to a string for our hashtable flashblockCounter++; // increment the unique-index counter -- to keep it unique flashblockOverlayArray[flashblockPosition] = new Array(); // initializes the global flashblock overlay array pageElement.setAttribute("flashblockPosition", flashblockPosition); // stores the array-position in the document-element objCheckFrames(page, "override"); // checks frames -- adds the overrides } } else return; // no documentElement == no flashblock } // catches all frames / iframes for object-overriding -- requires a page/element function objCheckFrames(page, conditional) { var itemFrames = page.getElementsByTagName("frame"); var itemiFrames = page.getElementsByTagName("iframe"); var frame, iframe; if (itemFrames.length > 0) for (var f = 0 ; f < itemFrames.length ; f++) { frame = itemFrames[f].contentDocument; objCheckFrames(frame, conditional); // recursion for frames } if (itemiFrames.length > 0) for (var g = 0 ; g < itemiFrames.length ; g++) { iframe = itemiFrames[g].contentDocument; objCheckFrames(iframe, conditional); // recursion for iframes } // if we have a valid page, override it if (page.hasChildNodes() && page.defaultView) switch (conditional) { case "override": //alert("overriding"); objectOverride(page); // check the page itself break; /* // DEPRECATED: this whole switch is unneeded now case "remove": //alert("removing"); objectRemoveOverride(page); break; */ } } // overlays all object's / embeds with a configurable div -- requires a page/element // -- overrides their "native" menus function objectOverride(page) { var rawObjects = page.getElementsByTagName("object"); var objects = new Array(); var objectEmbeds = new Array(); var rawEmbeds = page.getElementsByTagName("embed"); var embeds = new Array(); var applets = page.getElementsByTagName("applet"); var possibleTags = ["objects", "object-embeds", "embeds", "applets"]; var itemArray = new Array(); var childDiv, childDivTitle; var childTable, childTableRow, childTableData, childSpan; var x, y; var currentOffset, topmostFrame, flashblockPosition; // if we're in a frame/iframe, we'll need to get the flashblockPosition from our base document if (page.defaultView.frameElement) { topmostFrame = page.defaultView.frameElement; // break out of nested frames/iframes while (topmostFrame.ownerDocument.defaultView.frameElement) topmostFrame = topmostFrame.ownerDocument.defaultView.frameElement; flashblockPosition = topmostFrame.ownerDocument.documentElement.getAttribute("flashblockPosition"); } else flashblockPosition = page.documentElement.getAttribute("flashblockPosition"); // for each object, get its child-embed (if it has one), since only this carries correct width / height attributes for (var t = 0; t < rawObjects.length ; t++) { var children = rawObjects[t].getElementsByTagName("embed"); if (children.length > 0) for (var c = 0; c < children.length; c++) objectEmbeds.push(children[c]); // add child to our embed-array else objects.push(rawObjects[t]); // assume it's blockable if there's no child-embed } // check that our embed-list doesn't contain duplicates of *OBJECT-embeds* -- (we *should* just 'pop' the array, yo) for (var s = 0; s < rawEmbeds.length ; s++) { // fail-safe check for parentnode -- shouldn't ever fail if (rawEmbeds[s].parentNode) if (rawEmbeds[s].parentNode.tagName.toLowerCase() != "object") embeds.push(rawEmbeds[s]); // add any non-Object-embeds to our "accepted" array } // creates and adds the div-overlays for objects and raw-embeds for (var u = 0 ; u < possibleTags.length ; u++) { switch (possibleTags[u]) { case "objects": itemArray = objects; childDivTitle = "AdblockObjectDiv"; break; case "object-embeds": itemArray = objectEmbeds; childDivTitle = "AdblockObjectDiv"; break; case "embeds": itemArray = embeds; childDivTitle = "AdblockEmbedDiv"; break; case "applets": itemArray = applets; childDivTitle = "AdblockAppletDiv"; break; } for (var w = 0 ; w < itemArray.length; w++) if (itemArray[w] != null && itemArray[w].style.display != "none" && itemArray[w].style.visibility != "hidden") { x = itemArray[w].offsetLeft; y = itemArray[w].offsetTop; // if the item is contained by parent elements, add their position in too currentOffset = itemArray[w]; while (currentOffset.offsetParent) { x += currentOffset.offsetParent.offsetLeft; y += currentOffset.offsetParent.offsetTop; currentOffset = currentOffset.offsetParent; // increment the conditional, for while-loop } if (itemArray[w].previousSibling && itemArray[w].previousSibling.attributes && ( itemArray[w].previousSibling.hasAttribute("AdblockObjectDiv") || itemArray[w].previousSibling.hasAttribute("AdblockEmbedDiv") || itemArray[w].previousSibling.hasAttribute("AdblockAppletDiv") ) ) childDiv = itemArray[w].previousSibling; // we already had an overlay-div else { childDiv = page.createElement("div"); // create our div-overlay childDiv.innerHTML = '<table style="width: 100%; height: 100%;"><tr valign="middle"><td ' + childDivTitle + '="true"><span ' + childDivTitle + '="true" style="display: block; text-align: center; vertical-align: middle; background-color: #FFFFFF; color: #777788; font-family: Arial, Helvetica, Sans-serif; font-size: large; font-style: italic; font-variant: small-caps; border-color: #000099; border-width: 2pt 0pt 2pt 0pt; border-style: dashed none dashed none; padding: 2pt 0pt 2pt 0pt; overflow: hidden; clip: rect(auto auto auto auto); xtext-overflow: elipsis; width: 100%;">Flashblock</span></td></tr></table>'; childDiv.setAttribute("width", itemArray[w].offsetWidth + "px"); childDiv.setAttribute("height", itemArray[w].offsetHeight + "px"); childDiv.setAttribute("style", "display: block; overflow: hidden; text-overflow: elipsis; background-color: #FFDFBF; border-color: #999999; border-width: 1px; border-style: solid; position: absolute; width: " + itemArray[w].offsetWidth + "px; height: " + itemArray[w].offsetHeight + "px; left: " + x + "px; top: " + y + "px; z-index: 900; visibility: visible;"); childDiv.setAttribute(childDivTitle, true); childDiv.addEventListener("click", onOverlayClick, true); /* * we're now dealing with child-embeds individually */ itemArray[w].style.visibility = "hidden"; // hide the embedded item itemArray[w].parentNode.insertBefore(childDiv, itemArray[w]); // append our overlay flashblockOverlayArray[flashblockPosition].push(childDiv); // the global pointer, so we can remove *all* overlays later -- stupid abcnews.com itemArray[w]._AdblockOverlay = childDiv; } } } } // removes the div-overlay for all objects / embeds function objectRemoveOverride(page) { var flashblockPosition; var divOverlays; var flashblockedItem; var parentNode; // if we're in a frame/iframe, we'll need to get the flashblockPosition from our base document if (page.defaultView.frameElement) { var topmostFrame = page.defaultView.frameElement; while (topmostFrame.ownerDocument.defaultView.frameElement) topmostFrame = topmostFrame.ownerDocument.defaultView.frameElement; flashblockPosition = topmostFrame.ownerDocument.documentElement.getAttribute("flashblockPosition"); } else flashblockPosition = page.documentElement.getAttribute("flashblockPosition"); divOverlays = flashblockOverlayArray[flashblockPosition]; for (var u = 0 ; u < divOverlays.length ; u++) { if (divOverlays[u].parentNode) parentNode = divOverlays[u].parentNode; else parentNode = divOverlays[u].ownerDocument; flashblockedItem = divOverlays[u].nextSibling; parentNode.removeChild(divOverlays[u]); // <- don't remove until *after* we get it's 'nextSibling' -- duh! flashblockedItem.style.visibility = "visible"; } } // Event handler, Flashblock-Overlay has been clicked function onOverlayClick(event) { var target = event.target; // break out of the overlay and get our target while (target.nodeName.toLowerCase() != "div") target = target.parentNode; target = target.nextSibling; itemFilterDialog(false, target); } // reveals context menu-items as needed function adblockSetContext(evt) { if (evt.target.id != "contentAreaContextMenu") return; var target = gContextMenu.target; //var menuSeparator = document.getElementById("adblock-separator-menuitem"); //var propertyMenuItem = document.getElementById("context-metadata"); // 'Properties' element-id under mozilla 1.3.1 var frameFilter = document.getElementById("adblock-iframe-menuitem"); var frameLevel = 0; // iframe depth-counter var topmostFrame = target.ownerDocument.defaultView.frameElement; if (topmostFrame) if (topmostFrame.nodeName.toLowerCase() == "iframe") { frameLevel = 1; // depth-counter -- begins with current while (topmostFrame.ownerDocument.defaultView.frameElement) { topmostFrame = topmostFrame.ownerDocument.defaultView.frameElement; if (topmostFrame.tagName.toLowerCase() == "iframe") frameLevel++; // only for iframes, increment the counter -- we crawl up all frames } if (frameLevel > 1) frameFilter.label = "Adblock iFrame (" + frameLevel + " deep)"; else frameFilter.label = "Adblock iFrame"; } // reveal relevant item(s) gContextMenu.showItem('adblock-iframe-menuitem', (frameLevel > 0)); gContextMenu.showItem('adblock-image-menuitem', (target.nodeName.toLowerCase() == "img")); gContextMenu.showItem('adblock-maparea-menuitem', (target.nodeName.toLowerCase() == "area")); gContextMenu.showItem('adblock-object-menuitem', (target.hasAttribute && target.hasAttribute("AdblockObjectDiv") )); gContextMenu.showItem('adblock-embed-menuitem', (target.hasAttribute && target.hasAttribute("AdblockEmbedDiv") )); gContextMenu.showItem('adblock-applet-menuitem', (target.hasAttribute && target.hasAttribute("AdblockAppletDiv") )); } // disables a map-area, so we can click on the content beneath it function disableMapArea(areaItem) { if (!areaItem) areaItem = gContextMenu.target; areaItem.setAttribute("AdblockDisabled", true); if (areaItem.hasAttribute("coords")) { areaItem.setAttribute("AdblockCoords", areaItem.getAttribute("coords")); areaItem.removeAttribute("coords"); } //areaItem.style.display = "none"; // UNNEEDED: this has the side-effect of hiding items underneath -- removing the 'coords' is enough } // get the target node for an overlay function getOverlayTarget(target) { while (target.nodeName.toLowerCase() != "div") target = target.parentNode; target = target.nextSibling; return target; } // pops a filter dialog on right-click function itemFilterDialog(isFrame, targetNode) { if (typeof(targetNode) != 'undefined' && targetNode) var node = targetNode; else node = gContextMenu.target; // if the target is a frame / iframe if (typeof(isFrame) != 'undefined' && isFrame) node = node.ownerDocument.defaultView.frameElement; var page = node.ownerDocument; // -ownerDocument -! (ps: iframes don't register a parentNode from within them) var data = node._AdblockData; // passes the target item to the dialogue via window.argument[1] -- allows the item to be refiltered on 'accept' var dialogHandle = window.openDialog("chrome://adblock/content/addfilterdialog.xul","Add filter", "chrome,modal,centerscreen", data[0].spec, node); } // pops a filter window for "All Block-able Items.." function filterAllDialog(filterAll) { var currentPageElement = document.getElementById("content").contentDocument.defaultView.top; var flashblocked = document.getElementById("content").contentDocument.documentElement.hasAttribute("AdblockFlashblocked"); // passes the root-Element to the dialogue via window.argument[0] -- allows page to be refiltered on 'accept' //var filterAllWindow = window.open("chrome://adblock/content/filterall.xul", "adblockableItems", "chrome,centerscreen,resizable", currentPageElement); //filterAllWindow.focus(); window.openDialog("chrome://adblock/content/filterall.xul", "adblockableItems", "chrome,centerscreen,resizable", currentPageElement); } // Open the settings window. function adblockSettings() { var settingsHandle = window.open("chrome://adblock/content/settings.xul", "adblockPreferences", "chrome,resizable,centerscreen,close=no"); settingsHandle.focus(); } /* Open flags #define PR_RDONLY 0x01 #define PR_WRONLY 0x02 #define PR_RDWR 0x04 #define PR_CREATE_FILE 0x08 #define PR_APPEND 0x10 #define PR_TRUNCATE 0x20 #define PR_SYNC 0x40 #define PR_EXCL 0x80 ** File modes .... ** ** CAVEAT: 'mode' is currently only applicable on UNIX platforms. ** The 'mode' argument may be ignored by PR_Open on other platforms. ** ** 00400 Read by owner. ** 00200 Write by owner. ** 00100 Execute (search if a directory) by owner. ** 00040 Read by group. ** 00020 Write by group. ** 00010 Execute by group. ** 00004 Read by others. ** 00002 Write by others ** 00001 Execute by others. ** //init the output stream with realistic options. 420 are the file //options.. .funny huh! outputStream.init( file, 0x04 | 0x08, 420, 0 ); */ /* * Debug-routines */ // status message function debugmsg(str) { window.defaultStatus=str; } // lists everything in an object -- Useful debug-function. function listObject(obj, s) { var res = "List: " + obj + "\n"; for(var list in obj) { if (list.indexOf(s) != -1) res += list + ", "; } alert(res); } // lists items in an object, function invListObject(obj, s) { var res = "List: " + obj + "\n"; for(var list in obj) { if (list.indexOf(s) == -1) res += list + ", "; } alert(res); } // basic alerts function alertMsg1(eventX) { alert("1 :: event: " + eventX); } function alertMsg2(eventX) { alert("2 :: event: " + eventX); } // lists everything in an object -- unlimited function unlimitedListObject(obj) { var res = "List: " + obj + "\n\n"; for(var list in obj) res += list + ": " + eval("obj."+list) + "\n"; //+ " -- " + (eval("obj."+list))?(eval("obj."+list+".nodeName")):null + "\n"; return res + "--\n\n"; } // appends a given string to unique 'logfile.txt' function logfile(logString) { var streamOut = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); var dirService = Components.classes['@mozilla.org/file/directory_service;1'].getService(Components.interfaces.nsIProperties); var logFile = dirService.get("UChrm", Components.interfaces.nsIFile);// lxr.mozilla.org/seamonkey/source/xpcom/io/nsAppDirectoryServiceDefs.h logFile.append("logfile.txt"); // "appends" the file-string to our dir file-obj logFile.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666); // uniquely name file // if the file is writable, append logString if (logFile.isWritable()) { streamOut.init(logFile, 0x02, 0x200, null); //streamOut.flush(); streamOut.write(logString, logString.length); streamOut.close(); } } // Creates a text-listing for an item's nested node structure, n-layers deep -- very useful debug tool function listChildNodesX(itemN, depthX) { if (!itemN.hasChildNodes) return null; if (itemN.hasChildNodes()) { var itemlengthN = itemN.childNodes.length var prefixcharsX = '- - '; var prefixstringX = ' '; var cnodesL = ' '; // if this is our first recursion-call, 'depthX' wont be an array yet if (!depthX[1]) depthX = [0, depthX]; // define iteration counter and recursion limit // sets appropriate indentation, multiplying the prefix-string by our current depth for (var v = 0 ; v < depthX[0] ; v++) prefixstringX += prefixcharsX; cnodesL += ' :' + itemlengthN + '\n'; // prints the number of childnodes for this depth for (var w = 0 ; w < itemlengthN ; w++) { cnodesL += prefixstringX + w + '. ' + itemN.childNodes.item(w); if (itemN.childNodes.item(w).hasChildNodes()) { if (depthX[0] < depthX[1]) { depthX[0]++; cnodesL += listChildNodesX(itemN.childNodes.item(w), depthX); } } else cnodesL += '\n'; } } return cnodesL; }