views:

233

answers:

1

Update

The root cause appears to be a bug in Greasemonkey. Essentially, GM would start running in the main document space (window.self == window.top), but never finish!

Instead, GM would switch over to an iframe, on the select Google pages, and finish there. This does not seem to be 2 instances of GM, otherwise there would be no problem. After the iframe switch, the GM instance still sees the same state of global variables that were set before the switch. But any attempts to alter those globals (needed for state control) results in a silent GM-instance crash.

Furthermore, Google has, for now, changed their pages, so I can no longer duplicate the problem or test my workaround. I have a to-do item to generate my own trigger page but that is now very low priority.
.

Original Post

Hi, I have a Greasemonkey script that processes Google search results. But it's failing in a few instances, when xpath searches (and document body) appear to be empty.

Running the code in Firebug's console works every time. It only fails in a Greasemonkey script. Greasemonkey sees an empty document.body.

I've boiled the problem down to a test, greasemonkey script, below.
I'm using Firefox 3.5.9 and Greasemonkey 0.8.20100408.6 (but earlier versions had the same problem).

Problem:

Greasemonkey sees an empty document.body.

Recipe to Duplicate:

  1. Install the Greasemonkey script.
  2. Open a new tab or window.
  3. Navigate to Google.com (http://www.google.com/).
  4. Search on a simple term like "cats".
  5. Check Firefox's Error console (Ctrl-shift-J) or Firebug's console. The script will report that document body is empty.
  6. Hit refresh. The script will show a good result (document body found).
  7. Note that the failure only reliably appears on Google results obtained this way, and on a new tab/window.
  8. Turn javascript off globally (javascript.enabled set to false in about:config).
  9. Repeat steps 2 thru 5. Only now the Greasemonkey script will work.

It seems that Google javascript is killing the DOM tree for greasemonkey, somehow. I've tried a time-delayed retest and even a programmatic refresh; the script still fails to see the document body.

Test Script:

//
// ==UserScript==
// @name            TROUBLESHOOTING 2 snippets
// @namespace       http://www.google.com/
// @description     For code that has funky misfires and defies standard debugging.
// @include         http://*/*
// ==/UserScript==
//


function LocalMain (sTitle)
{
    var sUserMessage    = '';
  //var sRawHtml        = unsafeWindow.document.body.innerHTML; //-- unsafeWindow makes no difference.
    var sRawHtml        = document.body.innerHTML;
    if (sRawHtml)
    {
        sRawHtml        = sRawHtml.replace (/^\s\s*/, ''). substr (0, 60);
        sUserMessage    = sTitle + ', Doc body = ' + sRawHtml + ' ...';
    }
    else
    {
        sUserMessage    = sTitle + ', Document body seems empty!';
    }


    if (typeof (console) != "undefined")
    {
        console.log  (sUserMessage);
    }
    else
    {
        if (typeof (GM_log) != "undefined")
            GM_log (sUserMessage);
        else
            if (!sRawHtml)
                alert (sUserMessage);
    }
}


LocalMain ('Preload');

window.addEventListener ("load", function() {LocalMain ('After load');}, false);
+1  A: 

I get the following in my firebug console when I follow your steps:

Preload, Doc body = <textarea id="csi" style="display: none;"></textarea><script ...

After load, Doc body = <textarea id="csi" style="display: none;"></textarea><script ...

Preload, Document body seems empty!

After load, Document body seems empty!

The last two lines, which you are asking about I believe, occur because an empty iframe is added to the page.

Erik Vold
So document.body (and also XPATH) are seeing that iframe instead of the main document? I'll investigate that notion; don't iframe's appear under/in the body, normally? Anyway, if the script is seeing an iframe, any idea how to access the real body? (I'll start playing with parentNode.)
Brock Adams
Let me say this another way, the iframe is added, and iframe is a page, so your userscript is loaded for the page that is loaded in the iframe. The page in the iframe has a body tag, but nothing inside of it. So there are two instances of your userscript running on the page at this point, one for the top page, and the second for the iframe within the body of the top page.
Erik Vold
That's close to what I thought you meant, and I am investigating that possibility -- so far, with confusing results.There's a lot of weird stuff going on, for example I (my GM script) can see that there is an iframe, but it appears empty too. However, as soon as a google script is fired (like by typing a character in the search input), suddenly the GM script sees the whole DOM! (I had set dom-change event-handlers.)I also have one report that the script works fine on non-windows Firefox editions. I'm wondering if this might be a FF and/or GM bug. But, even if it is, I need a workaround.
Brock Adams
While I'm not satisfied with this answer, it was at least on the right track. Thanks for your help!
Brock Adams