2

Is there a Firefox extension capable of blocking a single function from embedded javascript in a page?

<html>
    <head>
        <script type='text/javascript'>
            function onLoad(){
                setTimeout(annoying, 1800000);
            }    

            function annoying(){
                //do something annoying
            }


            function useful(){
                //do something useful
            }
        </script>
    </HEAD>
    <BODY  onload="onLoad()">
        <!--rest of page goes here-->
    </BODY>
</HTML>
  • Probably there is not any dedicated extension to do so, but Greasemonkey is a good extension to handle it. I've added "greasemonkey" tag. Moreover I think it might be useful to move it to StackOverflow so more experienced JS people can add their opinions. – jakub.g Nov 07 '11 at 00:06
  • @jakub.gieryluk If the solution's turning into a GM programming question, I'd have no problem switching it to stackoverflow; but I don't know how to do so. – Dan Is Fiddling By Firelight Nov 07 '11 at 13:45
  • Added a bit of extra code to show how annoying is called. – Dan Is Fiddling By Firelight Nov 07 '11 at 13:45
  • And how `onLoad` is invoked? :) `` ? Greasemonkey scripts are executed on `DOMContentLoaded`, so AFAIK it might be too late to override it in that case. I voted to move the question to SO ("flag" below the question -> off-topic -> belongs to SO). – jakub.g Nov 07 '11 at 15:01
  • @jakub.gieryluk Yeah, that's how it was called. *sigh* – Dan Is Fiddling By Firelight Nov 07 '11 at 15:23

4 Answers4

2

Perhaps Greasemonkey is the way to go.

The answer below is quite detailed technical, sorry if I went too far ;)

It depends a bit on how the function annoying() is used by the scripts. I am not yet an expert in JavaScript, some more experienced person's voice could be useful.

If annoying() is used by functions like window.setInterval(), window.setTimeout(), you probably can't overwrite the function directly, because of JavaScript quirks with scoping (closures). When the code window.setTimeout(annoying, 600) is executed, a reference to the "old" annoying is stored and that "old" version is executed. You might then try to get rid of the code that is invoking window.setTimeout on annoying instead.

In other cases, you can add a function with the same name and de facto overwrite the function with the following Greasemonkey userscript:

  function addScript(sourceCode)
  {
     var script = document.createElement('script');
     script.innerHTML = sourceCode;
     var head = document.getElementsByTagName("head")[0];
     head.insertBefore(script, head.firstChild); // insert the script as a first child of <HEAD>
  }
  addScript('function annoying(){alert("overwritten")}');

If you have code like below (I am unable to provide live demo, because it works differently on JSFiddle perhaps because its sandboxing), and the userscript above is launched for that domain, then after 600 milliseconds after page loads, you will have "Nasty alert" alert, but then any time you click the text, you will have "overwritten" alert.

<html>
   <head>
      <script type='text/javascript'>
         function annoying(){
             alert("Nasty alert");
         }

         function useful(){
             //do something useful
         }

         window.setTimeout(annoying, 600); // closure; binds to the function as it is at the moment of execution
      </script>
   </head>
<body>
   <a onclick="annoying()">Click me</a>
</body>
</html>
jakub.g
  • 38,512
  • 12
  • 92
  • 130
  • Annoying() is called via setTimeout() from the onLoad() function; would I be able to override that using greasemonkey? – Dan Is Fiddling By Firelight Nov 07 '11 at 13:41
  • If `setTimeout` is executed, then it's probably too late. You must prevent executing `setTimeout` itself. You can remove timeout with `window.clearTimeout` but it requires timeout ID as a parameter (timeout ID is returned by setTimeou, but in the example you provided, the reference to timeout ID is not stored in any variable). – jakub.g Nov 07 '11 at 15:10
1

I know how to block it per page... I have a script here that is bugging me:

<script type="text/JavaScript">
<!--
function timedRefresh(timeoutPeriod) {
    setTimeout("location.reload(true);",timeoutPeriod);
}
//   -->
</script>
</head> 
<body onload="JavaScript:timedRefresh(300000);">

What these idiots refuse to consider is that if I'm looking around for solutions, I could wind up with 10+ of these page open and 90% of my CPU time is then dedicated to refreshing their pages in the background! grr

I have firebug handy for web development and I just enter this JS command into the console

timedRefresh = function(value){alert(value);}

smile, click ok, and go on my way.

ppostma1
  • 3,616
  • 1
  • 27
  • 28
  • meaning, replace their function with something that doesn't bother through firebug. – ppostma1 Jan 27 '12 at 19:40
  • oh, it calls that settimeout before I can firebug it. One cannot look up and/or terminate a list of timeouts which would be a nice feature. **noscript** will shut that down properly – ppostma1 Jan 27 '12 at 19:50
  • Is this something you have to do manually every time you start the browser/first visit the site? At that point, fixing it ends up having as high of an opportunity cost as just doing what my nuisance script wants in the first place. – Dan Is Fiddling By Firelight Jan 27 '12 at 19:51
  • Also, until the memory leaks are all fixed I'm reluctant to let firebug run when I don't need it; the instability it adds is really annoying. – Dan Is Fiddling By Firelight Jan 27 '12 at 19:52
1

I've posted a solution here: https://stackoverflow.com/a/9699686/6355

Since it's little more than a link here it goes again: http://userscripts.org/scripts/show/125936

Community
  • 1
  • 1
Sarien
  • 6,647
  • 6
  • 35
  • 55
0

This does not help but instead exacerbates the problem.

The following are particularly pernicious and ugly if javascript is enabled:

<script>
    setInterval("alert('irritate')",10)
</script>

or

<script>
    (function(){(function r(){alert('irritate');setTimeout(r,10)})()})()
</script>

though this can be stopped (and all future TimeOuts) by:

javascript:setTimeout=function(){}

perhaps as the URI of a bookmark, provided it can be clicked fast enough.
However,

setInterval("alert('irritate')",10)

can only be stopped by

javascript:setInterval=function(){}

BEFORE the script is run.

Good luck with:

<script>
    (function(){(function r(){alert('irritate');r()})()})()
</script>

or even simpler

<script>
    ( function r(){alert('irritate');r()} ) ()
</script>

Setting alert=function(){} will stop all messages but the script and its recursion of r will not stop until SO or system time out. Also, r is not in the global environment so r=function(){} is ineffective.

Some FF versions need an interesting solution, found on SO, if the alert response is mandatory, to kill the annoying page w/o killing the browser and other open tabs, by using ctrl-F4 to close the tab of the offending page. To aid the manual reflex and dexterity required to do this fast enough, ctrl-Enter is used to respond to the prompt and while ctrl-Enter is pressed F4 is typed.

looped
  • 129
  • 1
  • 3