home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2006 June / PCpro_2006_06.ISO / files / firefox / noscript-1.1.3.9-fxflmz.xpi / chrome / noscript.jar / content / noscript / noscriptOverlay.js < prev    next >
Encoding:
JavaScript  |  2006-01-26  |  27.9 KB  |  833 lines

  1. /***** BEGIN LICENSE BLOCK *****
  2.  
  3. NoScript - a Firefox extension for whitelist driven safe JavaScript execution
  4. Copyright (C) 2004-2005 Giorgio Maone - g.maone@informaction.com
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  19.  
  20. ***** END LICENSE BLOCK *****/
  21.  
  22. function NoScriptOverlay() {
  23.   this.ns=noscriptUtil.service;
  24. }
  25.  
  26. NoScriptOverlay.prototype={
  27.   getString: function(key,parms) {
  28.     return noscriptUtil.getString(key,parms);
  29.   }
  30. ,
  31.   isLoading : function() {   
  32.     return getBrowser().selectedBrowser.webProgress.isLoadingDocument;
  33.   }
  34. ,
  35.   getSites: function(doc,sites,tagName) {
  36.     try {
  37.       if(doc || (doc=this.srcWindow.document)) {
  38.         const ns=this.ns;
  39.         const lm=ns.lookupMethod;
  40.         
  41.         if(ns.truncateTitle) {
  42.           try {
  43.             const titleAccessor = lm(doc, "title");
  44.             if(titleAccessor().length > ns.truncateTitleLen) {
  45.               titleAccessor(titleAccessor().substring(0, ns.truncateTitleLen));
  46.             }
  47.           } catch(ex) {}
  48.         }
  49.         
  50.         const getByTag=lm(doc,"getElementsByTagName");
  51.         if(!tagName) {
  52.           const docURI=lm(doc,"documentURI")();
  53.           var url=ns.getSite(docURI);
  54.           if(url) {
  55.             if(sites) {
  56.               sites.push(url);
  57.             } else {
  58.               sites = [url];
  59.               sites.pluginsCache = ns.pluginsCache.get(getBrowser().selectedBrowser);
  60.               sites.scriptCount = 0;
  61.               sites.pluginCount = 0;
  62.               sites.docURIs = {};
  63.               sites.loading = this.isLoading();
  64.             }
  65.             sites.docURIs[docURI] = true;
  66.             var cache = sites.pluginsCache.uris[docURI];
  67.             if(cache) {
  68.               for(url in cache) {
  69.                 sites[sites.length] = url;
  70.               }
  71.             }
  72.           }
  73.           var scripts=new XPCNativeWrapper(getByTag("script"),"item()","length");
  74.           var scount=scripts.length;
  75.           if(scount) {
  76.             sites.scriptCount+=scount;
  77.             var script, scriptSrc;
  78.             while(scount-->0) {
  79.               script=scripts.item(scount);
  80.               if(script instanceof XULElement) {
  81.                 scriptSrc=script.getAttribute("src");
  82.                 if(!/^[\w\-]+:\/\//.test(scriptSrc)) continue;
  83.               } else {
  84.                 scriptSrc=lm(script,"src")();
  85.               }
  86.               scriptSrc=ns.getSite(scriptSrc);
  87.               if(scriptSrc) {
  88.                 sites.push(scriptSrc);
  89.               }
  90.             }
  91.           }
  92.           var pp = ns.showPlaceholder && ns.pluginPlaceholder;
  93.           var replacePlugins = pp && 
  94.                    !(sites.loading || lm(doc,"getElementById")("_noscript_styled")) ;
  95.           
  96.           const appletTags=["embed", "applet", "object"];
  97.           var tcount=appletTags.length;
  98.           var acount, applets, applet, div, innerDiv, appletParent;
  99.           var extras, title;
  100.           var style, cssLen, cssCount, cssProp, cssDef;
  101.           var aWidth,aHeight;
  102.           var createElem;
  103.           while(tcount-->0) {
  104.             var applets=new XPCNativeWrapper(getByTag(appletTags[tcount]),"item()","length");
  105.             for(acount=applets.length; acount-- >0;) {
  106.               applet = applets.item(acount);
  107.               if( (!tcount) && 
  108.                 (lm(applet,"parentNode")() instanceof HTMLObjectElement)) {
  109.                 continue; // skip "embed" if nested into "object"
  110.               }
  111.               
  112.               sites.pluginCount++;
  113.               
  114.               if(replacePlugins) {
  115.                 if(!createElem) {
  116.                   createElem=lm(doc,"createElement");
  117.                   var style=createElem("style");
  118.                   style.setAttribute("id","_noscript_styled");
  119.                   style.setAttribute("type","text/css");
  120.                   style.appendChild(lm(doc,"createTextNode")(
  121.                     ".-noscript-blocked { -moz-outline-color: red !important; -moz-outline-style: solid !important; -moz-outline-width: 1px !important; background: white url(\""
  122.                     + pp + "\") no-repeat left top !important; opacity: 0.6 !important; cursor: pointer !important; margin-top: 0px !important; margin-bottom: 0px !important }"
  123.                   ));
  124.                   try {
  125.                     lm(getByTag("head")[0],"appendChild")(style);
  126.                   } catch(ex) {}
  127.                 }
  128.                 try {
  129.                   if(extras = ns.getPluginExtras(applet)) {
  130.                    
  131.                     
  132.                     div = createElem("div");
  133.                     innerDiv = createElem("div");
  134.                     title = (extras.mime ? extras.mime.replace("application/","")+"@":"@") + url;
  135.                     extras.alt = lm(applet,"getAttribute")("alt");
  136.                     
  137.                     div.setAttribute("title", extras.alt ? title+" \"" + 
  138.                       extras.alt + "\"" : title);
  139.                     
  140.                     div.style.display = "inline";
  141.                     div.style.padding = div.style.margin = "0px";
  142.                      
  143.                     style=lm(lm(doc,"defaultView")(),"getComputedStyle")(applet,"");
  144.                     cssDef="";
  145.                     for(cssCount = 0, cssLen = style.length; cssCount < cssLen; cssCount++) {
  146.                       cssProp=style.item(cssCount);
  147.                       cssDef+=cssProp+": "+style.getPropertyValue(cssProp)+";";
  148.                     }
  149.                     innerDiv.setAttribute("style",cssDef);
  150.                     innerDiv.setAttribute("class", "-noscript-blocked");
  151.                     
  152.                     innerDiv.style.display = "block";
  153.                     
  154.                     div._noScriptRemovedObject = lm(applet, "cloneNode")(true);
  155.                     div._noScriptExtras = extras;
  156.                     
  157.                     while(lm(applet,"hasChildNodes")()) {
  158.                       lm(applet,"removeChild")(lm(applet,"firstChild")());
  159.                     }
  160.                     
  161.                     lm(lm(applet,"parentNode")(),"replaceChild")(div, applet);
  162.                     div.appendChild(innerDiv);
  163.                     div.addEventListener("click", _noScript_onPluginClick, false);
  164.                   }
  165.                 } catch(appletEx) {
  166.                   dump("NoScript: "+appletEx+" processing plugin "+acount+"@"+url);
  167.                 }
  168.               }
  169.             }
  170.           }
  171.           if((!doc._noscript_patch) && 
  172.               (ns.getPref("fixLinks", true) || ns.getPref("noping", true))
  173.               && !(ns.jsEnabled || ns.isJSEnabled(ns.getSite(url))) ) {
  174.             doc._noscript_patch = true;
  175.             doc.addEventListener("click", this.fixLink, true);
  176.           }
  177.           
  178.           sites=this.getSites(doc, sites, 'frame');
  179.           sites=this.getSites(doc, sites, 'iframe');
  180.           if(!sites.loading) ns.pluginsCache.purge(sites.pluginsCache, sites.docURIs);
  181.           return ns.sortedSiteSet(sites);
  182.         } else {
  183.           var frames=new XPCNativeWrapper(getByTag(tagName),"item()","length");
  184.           var contentDocument;
  185.           for(var j=frames.length; j-->0;) {
  186.             try {
  187.               contentDocument=lm(frames.item(j),"contentDocument")();
  188.               if(contentDocument) this.getSites(contentDocument,sites);
  189.             } catch(ex2) {
  190.             }
  191.           }
  192.         }
  193.       }
  194.     } catch(ex) {
  195.       // dump(ex);
  196.     }
  197.     if(!sites) {
  198.       sites=[];
  199.       sites.scriptCount=0;
  200.       sites.pluginCount=0;
  201.     }
  202.     return sites;
  203.   },
  204.   
  205.   fixLink: function(ev) {
  206.     const ns = noscriptOverlay.ns;
  207.     const lm = ns.lookupMethod;
  208.     
  209.     var a = ev.target;
  210.     
  211.     while(!(a instanceof HTMLAnchorElement || a instanceof HTMLMapElement)) {
  212.       if(!(a = a.parentNode)) return;
  213.     }
  214.     
  215.     const getAttr = lm(a, "getAttribute");
  216.     const setAttr = lm(a, "setAttribute");
  217.     
  218.     const href = getAttr("href");
  219.     
  220.     if(ns.getPref("noping", true)) {
  221.       var ping = getAttr("ping");
  222.       if(ping) {
  223.         lm(a, "removeAttribute")("ping");
  224.         setAttr("noping", ping);
  225.       }
  226.     }
  227.     
  228.     var jsURL;
  229.     if(href) {
  230.       jsURL = href.toLowerCase().indexOf("javascript:") == 0;
  231.       if(!(jsURL || href.indexOf("#") == 0)) return;
  232.     } else {
  233.       jsURL = false;
  234.     }
  235.     
  236.     var onclick = getAttr("onclick");
  237.     var fixedHref = fixedHref = (onclick && noscriptOverlay.extractLink(onclick)) || 
  238.                      (jsURL && noscriptOverlay.extractLink(href)) || "";
  239.     
  240.     if(fixedHref) {
  241.       setAttr("href", fixedHref);
  242.       var title = getAttr("title");
  243.       setAttr("title", title ? "[js] " + title : 
  244.         (onclick || "") + " " + href
  245.         );
  246.     }
  247.   },
  248.   
  249.   extractLink: function(js) {
  250.     var match = js.match(/['"]([\/\w-\?\.#%=&:@]+)/);
  251.     return match && match[1];
  252.   }
  253. ,
  254.   get prompter() {
  255.     return this.ns.prompter;
  256.   }
  257. ,
  258.   uninstallAlert: function() {
  259.     this.prompter.alert(window,this.getString("uninstall.alert.title"),
  260.           this.getString("uninstall.alert.text",
  261.             [this.getString("allowed."+(this.ns.jsEnabled?"glb":"no") ) ]
  262.             ));
  263.   }
  264. ,
  265.   prepareContextMenu: function(ev) {
  266.     menu=document.getElementById("noscript-context-menu");
  267.     if(this.ns.uninstalling || !this.ns.getPref("ctxMenu",true)) {
  268.       menu.setAttribute("hidden",true);
  269.       return;
  270.     }
  271.     menu.removeAttribute("hidden");
  272.     const status=document.getElementById("noscript-statusIcon");
  273.     menu.setAttribute("image",status.getAttribute("src"));
  274.     menu.setAttribute("tooltiptext",status.getAttribute("tooltiptext"));
  275.   }
  276. ,
  277.   toggleMenuOpt: function(node) {
  278.     var val=node.getAttribute("checked")=="true";
  279.     var k=node.id.lastIndexOf("-opt-");
  280.     if(k>-1) {
  281.       this.ns.setPref(node.id.substring(5+k),val);
  282.     }
  283.     return val;
  284.   }
  285. ,
  286.   prepareMenu: function(popup) {
  287.     const ns=this.ns;
  288.     var j,k,node;
  289.     
  290.     var opts=popup.getElementsByAttribute("type","checkbox");
  291.     for(j=opts.length; j-->0;) {
  292.       node=opts[j];
  293.       if((k=node.id.lastIndexOf("-opt-"))>-1) {
  294.         node.setAttribute("checked",ns.getPref(node.id.substring(5+k)));
  295.       }
  296.     }
  297.     
  298.     var miNotify=document.getElementById('noscript-mi-notify');
  299.     if(miNotify) miNotify.setAttribute("checked",ns.getPref("notify")); 
  300.     
  301.     const global=ns.jsEnabled;
  302.     
  303.     var separators=popup.getElementsByTagName("menuseparator");
  304.     var insertSep,stopSep,globalSep;
  305.     const sepNames=['insert','stop','global'];
  306.     var sepName;
  307.     for(j=separators.length; j-- >0;) {
  308.       sepName=(node=separators[j]).className;
  309.       for(k in sepNames) {
  310.         if(sepName.indexOf("-"+sepNames[k])>-1) {
  311.           eval(sepNames[k]+"Sep=node");
  312.         }
  313.       }
  314.     }
  315.     
  316.     delete separators;
  317.     const miGlobal = globalSep.nextSibling;
  318.     miGlobal.setAttribute("label",this.getString((global?"forbid":"allow")+"Global"));
  319.     miGlobal.setAttribute("oncommand","noscriptOverlay.menuAllow("+(!global)+")");
  320.     miGlobal.setAttribute("tooltiptext",document.getElementById("noscript-statusIcon").getAttribute("tooltiptext"));
  321.     miGlobal.setAttribute("image",this.getIcon(global?"no":"glb"));
  322.  
  323.     
  324.     node=insertSep.nextSibling;
  325.     const parent=node.parentNode;
  326.     var remNode;
  327.     while(node && (node!=stopSep)) {
  328.        remNode=node;
  329.        node=node.nextSibling;
  330.        parent.removeChild(remNode);
  331.     }
  332.     
  333.     const sites=this.getSites();
  334.     var site,enabled,lev;
  335.     var jsPSs=ns.jsPolicySites;
  336.     var matchingSite;
  337.     var menuSites,menuSite,scount;
  338.     var domain,isIP,pos,lastPos,domParts,dpLen,dp,tlds;
  339.     const STLDS=ns.SPECIAL_TLDS;
  340.     var domainDupChecker={
  341.       prev: "",
  342.       check: function(d) {
  343.          d=" "+d+" ";
  344.          if(this.prev.indexOf(d)>-1) return true;
  345.          this.prev+=d;
  346.          return false;
  347.       }
  348.     };
  349.     
  350.     const showAddress=ns.getPref("showAddress",false);
  351.     const showDomain=ns.getPref("showDomain",false);
  352.     const showBase=ns.getPref("showBaseDomain",true);
  353.     const showNothing=!(showAddress||showDomain||showBase);
  354.     
  355.     const showTemp=ns.getPref("showTemp");
  356.    
  357.     for(j=sites.length; j-->0;) {
  358.       site=sites[j];
  359.       matchingSite=jsPSs.matches(site);
  360.       enabled=!!matchingSite;
  361.       if(enabled) {
  362.         if(domainDupChecker.check(matchingSite)) continue;
  363.         menuSites=[matchingSite];
  364.       } else {
  365.         domain=site.match(/.*?:\/\/([^\?\/\\#]+)/); // double check - changed for Unicode compatibility
  366.         if(domain) {
  367.           domain=domain[1];
  368.           if(domain.indexOf(":")>-1) {
  369.             domain=null; // addresses with a specific port can't be enabled by domain
  370.           }
  371.         }
  372.         menuSites=(showAddress || showNothing || !domain)?[site]:[];
  373.         if(domain && (showDomain || showBase)) {
  374.           isIP=/^[\d\.]+$/.test(domain);
  375.           if(isIP || (lastPos=domain.lastIndexOf('.'))<0
  376.             || (dpLen=(domParts=domain.split('.')).length)<3) {
  377.             // IP or TLD or 2nd level domain
  378.             if(!domainDupChecker.check(domain)) {
  379.               menuSites[menuSites.length]=domain;
  380.             }
  381.           } else {
  382.             // Special TLD (co.uk, co.nz...) or normal domain
  383.             dp=domParts[dpLen-2];
  384.             if(tlds=STLDS[dp]) {
  385.               if(dp == "com" || tlds.indexOf(" " + domParts[dpLen - 1] + " ")>-1) {
  386.                 if(dp != "uk" || 
  387.                   (lastPos = domain.lastIndexOf(".here.co.uk")) != 
  388.                       domain.length - 10) {
  389.                   lastPos = domain.lastIndexOf('.', lastPos - 1);
  390.                 }
  391.               }
  392.             }
  393.             dp=domain;
  394.             for(pos=0; (pos = domain.indexOf('.',pos))>0; dp = domain.substring(++pos)) {
  395.               if(pos==lastPos) {
  396.                 if(menuSites.length>0 && !showBase) continue;
  397.               } else {
  398.                 if(!showDomain) continue;
  399.               }
  400.               if(!domainDupChecker.check(dp)) {
  401.                 menuSites[menuSites.length]=dp;
  402.                 if(pos==lastPos) break;
  403.               }
  404.             }
  405.           }
  406.         }
  407.       }
  408.       if(stopSep.previousSibling.nodeName!="menuseparator") {
  409.         node=document.createElement("menuseparator");
  410.         parent.insertBefore(node,stopSep);
  411.       }
  412.       
  413.       for(scount=menuSites.length; scount-->0;) {
  414.         menuSite=menuSites[scount];
  415.         node=document.createElement("menuitem");
  416.         node.setAttribute("label",this.getString((enabled?"forbidLocal":"allowLocal"),[menuSite]));
  417.         node.setAttribute("statustext",menuSite);
  418.         node.setAttribute("oncommand","noscriptOverlay.menuAllow("+(!enabled)+",this)");
  419.         node.setAttribute("tooltiptext",
  420.           this.getString("allowed."+(enabled?"yes":"no")));
  421.         if(enabled && ns.isPermanent(menuSite)) {
  422.           node.setAttribute("class","");
  423.           node.setAttribute("disabled","true");
  424.           node.style.fontStyle="normal";
  425.         } else {
  426.           node.setAttribute("class","menuitem-iconic");
  427.           node.setAttribute("image",this.getIcon(enabled?"no":"yes"));
  428.           node.style.fontStyle=(enabled && ns.isTemp(menuSite))?"italic":"normal";
  429.         }
  430.         parent.insertBefore(node,stopSep);
  431.         if(showTemp && !enabled) {
  432.           node=node.cloneNode(true);
  433.           node.setAttribute("label",this.getString("allowTemp",[menuSite]));
  434.           node.setAttribute("oncommand","noscriptOverlay.menuAllow(true,this,true)");
  435.           node.style.fontStyle="italic";
  436.           parent.insertBefore(node,stopSep);
  437.         }
  438.       }
  439.     }
  440.     
  441.     const doubleSep = stopSep.previousSibling.nodeName == "menuseparator";
  442.     if(globalSep!=stopSep) { // status bar
  443.       insertSep.setAttribute("hidden", insertSep.nextSibling.getAttribute("hidden")?"true":"false");
  444.       if(doubleSep) stopSep.previousSibling.setAttribute("hidden", "true");
  445.     } else { // context menu
  446.       stopSep.setAttribute("hidden",
  447.         //stopSep==parent.firstChild.nextSibling ||
  448.         doubleSep
  449.         ); 
  450.     }
  451.   }
  452. ,
  453.   get srcWindow() {
  454.     //var w=document.commandDispatcher.focusedWindow;
  455.     return new XPCNativeWrapper(window._content, 'document','getSelection()');
  456.   }
  457. ,
  458.   get srcDocument() {
  459.     return new XPCNativeWrapper(this.srcWindow.document, 'getElementsByTagName()','documentURI');
  460.   }
  461. ,
  462.   getBrowserDoc: function(browser) {
  463.     if(browser && browser.contentWindow) {
  464.       try {
  465.         return this.ns.lookupMethod(browser.contentWindow,'document')();
  466.       } catch(ex) {
  467.       }
  468.     } 
  469.     return null;
  470.   }
  471. ,
  472.   menuAllow: function(enabled,menuItem,temp) {
  473.     if(menuItem) { // local 
  474.       const site=menuItem.getAttribute("statustext");
  475.       if(!site) return;
  476.     } else { // global
  477.       if(enabled) {
  478.         enabled=this.prompter.confirm(window,this.getString("global.warning.title"),
  479.           this.getString("global.warning.text"));
  480.       }
  481.     }
  482.     this.safeAllow(site,enabled,temp);
  483.   }
  484. ,
  485.   safeAllow: function(site,enabled,temp) {
  486.     const overlay=this;
  487.     const ns=this.ns;
  488.     ns.safeCapsOp(function() {
  489.       if(site) {
  490.         ns.setJSEnabled(site,enabled);
  491.         ns.setTemp(site, enabled && temp);
  492.       } else {
  493.         ns.jsEnabled=enabled;
  494.       }
  495.       overlay.syncUI();
  496.     });
  497.   }
  498. ,
  499.   _iconURL: null,
  500.   getIcon: function(lev,inactive) {
  501.     if(!this._iconURL) this._iconURL=document.getElementById("noscript-statusIcon").src;
  502.     return this._iconURL.replace(/[^\/]*(yes|no|glb|prt)(\d+\.)/,(inactive?"inactive-":"")+lev+"$2");
  503.   }
  504. ,
  505.   _syncInfo: { enqueued: false, uninstallCheck: false }
  506. ,
  507.   syncUI: function(ev) {
  508.     if(ev && ev.eventPhase==ev.AT_TARGET 
  509.         && ev.target==document && ev.type=="focus") {
  510.       this._syncInfo.uninstallCheck=true;
  511.     }
  512.      
  513.     if(!this._syncInfo.enqueued) {
  514.       this._syncInfo.enqueued=true;
  515.       window.setTimeout(function(nso) { 
  516.         try {
  517.           nso._syncUINow();
  518.         } catch(ex) {
  519.           // dump(ex);
  520.         }
  521.         nso._syncInfo.enqueued=false; 
  522.        }, 400, this);
  523.     }
  524.   }
  525. ,
  526.   get messageBoxPos() {
  527.     return this.ns.getPref("notify.bottom",false)?"bottom":"top";
  528.   }
  529. ,
  530.   getMessageBox: function(pos) {
  531.     var b=getBrowser();
  532.     return b.getMessageForBrowser?
  533.         b.getMessageForBrowser(b.selectedBrowser,pos?pos:this.messageBoxPos)
  534.         :null;
  535.   }
  536. ,
  537.   _disablePopup: function(id) {
  538.     const popup=document.getElementById(id);
  539.     if(popup) {
  540.       popup.parentNode.setAttribute("onclick","noscriptOverlay.uninstallAlert()");
  541.       popup.parentNode.removeChild(popup);
  542.     }
  543.   }
  544. ,
  545.   _syncUINow: function() {
  546.    
  547.     const ns=this.ns;
  548.     if(ns.uninstalling) {
  549.       if(this._syncInfo.uninstallCheck && !ns.uninstallAlerted) {
  550.         window.setTimeout(function() { noscriptOverlay.uninstallAlert(); }, 10);
  551.         ns.uninstallAlerted=true;
  552.       }
  553.       this._syncInfo.uninstallCheck=false;
  554.       this._disablePopup("noscript-status-popup");
  555.       this._disablePopup("noscript-tbb-popup");
  556.     }
  557.     
  558.     const global=ns.jsEnabled;
  559.     const jsPSs=ns.jsPolicySites;
  560.     var lev;
  561.     const sites=this.getSites();
  562.     var totalScripts=sites.scriptCount;
  563.     var totalPlugins=sites.pluginCount;
  564.     var totalAnnoyances=totalScripts+totalPlugins;
  565.     var notificationNeeded;
  566.     if(global) {
  567.       lev="glb";
  568.       notificationNeeded=false;
  569.     } else {
  570.       var allowed=0;
  571.       var s=sites.length;
  572.       var total=s;
  573.       var url,site;
  574.       while(s-->0) {
  575.         url=sites[s];
  576.         site=jsPSs.matches(url);
  577.         if(site) {
  578.           if(ns.isPermanent(site)) {
  579.             total--;
  580.           } else {
  581.             allowed++;
  582.           }
  583.         } 
  584.       }
  585.       lev=(allowed==total && sites.length>0)?"yes":allowed==0?"no":"prt";
  586.       notificationNeeded=(lev!="yes" && totalAnnoyances>0); 
  587.     }
  588.     
  589.     var message=this.getString("allowed."+lev)
  590.       +" [<script>: "+totalScripts+"] [J+F+P: "+totalPlugins+"]";
  591.     var icon=this.getIcon(lev,!totalAnnoyances);
  592.     
  593.    var widget=document.getElementById("noscript-tbb");
  594.    if(widget) {
  595.      widget.setAttribute("tooltiptext",message);
  596.      widget.setAttribute("image", icon);  
  597.    }
  598.    
  599.    widget=document.getElementById("noscript-statusIcon");
  600.    widget.setAttribute("tooltiptext",message);
  601.    widget.setAttribute("src", icon);
  602.  
  603.    
  604.    
  605.     const mb=this.getMessageBox();
  606.     const mbMine=this.isNsMB(mb);
  607.     if(notificationNeeded) { // notifications
  608.  
  609.       const doc=this.srcWindow.document;
  610.       if(mb) {
  611.         var hidden=mb.hidden;
  612.         if(ns.getPref("notify",false)) { 
  613.           if(mbMine || hidden) {
  614.             if(this.checkDocFlag(doc, "_noscript_message_shown")) {
  615.               const browser=getBrowser();
  616.               var buttonLabel, buttonAccesskey;
  617.               if(/\baButtonAccesskey\b/i.test(browser.showMessage.toSource())) {
  618.                 const refWidget=document.getElementById("noscript-options-ctx-menuitem");
  619.                 buttonLabel=refWidget.getAttribute("label");
  620.                 buttonAccesskey=refWidget.getAttribute("accesskey");
  621.               } else {
  622.                 buttonLabel="";
  623.                 buttonAccesskey="";
  624.               }
  625.               browser.showMessage(browser.selectedBrowser, icon, message, 
  626.                 buttonLabel, null,
  627.                 null, "noscript-notify-popup",this.messageBoxPos,true,
  628.                 buttonAccesskey);
  629.               const delay = (ns.getPref("notify.hide") && ns.getPref("notify.delayHide",3)) || 0;
  630.               if(delay) {
  631.                 window.clearTimeout(this.notifyHideTimeout);
  632.                 this.notifyHideTimeout = window.setTimeout(
  633.                   function() { if(noscriptOverlay.isNsMB(mb)) mb.hidden = true },
  634.                   1000*delay);
  635.               }
  636.             } else if(mbMine && !hidden) {
  637.               mb.text=message;
  638.               mb.image=icon;
  639.             }
  640.             if(!mb._noScriptOneClickPatch) {
  641.               mb._noScriptOneClickPatch = true;
  642.               if(mb._buttonElement && mb._buttonElement.accessKey) { // Fx 1.5
  643.                 // mb.addEventListener("click",_noScript_onMessageClick,false);
  644.               }
  645.             }
  646.           }
  647.         } else if(mbMine && !hidden) {
  648.           mb.hidden=true; 
  649.         }
  650.       }
  651.       if(this.checkDocFlag(doc, "_noscript_sound_played")) {
  652.         ns.playSound(ns.getPref("sound.block"));
  653.       }
  654.     } else {
  655.       if(mbMine && !mb.hidden) {
  656.         mb.hidden=true;
  657.       }
  658.       message = "";
  659.     }
  660.     
  661.     widget=document.getElementById("noscript-statusLabelValue");
  662.     widget.setAttribute("value", message ? message.replace(/JavaScript/g,"JS") : "");
  663.     widget.parentNode.style.display = message ? "block" : "none";
  664.   }
  665. ,
  666.   notifyHideTimeout: 0
  667. ,
  668.   checkDocFlag: function(doc,flag) {
  669.     if(flag in doc && doc[flag]==_noscript_randomSignature) return false;
  670.     doc.__defineGetter__(flag, _noscript_signatureGetter);
  671.     return true;
  672.   }
  673. ,
  674.   isNsMB: function(mb) {
  675.     return mb && mb.popup=="noscript-notify-popup";
  676.   }
  677. }
  678.  
  679. const _noscript_randomSignature=Math.floor(100000000*Math.random());
  680. function _noscript_signatureGetter() { return _noscript_randomSignature; }
  681.  
  682. const noscriptOverlay=new NoScriptOverlay();
  683.  
  684. const noscriptOverlayPrefsObserver = {
  685.   ns: noscriptOverlay.ns,
  686.   iids: [Components.interfaces.nsISupports, Components.interfaces.nsIObserver],
  687.   QueryInterface: function(iid) {
  688.     return this.ns.queryInterfaceSupport(iid, this.iids);
  689.   }
  690. ,
  691.   observe: function(subject, topic, data) {
  692.     switch(data) {
  693.       case "statusIcon": case "statusLabel":  
  694.       window.setTimeout(function() {
  695.           var widget=document.getElementById("noscript-"+data);
  696.           if(widget) {
  697.             widget.setAttribute("hidden", !noscriptOverlay.ns.getPref(data))
  698.           }
  699.         },0);
  700.        break;
  701.        case "notify":
  702.        case "notify.bottom" : 
  703.        var mb=noscriptOverlay.getMessageBox("top");
  704.        if(mb) mb.hidden=true;
  705.        if(mb=noscriptOverlay.getMessageBox("bottom")) mb.hidden=true;
  706.        break;
  707.       
  708.     }
  709.   },
  710.   register: function() {
  711.     this.ns.prefs.addObserver("",this,false);
  712.     const initPrefs = ["statusIcon", "statusLabel"];
  713.     for(var j = 0; j < initPrefs.length; j++) {
  714.       this.observe(null, null, initPrefs[j]);
  715.     }
  716.   },
  717.   remove: function() {
  718.     this.ns.prefs.removeObserver("",this);
  719.   }
  720. };
  721.  
  722. function _noScript_onMessageClick(ev) {
  723.   if(noscriptOverlay.isNsMB(ev.target)) {
  724.     document.getElementById(ev.target.popup)
  725.             .showPopup(ev.target, -1, -1, "popup");
  726.   }
  727. }
  728.  
  729. function _noScript_onPluginClick(ev) {
  730.   const div = ev.currentTarget;
  731.   const applet = div._noScriptRemovedObject;
  732.   if(applet) {
  733.     const ns = noscriptUtil.service;
  734.     const extras = ns.getPluginExtras(div);
  735.     const cache = ns.pluginsCache.get(ns.pluginsCache.findBrowserForNode(div));
  736.     if(! (extras && extras.url && extras.mime && cache) ) return;
  737.     
  738.     var url = extras.url;
  739.     var mime = extras.mime;
  740.     var description = url + "\n(" + mime + ")\n";
  741.     var alwaysAsk = { value: ns.getPref("confirmUnblock", true) };
  742.     if((!alwaysAsk.value) || 
  743.         ns.prompter.confirmCheck(window, "NoScript", 
  744.        noscriptUtil.getString("allowTemp", [description]),
  745.        noscriptUtil.getString("alwaysAsk"), alwaysAsk)
  746.     ) {
  747.       ns.setPref("confirmUnblock", alwaysAsk.value);
  748.       div._noScriptRemovedObject = null;
  749.       cache.forceAllow[url] = mime;
  750.       window.setTimeout(function() {
  751.         const lm = ns.lookupMethod;
  752.         while(lm(div,"hasChildNodes")()) {
  753.           lm(div,"removeChild")(lm(div,"firstChild")());
  754.         }
  755.         lm(lm(div,"parentNode")(),"replaceChild")(applet, div)
  756.       },0);
  757.     }
  758.   }
  759. }
  760.  
  761. function _noScript_syncUI(ev) { 
  762.   noscriptOverlay.syncUI(ev); 
  763. }
  764. function _noScript_prepareCtxMenu(ev) {
  765.     noscriptOverlay.prepareContextMenu(ev);
  766. }
  767.  
  768. function _noScript_openOneBookmark(aURI, aTargetBrowser, aDS) {
  769.   const ns = noscriptUtil.service;
  770.   var snapshot = "";
  771.   if(aTargetBrowser == "current" && !(ns.getPref("forbidBookmarklets", false)  || ns.jsEnabled)) {
  772.     var ncNS = typeof(gNC_NS) == "undefined" ? ( typeof(NC_NS) == "undefined" ?
  773.       "http://home.netscape.com/NC-rdf#" : NC_NS ) : gNC_NS;
  774.     var url = BookmarksUtils.getProperty(aURI, ncNS+"URL", aDS);
  775.     if(!url) return;
  776.     var caughtEx = null;
  777.     try {
  778.       if(url.toLowerCase().indexOf("javascript:") == 0) {
  779.         var browser = getBrowser().selectedBrowser;
  780.         var site = ns.getSite(noscriptOverlay.srcDocument.documentURI);
  781.         if(browser && !ns.isJSEnabled(site)) {
  782.           snapshot = ns.jsPolicySites.sitesString;
  783.           try {
  784.             ns.setJSEnabled(site, true);
  785.             browser.loadURI(url);
  786.           } catch(ex) {
  787.             caughtEx = ex;
  788.           }
  789.           ns.flushCAPS(snapshot);
  790.           if(caughtEx) throw caughtEx;
  791.           return;
  792.         }
  793.       }
  794.     } catch(silentEx) {
  795.       dump(silentEx);
  796.     }
  797.   }
  798.   this._noScript_openOneBookmark_originalMethod(aURI, aTargetBrowser, aDS);
  799. }
  800.  
  801.  
  802. function _noScript_onloadInstall(ev) {
  803.   document.getElementById("contentAreaContextMenu")
  804.           .addEventListener("popupshowing",_noScript_prepareCtxMenu,false);
  805.   BookmarksCommand._noScript_openOneBookmark_originalMethod = BookmarksCommand.openOneBookmark;
  806.   BookmarksCommand.openOneBookmark = _noScript_openOneBookmark;
  807. }
  808.  
  809. const _noScript_syncEvents=["load","focus"];
  810. _noScript_syncEvents.visit=function(callback) {
  811.   for(var e=0,len=this.length; e<len; e++) {
  812.     callback.call(window,this[e],_noScript_syncUI,true);
  813.   }
  814. }
  815. function _noScript_install() {
  816.   _noScript_syncEvents.visit(window.addEventListener);
  817.   window.addEventListener("load", _noScript_onloadInstall,false);
  818.   window.addEventListener("unload", _noScript_dispose,false);
  819.   noscriptOverlayPrefsObserver.register();
  820. }
  821.  
  822. function _noScript_dispose(ev) {
  823.   _noScript_syncEvents.visit(window.removeEventListener);
  824.   noscriptOverlayPrefsObserver.remove();
  825.   window.removeEventListener("load", _noScript_onloadInstall, false);
  826.   document.getElementById("contentAreaContextMenu")
  827.           .removeEventListener("popupshowing",_noScript_prepareCtxMenu,false);  
  828.   
  829. }
  830.  
  831. _noScript_install();
  832.  
  833.