Intercept XMLHttpRequest from Greasemonkey script fails
Next, I gave unsafeWindow a try. It should not be needed. My userscript runs with @grant none and documentation (see here) says my script should run in the content scope.
This is wrong for Greasemonkey 4 as stated in its announcement:
Due to the more limited abilities that the new extension system gives us, we are currently unable to make @grant none scripts work in the same way. Most importantly, they have a different connection to unsafeWindow. For the short term at least, it's a good idea to adopt cloneInto and exportFunction.
See also this other question Firefox doesn't respect Object.defineProperty() from a Greasemonkey script?
This change explain the observations, but no idea why adding listener to window work.
Intercepting XMLHttpRequest in Greasemonkey while using @grant the right way
The solution depends on how you want to do interact. You could inject all the logic into the site's scope, however, there is a barrier between userscript's scope and site's scope if you want to interact. It is not trivial to exchange data between both scopes. unsafeWindow
is evil, avoid usage. Inject the logic as string to be evaluatet inside a setTimeout(String)
, so that it is executed in site's scope. If you need to interact with the userscript in privileged scope, setup a messaging system with window.dispatchEvent(new CustomEvent('eventname', {'detail': scalarData}));
. You won't be able to transfer complex datatype declared in a scope with other privileges.
capture a pages xmlhttp requests with a userscript
Since the page uses $.get()
, it's even easier to intercept requests. Use ajaxSuccess()
.
This will work in a Greasemonkey(Firefox) script:
Snippet 1:
unsafeWindow.$('body').ajaxSuccess (
function (event, requestData)
{
console.log (requestData.responseText);
}
);
Assuming the page uses jQuery in the normal way ($
is defined, etc.).
This should work in a Chrome userscript (as well as Greasemonkey):
Snippet 2:
function interceptAjax () {
$('body').ajaxSuccess (
function (event, requestData)
{
console.log (requestData.responseText);
}
);
}
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
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);
}
addJS_Node (null, null, interceptAjax);
Re:
"But how then do I get that data to the script? ... (So I can) use the data later in the script."
This works in Greasemonkey(Firefox); it might also work in Chrome's Tampermonkey:
Snippet 3:
function myAjaxHandler (requestData) {
console.log ('myAjaxHandler: ', requestData.responseText);
}
unsafeWindow.$('body').ajaxSuccess (
function (event, requestData) {
myAjaxHandler (requestData);
}
);
But, if it doesn't then you cannot share JS information (easily) between a Chrome userscript and the target page -- by design.
Typically what you do is inject your entire userscript, so that everything runs in the page scope. Like so:
Snippet 4:
function scriptWrapper () {
//--- Intercept Ajax
$('body').ajaxSuccess (
function (event, requestData) {
doStuffWithAjax (requestData);
}
);
function doStuffWithAjax (requestData) {
console.log ('doStuffWithAjax: ', requestData.responseText);
}
//--- DO YOUR OTHER STUFF HERE.
console.log ('Doing stuff outside Ajax.');
}
function addJS_Node (text, s_URL, funcToRun) {
var D = document;
var scriptNode = D.createElement ('script');
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);
}
addJS_Node (null, null, scriptWrapper);
Related Topics
Compare JavaScript Array of Objects to Get Min/Max
How Does a Function in a Loop (Which Returns Another Function) Work
The .Replace() Method Does Change the String in Place
Ruby with Watir: Handling JavaScript Popup Window
Switch on Ranges of Integers in JavaScript
How to Pause Setinterval() Functions
What's the Difference Between Returning Value or Promise.Resolve from Then()
Vue.Js - How to Properly Watch for Nested Data
Jquery: Load Txt File and Insert into Div
Cannot Set Boolean Values in Localstorage
Get Column from a Two Dimensional Array
Push Is Overwriting Previous Data in Array
How to Use Componentwillmount() in React Hooks
How to Get an Ajax Get-Request to Wait for the Page to Be Rendered Before Returning a Response
How to Access Constants in the Lib/Constants.Js File in Meteor