Take the 2-minute tour ×

This code works fine in Chrome. However, in Firefox, when it hits the GMxhr request, it simply stops. It gets right up to the GMxhr call, then just... stops. I've checked everything I can think of, making sure that the responseType param is only set for chrome, etc... yet still nothing. Any ideas?

var body       = document.getElementsByTagName('body')[0]
  , messageDiv = document.createElement('div')

messageDiv.id = 'xhrComlink';

function getUri(e) {
'use strict';
var chrome = navigator.userAgent.toString().toLowerCase().indexOf('chrome') !== -1;

var bin2base64 = function bin2base64 (binary) {

var storeRetrievedFile = function storeRetrievedFile(response) {
    var thisComlink = e.target
      , evt         = document.createEvent("MouseEvents")

    var text = response.responseText
      , len  = text.length
      , arr  = new Uint8Array(len)
      , i    = 0

    if (!chrome) {
            arr[i] = text.charCodeAt(i) & 0xFF;

    thisComlink.innerHTML = '';
            chrome ? bin2base64(response.responseText) : bin2base64(arr.buffer)


var gmXOptions = { method           : 'GET'
                 , overrideMimeType : 'text/plain; charset=x-user-defined'
                 , onload           : storeRetrievedFile
                 , url              : e.target.innerHTML

chrome && (gmXOptions.responseType = 'arraybuffer');



In the console, I get only "1" on Firefox. In Chrome, I get "1", "2", it rewrites the innerHTML, fires the event, and off we go.

I have also checked to make sure that Firefox has everything correct, with a dir of the gmXOptions at the same spot as the log(1) call:


method  "GET"
overrideMimeType    "text/plain; charset=x-user-defined"
url     "http://www.home...e-and-land-packages.jpg"
onload      storeRetrievedFile(response)

EDIT to explain the answer; maybe this'll help someone else in the future:

Firefox's GM has an annoying behaviour/bug:

1) Write a userscript which attaches an event listener. In that event listener function, such as getUri() above, use a GM_ function.

2) Now invoke that event's trigger from any other javascript context except for the one which just created the listener. For example, use the common Chrome-friendly "inject jquery, callback to main(), continue" pattern.

3) But doing that, you lose access to GM functions in main(). So you have to put them right at the start of the script, outside of main(), before you inject jQuery, then "communicate" between those GM-using (a GM context) functions and the functions in main (an injected, non-GM context), in this case w/events.

Result) In GM terms, unsafeWindow is calling GM_xmlhttpRequest. That triggers the "security" in Firefox Greasemonkey, and it silently blocks the call to GM_xmlhttpRequest. You have to use the workaround to get the stack "cleaned up" enough to make Firefox GM's "security" happy. Then it will call the GM_xmlhttpRequest.

share|improve this question
" However, in Chrome, when it hits the GMxhr request, it simply stops." Do you mean Firefox, as in the title? –  Yi Jiang Jun 13 '12 at 2:59
Yes, sorry - I've fixed the question. :) –  BrianFreud Jun 13 '12 at 4:07
add comment

1 Answer

up vote 1 down vote accepted

I finally found the problem, though Firefox Greasemonkey makes it REALLY hard to find, and for whatever reason, it wasn't throwing any error/warning/etc messages at all, which might have helped solve this faster.

Anyhow, this was the problem: http://wiki.greasespot.net/0.7.20080121.0_compatibility


 setTimeout(function() {


}, 0);

around the GM_xhr call, and all now works as it should.

share|improve this answer
That note does not apply unless you are trying to inject your code into the page -- something that is NOT shown in the question. The question code is (still) inaccurate and/or you fixed the problem coincidentally while adding the timeout. –  Brock Adams Jun 13 '12 at 23:48
Actually, it is shown in the question - a userscript by definition is injected into the page. GM_xmlhttpRequest does not exist outside of a userscript context. –  BrianFreud Jun 14 '12 at 12:10
No, a userscript is not injected, it operates in a sandbox, unless you explicitly inject it -- which you do not show in the question. That note does not apply to your question as posted. –  Brock Adams Jun 14 '12 at 12:20
A userscript is injected into a page, sandbox or no. If it weren't, it wouldn't exist anywhere. :P ref[1] O'Reilly: "Greasemonkey injects user scripts into a page", commons.oreilly.com/wiki/index.php/Greasemonkey_Hacks/… ref[2] Google: "Greasemonkey scripts are injected by default at a new point called "document-idle". This is different than Greasemonkey, which always injects at document-end." chromium.org/developers/design-documents/user-scripts ref[3,4]: GM wiki.greasespot.net/Security and wiki.greasespot.net/Version_history –  BrianFreud Jun 14 '12 at 12:38
add comment

Your Answer


