I need to call a cross domain GM_xmlhttpRequest
which would be triggered by an event in the webpage.
How do I access the functions within the greasemonkey sandbox, from the webpage?
I need to call a cross domain GM_xmlhttpRequest
which would be triggered by an event in the webpage.
How do I access the functions within the greasemonkey sandbox, from the webpage?
To allow pages to use GM_xmlhttpRequest
, you have to:
unsafeWindow.XMLHttpRequest
with a custom method.setInterval
.I have previously written such an User script for personal use, at the local protocol. Do not abuse it, and create very strict matching patterns to prevent exposing cross-site XHR to arbitrary websites.
The code does the following:
XMLHttpRequest
object to unsafeWindow.GM_XHR.original
.GM_XHR.restore()
.XMLHttpRequest
object is overwritten by a custom method, which adds any requests to an array queue.// ==UserScript==
// @name Cross-site XMLHttpRequest
// @namespace Rob W
// @description Enables cross-site XHR
// @include file:///home/*
// ==/UserScript==
/*
* http://www.w3.org/TR/XMLHttpRequest
* http://wiki.greasespot.net/GM_xmlhttpRequest
* https://developer.mozilla.org/en/XMLHttpRequest
*
* https://developer.mozilla.org/En/nsIDOMProgressEvent
* https://developer.mozilla.org/en/nsIChannel
*/
// Configuration. Allow paths via a RegExp:
var enabled = [
"^file:///home/rob/Documenten/etc/",
"^file:///home/rob/Documenten/test\.html$"
];
var XHR = {
allowed: new RegExp(enabled.join("|")),
allowed_atm: function(url){
return XHR.allowed.test(url || location.protocol + "//" + location.pathname)
},
original: unsafeWindow.XMLHttpRequest,
restore: function(){
unsafeWindow.XMLHttpRequest = XHR.original;
}
};
if (XHR.allowed_atm()) {
// Request queue
var reqs = [];
// Inititate the actual gm_xmlhttpRequest.
// Also define the `.abort()` method
var do_xmlHttpRequest = function(details) {
details.abort = GM_xmlhttpRequest(details).abort;
}
// Set poller, used to circumvent the security policy
window.setInterval(function(){
while(reqs.length) {
do_xmlHttpRequest(reqs.shift());
}
}, 50);
// unsafeWindow.XMLHttpRequest will be overwritten by:
var xmlhttprequest = function() {
var o = {headers: {}},
t = this,
sent = false,
currentHeaders = "";
t.channel = {
name: ""
};
o.onprogress = function(r){
if(r.lengthComputable) {
t.channel.contentLength = r.total;
currentHeaders = "Content-Length: " + r.total;
}
t.status = r.status;
t.statusText = r.statusText;
t.channel.name = r.finalUrl;
};
t.abort = function() {
if(typeof o.abort == "function") o.abort();
else t.onreadystatechange = null;
sent = false;
};
t.getAllResponseHeaders = function() {
return t.responseHeaders ? t.responseHeaders + (/(^|\n)Content-Length:\s?\d/i.test(t.responseHeaders)?"":"\n" + currentHeaders) : currentHeaders;
};
t.getResponseHeader = function(header) {
console_log("Method not supported. getResponseHeader: " + header);
return "";
};
t.open = function(method, url, async, user, password) {
o.method = method;
o.url = url;
t.channel.name = url; //finalUrl?
//o.synchronous = !async; //Not implemented for safety reasons
if (typeof user != "undefined") o.user = user;
if (typeof password != "undefined") o.password = password;
};
t.overrideMimeType = function(mimetype) {
o.overrideMimeType = mimetype;
};
t.send = function(data){
var readyState4reached = false;
if (typeof t.onabort == "function") r.onabort = t.onabort;
if (typeof t.onerror == "function") r.onerror = t.onerror;
o.onload = function(r){
o.onreadystatechange(r);
if (typeof t.onload == "function") t.onload();
};
o.data = data;
o.onreadystatechange = function(r) {
t.channel.name = r.finalUrl;
if (t.responseHeaders = r.responseHeaders) {
var tmp;
if(tmp = t.responseHeaders.match(/Content-Length:\s?(\d+)/i)) {
t.channel.contentLength = tmp[1];
}
}
t.readyState = r.readyState;
t.responseText = r.responseText;
t.status = r.status;
t.statusText = r.statusText;
if(readyState4reached) return;
if(!readyState4reached && t.readyState == 4) readyState4reached = true;
typeof t.onreadystatechange == "function" && t.onreadystatechange();
}
if(!sent) reqs.push(o);
sent = true;
};
t.setRequestHeader = function(name, value) {
o.headers[name] = value;
};
}
/* Event binding */
unsafeWindow.XMLHttpRequest = xmlhttprequest;
unsafeWindow.GM_XHR = {original: XHR.original, restore: XHR.restore};
// Log the exposed method in the console, to not forget about it:
console.log("GM cross-site XHR activated at: " + location.href);
};