Leonardo Daga
Leonardo Daga

Reputation: 145

WebBrowser to Gecko: Injecting javascripts

I'm trying to port my application that was using the WebBrowser control to Gecko. The only thing I can't manage is the javascript injection to access the global variables of the page just downloaded. If the javascript, for example, is:

function get_players()
{
    strout = "no data";
    try
    {
        if (players_ar == null) 
            return "Javascript error: players_ar is null";
        else
            return players_ar[0]["fp"];
    }
    catch (err)
    {
        strout += ";Javascript error = " + err;
    }

    return strout;
}

players_ar is a variable (an array) that is global in the page that I just loaded in the browser. Saving the text of the script in the variable function_text and calling the script as follows with a WebBrowser:

HtmlElement head = webBrowser.Document.GetElementsByTagName("head")[0];
HtmlElement scriptEl = webBrowser.Document.CreateElement("script");
IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement;
element.text = function_text;
HtmlElement res = head.AppendChild(scriptEl);
pl_data = (string)webBrowser.Document.InvokeScript("get_players");

I successfully returned the value of that element of players_ar. Doing the same with Gecko, was not successful:

GeckoHtmlElement head = webBrowser.Document.GetElementsByTagName("head")[0];
GeckoElement scriptEl = webBrowser.Document.CreateElement("script");

nsIDOMHTMLScriptElement element = (Gecko.nsIDOMHTMLScriptElement)scriptEl.DOMElement;
element.SetTextAttribute(new nsAString(Resources.players_loader));
GeckoNode res = head.AppendChild(scriptEl);

using (var java = new AutoJSContext(GlobalJSContextHolder.BackstageJSContext))
{
    string result;
    const string javascript =
        @"
        function get_players()
        {
            strout = 'no data';
            try
            {
                if (players_ar == null)
                    return 'Javascript error: players_ar is null';
                else
                    return players_ar[0]['fp'];
            }
            catch (err)
            {
                strout += ';Javascript error = ' + err;
            }

            return strout;
        }
        get_players();
        ";

    if (java.EvaluateScript(javascript, (nsISupports)webBrowser.Document.DomObject, out result))
    {
        MessageBox.Show(String.Format("javascript returned '{0}'", result));
    }
}

In this case the returned value is: "no data;Javascript error = ReferenceError: players_ar is not defined", that means that it blocks in the check if player_ar is null because the variable is not declared at all.

I wonder is the behaviour of Gecko is different respect to IE, maybe the first browser doesn't hold the variable environment once loaded the page. Please help, I ran out of ideas.

Upvotes: 0

Views: 2749

Answers (1)

Leonardo Daga
Leonardo Daga

Reputation: 145

After a week of attempts, it turned out that I was using the wrong function. It's still EvaluateScript, but I don't know why this prototype works while the other doesn't work. I asked directly to the geckofx guys and to help the other people facing the same problem, I post their reply (thanks to Andrey Filippov). The code for this is the following (it actually works, so it has been tested also):

const string function_text =
    @"
        function get_players()
        {
            strout = 'no data';
            try
            {
                strout += ';clubname = ' + this.screenX;

                if (players_ar == null)
                    return 'Javascript error: players_ar is null';
                else
                    return players_ar[0]['fp'];
            }
            catch (err)
            {
                strout += ';Javascript error = ' + err;
            }

            return strout;
        }                    
        ";

GeckoElement scriptEl = webBrowser.Document.CreateElement("script");

scriptEl.TextContent = function_text;
GeckoNode res = webBrowser.Document.Head.AppendChild(scriptEl);

using (var java = new AutoJSContext(webBrowser.Window.JSContext))
{
    JsVal result = java.EvaluateScript("get_players()", webBrowser.Window.DomWindow);
    MessageBox.Show(result.ToString());
}

Upvotes: 3

Related Questions