views:

57

answers:

1

I've created a Greasemonkey script which replaces a page function:

(function() {
    var oldFunc = func;
    func = function() {
        oldFunc();
        // other stuff
    };
)();

I had always intended this script to work in both Gresemonkey and Chrome and had read that Chrome doesn't support unsafeWindow, so have been injecting the script into the page by converting the function to a string and using setTimeout:

setTimeout("(function(){var old=func;func=function(){old();/*other stuff*/}}())", 0);

This works perfectly well in Greasemonkey, but gives me absolutely nothing in Chrome. It clearly isn't firing, but nothing appears in the log, either. I have tried a number of other injection styles, but can't get anything to work. (For testing, I also added an alert() to the top of the function.)

  1. setTimeout(..., 0) — nothing
  2. Running the function in-scope, without injection into the page — no alert, but "func is not defined" in console
  3. document.href = "javascript:..." — nothing
  4. document.body.addEventListener("load", ...) — nothing

All of these are with @run-at document-end.

Unfortunately, this being my first Chrome userscript, I'm at a loss as to how to debug it, even after an hour or so of Googling and poking around SO. Any help?

Actual script, currently working in Greasemonkey: http://pastebin.com/HtLVjYHg

A: 

In the end, the only technique I found which worked in Chrome was to create a <script> node using DOM methods. Fortunately, this seems to work equally well in Firefox and Opera and is made fairly painless by <func>.toString():

function embed() {
   var oldFunc = window.func;

    window.func = function() {
        oldFunc();

        // other stuff
    };
}

var inject = document.createElement("script");

inject.setAttribute("type", "text/javascript");
inject.appendChild(document.createTextNode("(" + embed + ")()"));

document.body.appendChild(inject);

Final script: http://userscripts.org/scripts/review/84394

Ben Blank