GM_xmlhttpRequest
我需要调用一个由网页中的事件触发的跨域。
如何从网页访问greasemonkey 沙箱中的功能?
GM_xmlhttpRequest
我需要调用一个由网页中的事件触发的跨域。
如何从网页访问greasemonkey 沙箱中的功能?
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);
};