0.7.20080121.0 compatibility
From GreaseSpot
Greasemonkey 0.7.20080121.0 introduced a change to work around a potential security problem which could break some previously working scripts.
Starting at this version, GM "double-checks" the call stack of all calls into potentially unsafe Greasemonkey APIs to make sure that every frame on the stack is either from a user script, or from the browser DOM. The APIs that currently have this check are:
* GM_xmlhttpRequest * GM_getValue * GM_setValue * GM_getResourceURL (new in 0.8) * GM_getResourceText (new in 0.8)
This means that you cannot register a callback with content-defined JavaScript and call one of these GM APIs from that callback. Code like below will not work:
unsafeWindow.someObject.registerCallback(function() {
GM_setValue("foo", "bar");
});
or
unsafeWindow.someAPIfunction = function() {
GM_setValue("foo", "bar");
};
Here is a workaround for this limitation:
unsafeWindow.someObject.registerCallback(function() {
window.setTimeout(function() {
GM_setValue("foo", "bar");
}, 0);
});
and
unsafeWindow.someAPIfunction = function() {
window.setTimeout(GM_setValue, 0, "foo", "bar");
};
or, if you have a lot of them, perhaps this:
function safeWrap(f) {
return function() {
setTimeout.apply(window, [f, 0].concat([].slice.call(arguments)));
};
}
unsafeWindow.someAPIfunction = wrap(function() {
GM_setValue("foo", "bar");
});
Take care with untrusted input when using this workaround. Remember that since someObject is a property of unsafeWindow it might not contain the code you expect it to. For example, the below is not safe because it blindly requests a URL that originated in unsafeWindow.
unsafeWindow.someObject.registerCallback(function(url) {
window.setTimeout(function() {
GM_xmlhttpRequest({
method: "GET",
url: url
});
}, 0);
});
Here is a safer version:
unsafeWindow.someObject.registerCallback(function(asin) {
window.setTimeout(function() {
GM_xmlhttpRequest({
method: "GET",
url: "http://www.amazon.com/asin/" + asin;
});
}, 0);
});
In this example, you know that your user script can only ever be used to make requests to amazon.com.

