cordova-plugin-inappbrowserxwalk icon indicating copy to clipboard operation
cordova-plugin-inappbrowserxwalk copied to clipboard

Feature Request: executeScript

Open stephio opened this issue 9 years ago • 7 comments

Maybe I'm asking too much, and this is my second feature request, but this would really match with the regular Cordova WebView.

So if you have the time to implement the executeScript feature it would be really perfect.

Code snippet to explain: var ref = window.inAppBrowserXwalk.open(playerPath); ref.addEventListener('loadstop', function (event) { var loop = setInterval(function () { ref.executeScript( { code: "getShouldExit()" //being a javascript function inside the XWalk view }, function (values) { var name = values[0]; if (name) { clearInterval(loop); ref.close(); } } ); }); });

Thank you!

stephio avatar Sep 02 '15 10:09 stephio

Hi, I'm working on the implementation of executeScript function based on the inAppBrowser plugin.

I add the JS code and the Java code. Everything work well to send data to the page loaded, but I can't get my callback called.

xWalkWebView.evaluateJavascript(finalScriptToInject, null); this already exist and work well.

jsWrapper = String.format("prompt(JSON.stringify([eval(%%s)]), 'gap-iab://%s')", callbackContext.getCallbackId()); this is the callback implementation in InAppBrowser and it's called to with xWalkWebView but this show me a prompt with the right return value but don't call the callback function. I don't know how to get it work.

If you have any idea we can work on it together.

Regards.

macarron avatar Sep 16 '15 18:09 macarron

I was working on that too and i am also not able to to get the return value of the evaluateJavascript function through callback...

ClaasBrueggemann avatar Sep 16 '15 18:09 ClaasBrueggemann

public void executeScript(final String code) {
        if(xWalkWebView != null) {
            this.cordova.getActivity().runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    xWalkWebView.evaluateJavascript(code, new android.webkit.ValueCallback<String>() {
                        @Override
                        public void onReceiveValue(String scriptResult) {
                            try {
                                JSONObject obj = new JSONObject();
                                obj.put("type", "executeScriptResult");
                                obj.put("result", scriptResult);
                                PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
                                result.setKeepCallback(true);
                                callbackContext.sendPluginResult(result);
                            }
                            catch (Exception e) {}
                        }
                    });
                }
            });
        }
    }

The problem is, that onReceiveValue doesnt get called and i could not figure out why yet.

ClaasBrueggemann avatar Sep 16 '15 18:09 ClaasBrueggemann

Ok i've got it work based on your work, but I don't know how to paste my code

macarron avatar Sep 16 '15 20:09 macarron

in my website

var APP = {
    test:function()
    {
        return {success:"", data:"test"};
    }
}

in index.js

var browser = window.inAppBrowserXwalk.open("url");
        browser.addEventListener("loadstop", loaded);

        function loaded()
        {
            console.log("browser loaded");

            browser.addEventListener("jsCallback", callback);
            browser.executeScript("APP.test();");

            function callback(result)
            {
                console.log("callback : " + result);
            }
        }

in inappbrowserxwalk.js

InAppBrowserXwalk.prototype = {
    close: function () {
        cordova.exec(null, null, "InAppBrowserXwalk", "close", []);
    },
    addEventListener: function (eventname, func) {
        callbacks[eventname] = func;
    },
    removeEventListener: function (eventname) {
        callbacks[eventname] = undefined;
    },
    show: function () {
        cordova.exec(null, null, "InAppBrowserXwalk", "show", []);
    },
    hide: function () {
        cordova.exec(null, null, "InAppBrowserXwalk", "hide", []);
    },

    executeScript: function(injectDetails) {
        cordova.exec(null, null, "InAppBrowserXwalk", "injectScriptCode", [injectDetails]);
    }
}

var callback = function(event) {
    if (event.type === "loadstart" && callbacks['loadstart'] !== undefined) {
        callbacks['loadstart'](event.url);
    }
    if (event.type === "loadstop" && callbacks['loadstop'] !== undefined) {
        callbacks['loadstop'](event.url);
    }
    if (event.type === "exit" && callbacks['exit'] !== undefined) {
        callbacks['exit']();
    }
    if (event.type === "jsCallback" && callbacks['jsCallback'] !== undefined) {
        callbacks['jsCallback'](event.result);
    }
}

in inappbrowserxwalk.java function execute just add this

if (action.equals("injectScriptCode")) {
            this.injectJS(data.getString(0));
        }

and the injectJS function

public void injectJS(String source) {

        final String finalScriptToInject = source;
        this.cordova.getActivity().runOnUiThread(new Runnable() {

            @Override
            public void run() {

                xWalkWebView.evaluateJavascript(finalScriptToInject, new ValueCallback<String>() {
                    @Override
                    public void onReceiveValue(String scriptResult) {
                        try {
                            JSONObject obj = new JSONObject();
                            obj.put("type", "jsCallback");
                            obj.put("result", scriptResult);
                            PluginResult result = new PluginResult(PluginResult.Status.OK, obj);
                            result.setKeepCallback(true);
                            callbackContext.sendPluginResult(result);
                        } catch (JSONException ex) {}
                    }
                });
            }
        });
    }

macarron avatar Sep 16 '15 20:09 macarron

can you create a pull request pls?

ClaasBrueggemann avatar Sep 17 '15 12:09 ClaasBrueggemann

I tried the code suggested above and it failed because of missing import statement in InAppBrowserXwalk.java:

import android.webkit.ValueCallback;

After adding it, the build went fine, but then another issue appeared - when return value of evaluated JavaScript was an object (I tried to get localStorage by 'window.localStorage;' statement), the result turned out to be null. I'm not a Java expert, but it seems to me that ValueCallback<String> accepts only string values and for some reason conversion from Storage object was not correct;

xWalkWebView.evaluateJavascript(finalScriptToInject, new ValueCallback<String>() {

Then I tried 'JSON.stringify(window.localStorage);' instead and got my localStorage stringified twice. That is better than nothing, and I'm currently have no time to investigate further, so for now this would be enough:

let results = JSON.parse(JSON.parse(data));

The traditional inAppBrowser has no such an issue.

My fork with those changes and build fix: https://github.com/EternallLight/cordova-plugin-inappbrowserxwalk

EternallLight avatar Feb 17 '17 11:02 EternallLight