Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

setTimeout not working in Greasemonkey user script when JS disabled in browser

I'm working on a project that requires my user script be run on pages as they are rendered without executing any of the page's JavaScript. That is to say, we need to browse with JavaScript disabled.

I've encountered a problem though when I try to delay execution of a function within my script. Whenever I make a call to window.setTimeout, the function I pass in never gets executed.

I think maybe this function is actually getting called on unsafeWindow instead of window. Is there any workaround for this?

I should mention that calls to setTimeout work fine when JavaScript is enabled and everything else in my script is working fine without enabling JavaScript.

Thanks for your help!

like image 662
peter Avatar asked Jul 28 '10 17:07

peter


People also ask

Is setTimeout blocking JavaScript?

Explanation: setTimeout() is non-blocking which means it will run when the statements outside of it have executed and then after one second it will execute. All other statements that are not part of setTimeout() are blocking which means no other statement will execute before the current statement finishes.

Is setTimeout part of JavaScript or browser?

While famously known as “JavaScript Timers”, functions like setTimeout and setInterval are not part of the ECMAScript specs or any JavaScript engine implementations. Timer functions are implemented by browsers and their implementations will be different among different browsers.

What we can use instead of setTimeout in JavaScript?

The setInterval method has the same syntax as setTimeout : let timerId = setInterval(func|code, [delay], [arg1], [arg2], ...) All arguments have the same meaning. But unlike setTimeout it runs the function not only once, but regularly after the given interval of time.

Is setTimeout deprecated in JavaScript?

We all know that passing a string to setTimeout (or setInterval ) is evil, because it is run in the global scope, has performance issues, is potentially insecure if you're injecting any parameters, etc. So doing this is definitely deprecated: setTimeout('doSomething(someVar)', 10000);


2 Answers

Even though Greasemonkey JavaScript runs with elevated privileges, as Pointy said, setTimeout functions are appended to the page's JavaScript space -- wrapped in a closure as needed. (In normal operation, the Greasemonkey instance is often gone by the time any timers, it has set, fire.)

So, if the page's main JavaScript is disabled, the timer will never run.

Possible workarounds:

  • Use GM_xmlhttpRequest as a crude delay. You can setup a page that deliberately draws out its response. So code like:

    GM_xmlhttpRequest
    (
        {
            method: "GET",
            url:    "http://YourTestServer.com/DelayService.php?Seconds=2",
            onload: function (response) {YourDelayedFunctionHere (); }
        }
    );
    

    Would call a utility page that you set up to do the delay for you.

  • Use NoScript to disable all of the page's JavaScript except for the main page. For example, for page, YourSite.com/testpage.htm, which includes scripts from, say, *SpamGenerator.net... Allow scripts from YourSite.com but block them from SpamGenerator.net.

like image 181
Brock Adams Avatar answered Oct 30 '22 23:10

Brock Adams


The window reference is still the page's window, just wrapped in the sandbox wrapper thing. When you call setTimeout on it you're still setting up something to be run by the page. I suppose that it must be the case that the browser won't fire those timeout events at all (or will just ignore the events) when Javascript is disabled.

like image 39
Pointy Avatar answered Oct 31 '22 00:10

Pointy