home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2006 March / PCWMAR06.iso / Software / FromTheMag / Noscript / noscript-1.1.3.5-fx+mz.xpi / chrome / noscript.jar / content / noscript / noscriptOverlay.js < prev    next >
Encoding:
JavaScript  |  2005-12-08  |  26.3 KB  |  778 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.           
  172.           sites=this.getSites(doc, sites, 'frame');
  173.           sites=this.getSites(doc, sites, 'iframe');
  174.           if(!sites.loading) ns.pluginsCache.purge(sites.pluginsCache, sites.docURIs);
  175.           return ns.sortedSiteSet(sites);
  176.         } else {
  177.           var frames=new XPCNativeWrapper(getByTag(tagName),"item()","length");
  178.           var contentDocument;
  179.           for(var j=frames.length; j-->0;) {
  180.             try {
  181.               contentDocument=lm(frames.item(j),"contentDocument")();
  182.               if(contentDocument) this.getSites(contentDocument,sites);
  183.             } catch(ex2) {
  184.             }
  185.           }
  186.         }
  187.       }
  188.     } catch(ex) {
  189.       // dump(ex);
  190.     }
  191.     if(!sites) {
  192.       sites=[];
  193.       sites.scriptCount=0;
  194.       sites.pluginCount=0;
  195.     }
  196.     return sites;
  197.   }
  198. ,
  199.   get prompter() {
  200.     return this.ns.prompter;
  201.   }
  202. ,
  203.   uninstallAlert: function() {
  204.     this.prompter.alert(window,this.getString("uninstall.alert.title"),
  205.           this.getString("uninstall.alert.text",
  206.             [this.getString("allowed."+(this.ns.jsEnabled?"glb":"no") ) ]
  207.             ));
  208.   }
  209. ,
  210.   prepareContextMenu: function(ev) {
  211.     menu=document.getElementById("noscript-context-menu");
  212.     if(this.ns.uninstalling || !this.ns.getPref("ctxMenu",true)) {
  213.       menu.setAttribute("hidden",true);
  214.       return;
  215.     }
  216.     menu.removeAttribute("hidden");
  217.     const status=document.getElementById("noscript-statusIcon");
  218.     menu.setAttribute("image",status.getAttribute("src"));
  219.     menu.setAttribute("tooltiptext",status.getAttribute("tooltiptext"));
  220.   }
  221. ,
  222.   toggleMenuOpt: function(node) {
  223.     var val=node.getAttribute("checked")=="true";
  224.     var k=node.id.lastIndexOf("-opt-");
  225.     if(k>-1) {
  226.       this.ns.setPref(node.id.substring(5+k),val);
  227.     }
  228.     return val;
  229.   }
  230. ,
  231.   prepareMenu: function(popup) {
  232.     const ns=this.ns;
  233.     var j,k,node;
  234.     
  235.     var opts=popup.getElementsByAttribute("type","checkbox");
  236.     for(j=opts.length; j-->0;) {
  237.       node=opts[j];
  238.       if((k=node.id.lastIndexOf("-opt-"))>-1) {
  239.         node.setAttribute("checked",ns.getPref(node.id.substring(5+k)));
  240.       }
  241.     }
  242.     
  243.     var miNotify=document.getElementById('noscript-mi-notify');
  244.     if(miNotify) miNotify.setAttribute("checked",ns.getPref("notify")); 
  245.     
  246.     const global=ns.jsEnabled;
  247.     
  248.     var separators=popup.getElementsByTagName("menuseparator");
  249.     var insertSep,stopSep,globalSep;
  250.     const sepNames=['insert','stop','global'];
  251.     var sepName;
  252.     for(j=separators.length; j-- >0;) {
  253.       sepName=(node=separators[j]).className;
  254.       for(k in sepNames) {
  255.         if(sepName.indexOf("-"+sepNames[k])>-1) {
  256.           eval(sepNames[k]+"Sep=node");
  257.         }
  258.       }
  259.     }
  260.     
  261.     delete separators;
  262.     const miGlobal=globalSep.nextSibling;
  263.     miGlobal.setAttribute("label",this.getString((global?"forbid":"allow")+"Global"));
  264.     miGlobal.setAttribute("oncommand","noscriptOverlay.menuAllow("+(!global)+")");
  265.     miGlobal.setAttribute("tooltiptext",document.getElementById("noscript-statusIcon").getAttribute("tooltiptext"));
  266.     miGlobal.setAttribute("image",this.getIcon(global?"no":"glb"));
  267.  
  268.     
  269.     node=insertSep.nextSibling;
  270.     const parent=node.parentNode;
  271.     var remNode;
  272.     while(node && (node!=stopSep)) {
  273.        remNode=node;
  274.        node=node.nextSibling;
  275.        parent.removeChild(remNode);
  276.     }
  277.     
  278.     const sites=this.getSites();
  279.     var site,enabled,lev;
  280.     var jsPSs=ns.jsPolicySites;
  281.     var matchingSite;
  282.     var menuSites,menuSite,scount;
  283.     var domain,isIP,pos,lastPos,domParts,dpLen,dp,tlds;
  284.     const STLDS=ns.SPECIAL_TLDS;
  285.     var domainDupChecker={
  286.       prev: "",
  287.       check: function(d) {
  288.          d=" "+d+" ";
  289.          if(this.prev.indexOf(d)>-1) return true;
  290.          this.prev+=d;
  291.          return false;
  292.       }
  293.     };
  294.     
  295.     const showAddress=ns.getPref("showAddress",false);
  296.     const showDomain=ns.getPref("showDomain",false);
  297.     const showBase=ns.getPref("showBaseDomain",true);
  298.     const showNothing=!(showAddress||showDomain||showBase);
  299.     
  300.     const showTemp=ns.getPref("showTemp");
  301.    
  302.     for(j=sites.length; j-->0;) {
  303.       site=sites[j];
  304.       matchingSite=jsPSs.matches(site);
  305.       enabled=!!matchingSite;
  306.       if(enabled) {
  307.         if(domainDupChecker.check(matchingSite)) continue;
  308.         menuSites=[matchingSite];
  309.       } else {
  310.         domain=site.match(/.*?:\/\/([^\?\/\\#]+)/); // double check - changed for Unicode compatibility
  311.         if(domain) {
  312.           domain=domain[1];
  313.           if(domain.indexOf(":")>-1) {
  314.             domain=null; // addresses with a specific port can't be enabled by domain
  315.           }
  316.         }
  317.         menuSites=(showAddress || showNothing || !domain)?[site]:[];
  318.         if(domain && (showDomain || showBase)) {
  319.           isIP=/^[\d\.]+$/.test(domain);
  320.           if(isIP || (lastPos=domain.lastIndexOf('.'))<0
  321.             || (dpLen=(domParts=domain.split('.')).length)<3) {
  322.             // IP or TLD or 2nd level domain
  323.             if(!domainDupChecker.check(domain)) {
  324.               menuSites[menuSites.length]=domain;
  325.             }
  326.           } else {
  327.             // Special TLD (co.uk, co.nz...) or normal domain
  328.             dp=domParts[dpLen-2];
  329.             if(tlds=STLDS[dp]) {
  330.               if(dp == "com" || tlds.indexOf(" " + domParts[dpLen - 1] + " ")>-1) {
  331.                 if(dp != "uk" || 
  332.                   (lastPos = domain.lastIndexOf(".here.co.uk")) != 
  333.                       domain.length - 10) {
  334.                   lastPos = domain.lastIndexOf('.', lastPos - 1);
  335.                 }
  336.               }
  337.             }
  338.             dp=domain;
  339.             for(pos=0; (pos = domain.indexOf('.',pos))>0; dp = domain.substring(++pos)) {
  340.               if(pos==lastPos) {
  341.                 if(menuSites.length>0 && !showBase) continue;
  342.               } else {
  343.                 if(!showDomain) continue;
  344.               }
  345.               if(!domainDupChecker.check(dp)) {
  346.                 menuSites[menuSites.length]=dp;
  347.                 if(pos==lastPos) break;
  348.               }
  349.             }
  350.           }
  351.         }
  352.       }
  353.       if(stopSep.previousSibling.nodeName!="menuseparator") {
  354.         node=document.createElement("menuseparator");
  355.         parent.insertBefore(node,stopSep);
  356.       }
  357.       
  358.       for(scount=menuSites.length; scount-->0;) {
  359.         menuSite=menuSites[scount];
  360.         node=document.createElement("menuitem");
  361.         node.setAttribute("label",this.getString((enabled?"forbidLocal":"allowLocal"),[menuSite]));
  362.         node.setAttribute("statustext",menuSite);
  363.         node.setAttribute("oncommand","noscriptOverlay.menuAllow("+(!enabled)+",this)");
  364.         node.setAttribute("tooltiptext",
  365.           this.getString("allowed."+(enabled?"yes":"no")));
  366.         if(enabled && ns.isPermanent(menuSite)) {
  367.           node.setAttribute("class","");
  368.           node.setAttribute("disabled","true");
  369.           node.style.fontStyle="normal";
  370.         } else {
  371.           node.setAttribute("class","menuitem-iconic");
  372.           node.setAttribute("image",this.getIcon(enabled?"no":"yes"));
  373.           node.style.fontStyle=(enabled && ns.isTemp(menuSite))?"italic":"normal";
  374.         }
  375.         parent.insertBefore(node,stopSep);
  376.         if(showTemp && !enabled) {
  377.           node=node.cloneNode(true);
  378.           node.setAttribute("label",this.getString("allowTemp",[menuSite]));
  379.           node.setAttribute("oncommand","noscriptOverlay.menuAllow(true,this,true)");
  380.           node.style.fontStyle="italic";
  381.           parent.insertBefore(node,stopSep);
  382.         }
  383.       }
  384.     }
  385.     
  386.     const doubleSep = stopSep.previousSibling.nodeName == "menuseparator";
  387.     if(globalSep!=stopSep) { // status bar
  388.       insertSep.setAttribute("hidden", insertSep.nextSibling.getAttribute("hidden")?"true":"false");
  389.       if(doubleSep) stopSep.previousSibling.setAttribute("hidden", "true");
  390.     } else { // context menu
  391.       stopSep.setAttribute("hidden",
  392.         //stopSep==parent.firstChild.nextSibling ||
  393.         doubleSep
  394.         ); 
  395.     }
  396.   }
  397. ,
  398.   get srcWindow() {
  399.     //var w=document.commandDispatcher.focusedWindow;
  400.     return new XPCNativeWrapper(window._content, 'document','getSelection()');
  401.   }
  402. ,
  403.   get srcDocument() {
  404.     return new XPCNativeWrapper(this.srcWindow.document, 'getElementsByTagName()','documentURI');
  405.   }
  406. ,
  407.   getBrowserDoc: function(browser) {
  408.     if(browser && browser.contentWindow) {
  409.       try {
  410.         return this.ns.lookupMethod(browser.contentWindow,'document')();
  411.       } catch(ex) {
  412.       }
  413.     } 
  414.     return null;
  415.   }
  416. ,
  417.   menuAllow: function(enabled,menuItem,temp) {
  418.     if(menuItem) { // local 
  419.       const site=menuItem.getAttribute("statustext");
  420.       if(!site) return;
  421.     } else { // global
  422.       if(enabled) {
  423.         enabled=this.prompter.confirm(window,this.getString("global.warning.title"),
  424.           this.getString("global.warning.text"));
  425.       }
  426.     }
  427.     this.safeAllow(site,enabled,temp);
  428.   }
  429. ,
  430.   safeAllow: function(site,enabled,temp) {
  431.     const overlay=this;
  432.     const ns=this.ns;
  433.     ns.safeCapsOp(function() {
  434.       if(site) {
  435.         ns.setJSEnabled(site,enabled);
  436.         ns.setTemp(site, enabled && temp);
  437.       } else {
  438.         ns.jsEnabled=enabled;
  439.       }
  440.       overlay.syncUI();
  441.     });
  442.   }
  443. ,
  444.   _iconURL: null,
  445.   getIcon: function(lev,inactive) {
  446.     if(!this._iconURL) this._iconURL=document.getElementById("noscript-statusIcon").src;
  447.     return this._iconURL.replace(/[^\/]*(yes|no|glb|prt)(\d+\.)/,(inactive?"inactive-":"")+lev+"$2");
  448.   }
  449. ,
  450.   _syncInfo: { enqueued: false, uninstallCheck: false }
  451. ,
  452.   syncUI: function(ev) {
  453.     if(ev && ev.eventPhase==ev.AT_TARGET 
  454.         && ev.target==document && ev.type=="focus") {
  455.       this._syncInfo.uninstallCheck=true;
  456.     }
  457.      
  458.     if(!this._syncInfo.enqueued) {
  459.       this._syncInfo.enqueued=true;
  460.       window.setTimeout(function(nso) { 
  461.         try {
  462.           nso._syncUINow();
  463.         } catch(ex) {
  464.           // dump(ex);
  465.         }
  466.         nso._syncInfo.enqueued=false; 
  467.        }, 400, this);
  468.     }
  469.   }
  470. ,
  471.   get messageBoxPos() {
  472.     return this.ns.getPref("notify.bottom",false)?"bottom":"top";
  473.   }
  474. ,
  475.   getMessageBox: function(pos) {
  476.     var b=getBrowser();
  477.     return b.getMessageForBrowser?
  478.         b.getMessageForBrowser(b.selectedBrowser,pos?pos:this.messageBoxPos)
  479.         :null;
  480.   }
  481. ,
  482.   _disablePopup: function(id) {
  483.     const popup=document.getElementById(id);
  484.     if(popup) {
  485.       popup.parentNode.setAttribute("onclick","noscriptOverlay.uninstallAlert()");
  486.       popup.parentNode.removeChild(popup);
  487.     }
  488.   }
  489. ,
  490.   _syncUINow: function() {
  491.    
  492.     const ns=this.ns;
  493.     if(ns.uninstalling) {
  494.       if(this._syncInfo.uninstallCheck && !ns.uninstallAlerted) {
  495.         window.setTimeout(function() { noscriptOverlay.uninstallAlert(); }, 10);
  496.         ns.uninstallAlerted=true;
  497.       }
  498.       this._syncInfo.uninstallCheck=false;
  499.       this._disablePopup("noscript-status-popup");
  500.       this._disablePopup("noscript-tbb-popup");
  501.     }
  502.     
  503.     const global=ns.jsEnabled;
  504.     const jsPSs=ns.jsPolicySites;
  505.     var lev;
  506.     const sites=this.getSites();
  507.     var totalScripts=sites.scriptCount;
  508.     var totalPlugins=sites.pluginCount;
  509.     var totalAnnoyances=totalScripts+totalPlugins;
  510.     var notificationNeeded;
  511.     if(global) {
  512.       lev="glb";
  513.       notificationNeeded=false;
  514.     } else {
  515.       var allowed=0;
  516.       var s=sites.length;
  517.       var total=s;
  518.       var url,site;
  519.       while(s-->0) {
  520.         url=sites[s];
  521.         site=jsPSs.matches(url);
  522.         if(site) {
  523.           if(ns.isPermanent(site)) {
  524.             total--;
  525.           } else {
  526.             allowed++;
  527.           }
  528.         } 
  529.       }
  530.       lev=(allowed==total && sites.length>0)?"yes":allowed==0?"no":"prt";
  531.       notificationNeeded=(lev!="yes" && totalAnnoyances>0); 
  532.     }
  533.     
  534.     var message=this.getString("allowed."+lev)
  535.       +" [<script>: "+totalScripts+"] [J+F+P: "+totalPlugins+"]";
  536.     var icon=this.getIcon(lev,!totalAnnoyances);
  537.     
  538.    var widget=document.getElementById("noscript-tbb");
  539.    if(widget) {
  540.      widget.setAttribute("tooltiptext",message);
  541.      widget.setAttribute("image", icon);  
  542.    }
  543.    
  544.    widget=document.getElementById("noscript-statusIcon");
  545.    widget.setAttribute("tooltiptext",message);
  546.    widget.setAttribute("src", icon);
  547.  
  548.    
  549.    
  550.     const mb=this.getMessageBox();
  551.     const mbMine=this.isNsMB(mb);
  552.     if(notificationNeeded) { // notifications
  553.  
  554.       const doc=this.srcWindow.document;
  555.       if(mb) {
  556.         var hidden=mb.hidden;
  557.         if(ns.getPref("notify",false)) { 
  558.           if(mbMine || hidden) {
  559.             if(this.checkDocFlag(doc,"_noscript_message_shown")) {
  560.               const browser=getBrowser();
  561.               var buttonLabel, buttonAccesskey;
  562.               if(/\baButtonAccesskey\b/i.test(browser.showMessage.toSource())) {
  563.                 const refWidget=document.getElementById("noscript-options-ctx-menuitem");
  564.                 buttonLabel=refWidget.getAttribute("label");
  565.                 buttonAccesskey=refWidget.getAttribute("accesskey");
  566.               } else {
  567.                 buttonLabel="";
  568.                 buttonAccesskey="";
  569.               }
  570.               browser.showMessage(browser.selectedBrowser, icon, message, 
  571.                 buttonLabel, null,
  572.                 null, "noscript-notify-popup",this.messageBoxPos,true,
  573.                 buttonAccesskey);
  574.               const delay = (ns.getPref("notify.hide") && ns.getPref("notify.delayHide",3)) || 0;
  575.               if(delay) {
  576.                 window.clearTimeout(this.notifyHideTimeout);
  577.                 this.notifyHideTimeout = window.setTimeout(
  578.                   function() { if(noscriptOverlay.isNsMB(mb)) mb.hidden = true },
  579.                   1000*delay);
  580.               }
  581.             } else if(mbMine && !hidden) {
  582.               mb.text=message;
  583.               mb.image=icon;
  584.             }
  585.             if(!mb._noScriptOneClickPatch) {
  586.               mb._noScriptOneClickPatch = true;
  587.               if(mb._buttonElement && mb._buttonElement.accessKey) { // Fx 1.5
  588.                 // mb.addEventListener("click",_noScript_onMessageClick,false);
  589.               }
  590.             }
  591.           }
  592.         } else if(mbMine && !hidden) {
  593.           mb.hidden=true; 
  594.         }
  595.       }
  596.       if(this.checkDocFlag(doc,"_noscript_sound_played")) {
  597.         ns.playSound(ns.getPref("sound.block"));
  598.       }
  599.     } else {
  600.       if(mbMine && !mb.hidden) {
  601.         mb.hidden=true;
  602.       }
  603.       message = "";
  604.     }
  605.     
  606.     widget=document.getElementById("noscript-statusLabelValue");
  607.     widget.setAttribute("value", message ? message.replace(/JavaScript/g,"JS") : "");
  608.     widget.parentNode.style.display = message ? "block" : "none";
  609.   }
  610. ,
  611.   notifyHideTimeout: 0
  612. ,
  613.   checkDocFlag: function(doc,flag) {
  614.     if(flag in doc && doc[flag]==_noscript_randomSignature) return false;
  615.     doc.__defineGetter__(flag,_noscript_signatureGetter);
  616.     return true;
  617.   }
  618. ,
  619.   isNsMB: function(mb) {
  620.     return mb && mb.popup=="noscript-notify-popup";
  621.   }
  622. }
  623.  
  624. const _noscript_randomSignature=Math.floor(100000000*Math.random());
  625. function _noscript_signatureGetter() { return _noscript_randomSignature; }
  626.  
  627. const noscriptOverlay=new NoScriptOverlay();
  628.  
  629. const noscriptOverlayPrefsObserver = {
  630.   ns: noscriptOverlay.ns,
  631.   iids: [Components.interfaces.nsISupports, Components.interfaces.nsIObserver],
  632.   QueryInterface: function(iid) {
  633.     return this.ns.queryInterfaceSupport(iid, this.iids);
  634.   }
  635. ,
  636.   observe: function(subject, topic, data) {
  637.     switch(data) {
  638.       case "statusIcon": case "statusLabel":  
  639.       window.setTimeout(function() {
  640.           var widget=document.getElementById("noscript-"+data);
  641.           if(widget) {
  642.             widget.setAttribute("hidden", !noscriptOverlay.ns.getPref(data))
  643.           }
  644.         },0);
  645.        break;
  646.        case "notify":
  647.        case "notify.bottom" : 
  648.        var mb=noscriptOverlay.getMessageBox("top");
  649.        if(mb) mb.hidden=true;
  650.        if(mb=noscriptOverlay.getMessageBox("bottom")) mb.hidden=true;
  651.        break;
  652.       
  653.     }
  654.   },
  655.   register: function() {
  656.     this.ns.prefs.addObserver("",this,false);
  657.     const initPrefs = ["statusIcon", "statusLabel"];
  658.     for(var j = 0; j < initPrefs.length; j++) {
  659.       this.observe(null, null, initPrefs[j]);
  660.     }
  661.   },
  662.   remove: function() {
  663.     this.ns.prefs.removeObserver("",this);
  664.   }
  665. };
  666.  
  667. function _noScript_onMessageClick(ev) {
  668.   if(noscriptOverlay.isNsMB(ev.target)) {
  669.     document.getElementById(ev.target.popup)
  670.             .showPopup(ev.target, -1, -1, "popup");
  671.   }
  672. }
  673.  
  674. function _noScript_onPluginClick(ev) {
  675.   const div = ev.currentTarget;
  676.   const applet = div._noScriptRemovedObject;
  677.   if(applet) {
  678.     const ns = noscriptUtil.service;
  679.     const extras = ns.getPluginExtras(div);
  680.     const cache = ns.pluginsCache.get(ns.pluginsCache.findBrowserForNode(div));
  681.     if(! (extras && extras.url && extras.mime && cache) ) return;
  682.     
  683.     var url = extras.url;
  684.     var mime = extras.mime;
  685.     var description = url + "\n(" + mime + ")\n";
  686.     var alwaysAsk = { value: ns.getPref("confirmUnblock", true) };
  687.     if((!alwaysAsk.value) || 
  688.         ns.prompter.confirmCheck(window, "NoScript", 
  689.        noscriptUtil.getString("allowTemp", [description]),
  690.        noscriptUtil.getString("alwaysAsk"), alwaysAsk)
  691.     ) {
  692.       ns.setPref("confirmUnblock", alwaysAsk.value);
  693.       div._noScriptRemovedObject = null;
  694.       cache.forceAllow[url] = mime;
  695.       window.setTimeout(function() {
  696.         const lm = ns.lookupMethod;
  697.         while(lm(div,"hasChildNodes")()) {
  698.           lm(div,"removeChild")(lm(div,"firstChild")());
  699.         }
  700.         lm(lm(div,"parentNode")(),"replaceChild")(applet, div)
  701.       },0);
  702.     }
  703.   }
  704. }
  705.  
  706. function _noScript_syncUI(ev) { 
  707.   noscriptOverlay.syncUI(ev); 
  708. }
  709. function _noScript_prepareCtxMenu(ev) {
  710.     noscriptOverlay.prepareContextMenu(ev);
  711. }
  712.  
  713. function _noScript_openOneBookmark(aURI, aTargetBrowser, aDS) {
  714.   const ns = noscriptUtil.service;
  715.   var snapshot = "";
  716.   if(aTargetBrowser == "current" && !(ns.getPref("forbidBookmarklets", false)  || ns.jsEnabled)) {
  717.     var ncNS = typeof(gNC_NS) == "undefined" ? ( typeof(NC_NS) == "undefined" ?
  718.       "http://home.netscape.com/NC-rdf#" : NC_NS ) : gNC_NS;
  719.     var url = BookmarksUtils.getProperty(aURI, ncNS+"URL", aDS);
  720.     if(!url) return;
  721.     var caughtEx = null;
  722.     try {
  723.       if(url.toLowerCase().indexOf("javascript:") == 0) {
  724.         var browser = getBrowser().selectedBrowser;
  725.         var site = ns.getSite(noscriptOverlay.srcDocument.documentURI);
  726.         if(browser && !ns.isJSEnabled(site)) {
  727.           snapshot = ns.jsPolicySites.sitesString;
  728.           try {
  729.             ns.setJSEnabled(site, true);
  730.             browser.loadURI(url);
  731.           } catch(ex) {
  732.             caughtEx = ex;
  733.           }
  734.           ns.flushCAPS(snapshot);
  735.           if(caughtEx) throw caughtEx;
  736.           return;
  737.         }
  738.       }
  739.     } catch(silentEx) {
  740.       dump(silentEx);
  741.     }
  742.   }
  743.   this._noScript_openOneBookmark_originalMethod(aURI, aTargetBrowser, aDS);
  744. }
  745.  
  746.  
  747. function _noScript_onloadInstall(ev) {
  748.   document.getElementById("contentAreaContextMenu")
  749.           .addEventListener("popupshowing",_noScript_prepareCtxMenu,false);
  750.   BookmarksCommand._noScript_openOneBookmark_originalMethod = BookmarksCommand.openOneBookmark;
  751.   BookmarksCommand.openOneBookmark = _noScript_openOneBookmark;
  752. }
  753.  
  754. const _noScript_syncEvents=["load","focus"];
  755. _noScript_syncEvents.visit=function(callback) {
  756.   for(var e=0,len=this.length; e<len; e++) {
  757.     callback.call(window,this[e],_noScript_syncUI,true);
  758.   }
  759. }
  760. function _noScript_install() {
  761.   _noScript_syncEvents.visit(window.addEventListener);
  762.   window.addEventListener("load",_noScript_onloadInstall,false);
  763.   window.addEventListener("unload",_noScript_dispose,false);
  764.   noscriptOverlayPrefsObserver.register();
  765. }
  766.  
  767. function _noScript_dispose(ev) {
  768.   _noScript_syncEvents.visit(window.removeEventListener);
  769.   noscriptOverlayPrefsObserver.remove();
  770.   window.removeEventListener("load",_noScript_onloadInstall,false);
  771.   document.getElementById("contentAreaContextMenu")
  772.           .removeEventListener("popupshowing",_noScript_prepareCtxMenu,false);  
  773.   
  774. }
  775.  
  776. _noScript_install();
  777.  
  778.