In short instead of alerting URLs and the response body I'd like to send it to my app. This code works but I can not use GM_xmlhttpRequest unless I grant it.
Changing nothing else the code magically breaks. I'm unsure what is changed and how to fix it. I thought I could use console.log
and copy/paste the data into my app however Facebook disables console.log.
I thought about doing xmlhttpRequest but that too is somehow blocked. I tested by executing code in a console. The 3 lines seem to work everywhere except on a Facebook domain. I believe it has something to do with CORS.
// ==UserScript==
// @name FBTest
// @namespace test
// @include https://*.facebook.com/*
// @version 1
// @grant none
// ==/UserScript==
//change none to GM_xmlhttpRequest
(function() {
var proxied = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function(method, url) {
alert(url);
return proxied.apply(this, [].slice.call(arguments));
};
})();
When you grant GM_xmlhttpRequest, it switches on the sandbox -- which means that you cannot access window.XMLHttpRequest
like that as it is in a different context now.
To work around this, use script injection to intercept the AJAX. And, use either messaging or a custom event to access the data in your userscript's context.
Here's an example script using a custom event (less vulnerable to 3rd-party exploits):
// ==UserScript==
// @name _Intercept AJAX with grant/sandbox on
// @match https://*.facebook.com/*
// @grant GM_xmlhttpRequest
// ==/UserScript==
function xmlOpenIntercept () {
var proxied = window.XMLHttpRequest.prototype.open;
window.XMLHttpRequest.prototype.open = function (method, newUrl) {
var cEvnt = new CustomEvent ('newAjaxStart', {'detail': newUrl} );
document.body.dispatchEvent (cEvnt);
return proxied.apply (this, [].slice.call (arguments) );
};
}
addJS_Node (null, null, xmlOpenIntercept); //-- Injects code
//--- This code listens for the right kind of message.
document.body.addEventListener ("newAjaxStart", receiveAjaxMessage);
function receiveAjaxMessage (zEvent) {
console.log ("Intercepted AJAX to: ", zEvent.detail);
}
function addJS_Node (text, s_URL, funcToRun, runOnLoad) {
var D = document;
var scriptNode = D.createElement ('script');
if (runOnLoad) scriptNode.addEventListener ("load", runOnLoad);
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
if (funcToRun) scriptNode.textContent = '(' + funcToRun.toString() + ')()';
var targ = D.getElementsByTagName ('head')[0] || D.body || D.documentElement;
targ.appendChild (scriptNode);
}