views:

184

answers:

2

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!

A: 

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.

Pointy
But since it's wrapped up, it isn't *really* the page's window, right? Greasemonkey gets to define its behavior, instead of the page being allowed to do this. I'm wondering if GM maybe just punts on the function call and allows the original window (ie. unsafeWindow) to deal with it. (Edit: In the end, my understanding is the same as yours. The call gets set up and ignored. Now I'm just wondering if there's any way around this. Maybe some way to delay function execution outside of using window object...?)
peter
Well Greasemonkey might not get a say in the matter if the browser thinks that it shouldn't run any Javascript event handlers. I have not found any explicit documentation that says what happens when Javascript is disabled on a page. Obviously the "native" event handling still works - you can still submit forms by clicking "submit" buttons for example, and checkboxes and radio buttons work.
Pointy
+1  A: 

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.

Brock Adams
NoScript as it turns out doesn't work for me, since I need to disable JavaScript from the main page as well as from any other sources that aren't my user script. The XMLhttpRequest on the other hand works beautifully (even though it's a total hack).Thanks for the insight, Brock!
peter
@user360010: You're welcome. Glad to help!
Brock Adams