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>
5
  • 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. Commented Nov 7, 2011 at 0: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. Commented Nov 7, 2011 at 13:45
  • Added a bit of extra code to show how annoying is called. Commented Nov 7, 2011 at 13:45
  • And how onLoad is invoked? :) <body onload="onLoad()"> ? 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). Commented Nov 7, 2011 at 15:01
  • @jakub.gieryluk Yeah, that's how it was called. sigh Commented Nov 7, 2011 at 15:23

4 Answers 4

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>
Sign up to request clarification or add additional context in comments.

2 Comments

Annoying() is called via setTimeout() from the onLoad() function; would I be able to override that using greasemonkey?
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).
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.

4 Comments

meaning, replace their function with something that doesn't bother through firebug.
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
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.
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.
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

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.