I use Selenium to test a web application, and I am not allowed to modify the javascript code of the application. I am trying to track the number of outstanding AJAX requests using GreaseMonkey to override XMLHttpRequest.send. The new send () function will basically wrap what was set as the onreadystatechange callback, check for readiness, increment or decrement the counter, if necessary, and call the callback function.
The problem I am facing is a privilege problem, because if I just go to the page in a regular Firefox browser, open firebug and paste the following code, it seems to work fine:
document.ajax_outstanding = 0; if (typeof XMLHttpRequest.prototype.oldsend != 'function') { XMLHttpRequest.prototype.oldsend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function() { console.log('in new send'); console.log('this.onreadystatechange = ' + this.onreadystatechange); this.oldonreadystatechange = this.onreadystatechange; this.onreadystatechange = function() { if (this.readyState == 2) { document.ajax_outstanding++; console.log('set ajax_outstanding to ' + document.ajax_outstanding); } this.oldonreadystatechange.handleEvent.apply(this, arguments); if (this.readyState == 4) { document.ajax_outstanding--; console.log('set ajax_outstanding to ' + document.ajax_outstanding); } }; this.oldsend.apply(this, arguments); }; }
Now, if I use a slightly modified version of this snippet from a GreaseMonkey user script as follows:
unsafeWindow.document.ajax_outstanding = 0; if (typeof unsafeWindow.XMLHttpRequest.prototype.oldsend != 'function') { unsafeWindow.XMLHttpRequest.prototype.oldsend = unsafeWindow.XMLHttpRequest.prototype.send; unsafeWindow.XMLHttpRequest.prototype.send = function() { GM_log('in new send'); GM_log('this.onreadystatechange = ' + this.onreadystatechange); this.oldonreadystatechange = this.onreadystatechange; this.onreadystatechange = function() { if (this.readyState == 2) { unsafeWindow.document.ajax_outstanding++; GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); } this.oldonreadystatechange.handleEvent.apply(this, arguments); if (this.readyState == 4) { unsafeWindow.document.ajax_outstanding--; GM_log('set ajax_outstanding to ' + unsafeWindow.document.ajax_outstanding); } }; this.oldsend.apply(this, arguments); }; }
and I go to the page, do something that triggers the AJAX request, I get the following message in the javascript error console:
http://www.blah.com/gmscripts/overrides: in new send uncaught exception: [Exception... "Illegal value" nsresult: "0x80070057 (NS_ERROR_ILLEGAL_VALUE)" location: "JS frame :: file:///tmp/customProfileDir41e7266f56734c97a2ca02b1f7f528e1/extensions/%7Be4a8a97b-f2ed-450b-b12d-ee082ba24781%7D/components/greasemonkey.js :: anonymous :: line 372" data: no]
So this seems to throw an exception when trying to access this.onreadystatechange
Presumably, this is due to an isolated environment. Any help would be greatly appreciated. I am not attached to this decision, so any other suggestions in order to do what I need are welcome. It is just that I tried several others, and it seems the most promising. The requirement is that I need to make sure that the counter reaches 0 after the ReadyState goes to 4 and the onreadystatechange callback completes the execution.