Webview html to host communication in Nashorn - javascript

I am trying to wrap my head around establishing communication between an HTML page in a webview in Nashorn and the host nashorn application. I read this tutorial
here
but I can't seem to get how to create a callback which I can call inside the HTML page to run something in the host. The wrapping function works fine I just don't know where to go from here to get webview html to host communication. No matter how I do it, I get an empty object but no methods.
This.engine.loadWorker.stateProperty().addListener(new ChangeListener() {
changed: function(value, oldState, newState) {
if (newState == Worker.State.SUCCEEDED) {
function testObj(){
this.foo = function(){
print('hello');
}
}
This.document = wrap(This.engine.executeScript("document"));
This.window = wrap(This.engine.executeScript("window"));
I tried
This.window.setMember('HOST',new testObj());
and
This.window.setMember('HOST',wrap(new testObj()));
Both get me nothing in the window
This.window.executeScript("window").setMember('HOST',new testObj());
Gets me an empty object in the HTML page javascript "{}"

Related

Android Calling JavaScript functions in Button

I've an Android Activity and I've got a Button that button need to access some Javascript function. Simply my app get the user info(ID,pass) then go to web page(this operation doing backgrun with asynctask class) write these two info as ID and pass then user click the Log In button in my app button has to use some js function
<script type="text/javascript">
//<![CDATA[
var theForm = document.forms['form1'];
if (!theForm) {
theForm = document.form1;
}
function __doPostBack(eventTarget, eventArgument) {
if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
theForm.__EVENTTARGET.value = eventTarget;
theForm.__EVENTARGUMENT.value = eventArgument;
theForm.submit();
}
}
//]]>
</script>
this is the func. i need to use
My post and get request for connection the site are
POST//
URL url = new URL(params[0]); //http://login.cu.edu.tr/Login.aspx? site=https://derskayit.cu.edu.tr&ReturnUrl=%2f
connection=(HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
writer.write(data);
writer.flush();
these codes for the put the ID and pass
GET //
reader= new BufferedReader((new InputStreamReader(connection.getInputStream())));
StringBuilder builder = new StringBuilder();
String line;
while((line= reader.readLine())!=null){
builder.append(line + "\n");
}
text=builder.toString();
there is any help or suggestion for me i am very confused about that situation and i feel really bad myself thanks for helps anyway. Have a nice day
For using Javascript without a webView to make requests!
The question has already an answer here in this question
The javax.script package is not part of the Android SDK. You can execute JavaScript in a WebView, as described here. You perhaps can use Rhino, as described here. You might also take a look at the Scripting Layer for Android project.
Also a similar question was asked here
You can execute JavaScript without a WebView. You can use AndroidJSCore. Here is a quick example how you might do it:
HttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet("http://your_website_here/file.js");
HttpResponse response = client.execute(request);
String js = EntityUtils.toString(response.getEntity());
JSContext context = new JSContext();
context.evaluateScript(js);
context.evaluateScript("question.vote(0);");
However, this most likely won't work outside of a WebView, because I presume you are not only relying on JavaScript, but AJAX, which is not part of pure JavaScript. It requires a browser implementation.
Is there a reason you don't use a hidden WebView and simply inject your code?
// Create a WebView and load a page that includes your JS file
webView.evaluateJavascript("question.vote(0);", null);
Otherwise:
Yes you can make HTTP POST and HTTP GET requests without using WebView. But if you want to use a webView remember Javascript in a webview is disabled by default (for security purposes). So before calling any javascript functions make sure you enable javascript in your webview like this
webView.getSettings().setJavaScriptEnabled( true );
And after that javascript will be enabled in your webView.
But in case you do not want to use a webview and javascript to make http requests. There is a lot of alternative methods you can define a Button in your activity's layout in xml. And respond with a http request on button Clicked listener!
Also remember making http Request using Android/Java default classes is a huge task and error prone and requires you to care about using async tasks to avoid blocking the UI thread.
Alternatively
In android we use ready-made library to make http requests. Google has a good library called Volley. it is easy to customize,respond to errors and it automatically making request out of the main thread.See more explanation here!. If there is still some problems comment below!

How to communicate with a webpage via browser plugin

How can I communicate from a JavaScript code of a webpage to the main code of the add-on?
For example, something like this: If some element is clicked, in the corresponding event handler of the page script, which is the syntax that can be used to send some message to the main code?
Specifically, something like this, where the frame now must be replaced by a generic webpage. Is it possible?
Edit: I have tried the suggested code, but how I had said, the application returns this error:
console.error: sherlock:
Message: ReferenceError: document is not defined
Stack:
A coding exception was thrown in a Promise resolution callback.
See https://developer.mozilla.org/Mozilla/JavaScript_code_modules/Promise.jsm/Promise
Full message: ReferenceError: document is not defined
Previously my question, I had infact tried something similar without any effect.
Yes it is possible.
document.onload = function() {
var elementYouWant = document.getElementById("someID");
elementYouWant.onclick = console.log("Yup.. It was clicked..");
};
Reference.
The answer to the question is not as trivial as it may seem at first sight. I had also thought of a logic of the type described in the Pogrindis' response.
But here, in the case of interaction between the main script (i.e. that of the add-on) and generic script of arbitrary documents, the pattern is different.
In summary, the interaction takes place in this way:
It is required the API page-mod.
Through the property includes of the object PageMod you create a reference to the document, specifying the URI (wildcards are allowed).
Via the contentScriptFile property it is set the URL of the .js file that will act as a vehicle between the main code and that of the document.
Here's an example that refers to the specific needs of the context in which I am. We have:
an add-on code (the main code);
a Sidebar type html document (gui1.html) loaded in the file that I
use as a simple UI (I advise against the use of Frames, since it does
not support many typical HTML features - eg the click on a link,
etc.) containing a link to a second document (gui2.html) which will then
be loaded into the browser tab (I needed this trick because the
Sidebar does not support localStorage, while it is necessary for me);
a script in the document.
We must create an exchange of information between the two elements. In my case the exchange is unidirectional, from the page script to the main one.
Here's the code (main.js):
var pageMod = require("sdk/page-mod");
pageMod.PageMod({
include: "resource://path/to/document/gui2.html",
contentScriptFile: data.url("listen.js"),
onAttach: function(worker) {
worker.port.on("gotElement", function(elementContent) {
console.log(elementContent);
});
}
});
and in the html page script:
<script type="text/javascript">
[...]
SOWIN = (navigator.userAgent.toLowerCase().indexOf("win") > -1) ? "win" : "nix";
if (SOWIN == "win") {
window.postMessage("win","*");
} else {
window.postMessage("Linux","*");
}
[...]
</script>
Finally in the JS file (listen.js) to be attached to the page script:
window.addEventListener('message', function(event) {
self.port.emit("gotElement", event.data);
}, false);
This is just a small example, but logic I would say that it is clear. The uploaded content scripts are not accessible directly from main.js (i.e. the add-on), but you can create a bidirectional communication through the exchange of messages. To achieve this we have to put ourselves in listening the event Attach of the page-mod. Then, it is passed a worker object to the listener; that worker may be used by the add-on for the exchange of messages.
Here are the references to have an exhaustive picture:
Interacting with page scripts
Communicating with other scripts
page-mod
port
Communicating using "port"
postMessage
Communicating using postMessage

Chrome extension: sending data to window created with chrome.windows.create

I'm struggling to find the best way to communicate with my web app, which I'm opening with chrome.windows.create in my extension.
I've got the wiring between content script and background script right. I can right click an element and send it's value to the background script, and the background script creates a window containing my webapp. But from there I can't figure out how to access and use that value in my webapp (it needs to load the value into an editor).
I've tried setting fns and vars on the window and tab objects, but somehow they go missing from the window object once the web app is loaded.
With chrome.tabs.executeScript I can fiddle with the dom, but not set global variables or anything on 'window' either.
If there isn't a better way, I guess I'm forced to add to the DOM and pick that up once my web app is loaded, but it seems messy. I was hoping for a cleaner method, like setting an onLoadFromExtension fn which my web app can execute to get the value it needs.
I found a method that works after much trial and error, though it still seems error prone. And it also depends on the extension ID matching the installed one, so if that can't be hard-coded it'll be another message that needs passing through another channel (after reading up, looks like that can be hard-coded since it's a hash of the public key, so problem solved)... Starting to think manipulating the DOM is less messy...
background.js:
var selectedContent = null;
chrome.runtime.onMessageExternal.addListener(
function(request, sender, sendResponse) {
console.info("------------------------------- Got request", request);
if (request.getSelectedContent) {
sendResponse(selectedContent);
}
});
web app:
var extensionId = "naonkagfcedpnnhdhjahadkghagenjnc";
chrome.runtime.sendMessage(extensionId, {getSelectedContent: "true"},
response => {
console.info("----------------- Got response", response);
if(response) {
this.text = response;
}
});
manifest.json:
"externally_connectable": {
"ids": ["naonkagfcedpnnhdhjahadkghagenjnc"],
"matches": ["http://localhost:1338/*"]
},
Within the popup, do the following:
const parentWindow = window.opener
parentWindow.postMessage({ action: 'opened' })
window.onmessage = msg => {
alert(JSON.stringify(msg.data)) // Alerts you with {"your":"data"}
}
Within the script that will call chrome.windows.create, do the following:
window.onmessage = msg => {
if (msg.data.action == 'opened') {
msg.source.postMessage({ your: 'data' })
}
}
Set setSelfAsOpener: true when calling chrome.windows.create
How does this work?
Due to limitations of the Chrome extension windows API, the created window needs to post a message to its creator (aka window.opener) or else the creator won't have access to a WindowProxy (useful for posting messages to the created window).

When does UIWebView start recognising Javascript code

// MARK: - UIWebViewDelegate
func webViewDidFinishLoad(webView: UIWebView) {
let initResponse = self.stringByEvaluatingJavaScriptFromString("initialize('','','',\(isPreview))")
if (initResponse != "") {
isLoaded = true
}
println("\(viewType) initResponse \(initResponse)")
}
In my program, I am attempting to initialise UIWebView by calling a Javascript function. UIWebView is loaded with a local template file.
Apparently, the webview still does not respond to my javascript command even though webViewDidFinishLoad is called.
Therefore, I think there is another moment when web view can actually start accept Javascript calls. In my opinion, it is when document is ready for my locally loaded html file.
But then, how do I know when my UIWebview is ready to receive Javascript code?
For iOS/UIWebView, please have a try on this
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if (![[webView stringByEvaluatingJavaScriptFromString:#"document.readyState"] isEqualToString:#"complete"])
return;
// Now it's ready
}
and for OS X, this one webView:didFinishLoadForFrame: is what you want.

Getting content out of WebView In a unit test Android, using java script

I have been able to get content out of WebView using javascript and loadUrl() method having specified an interface thats called from javascript string that is injected into WebView.The problem is that this only works for me when the loadUrl() method is present in onPageFinished() method in the WebView client. What I want to do is I want to get the content out of the WebView (with the content already loaded). The WebView is in an activity instrumentation test case and I can for instance use findAll() method and that works fine. For some reason I can not use loadUrl() and get the desired behaviour (which is injecting javascript and getting content out of the WebView with a help of an interface).
PLease help.
Thanks
Pawel
EDIT:
Just adding code to show what I am doing exactly:
Yes I understand that but my problem is that I am trying to do it within a test case this way:
public void testWebView() throws Exception {
solo.sleep(3000); // wait for views to load on the screen
WebView a=null;
ArrayList<View> views = solo.getCurrentViews(); // I am using solo object to get views for the screen currently loaded
for(View s:views)
{
if (s instanceof WebView)
{
a = (WebView)s; // this is where I get my WebView
}
}
Instrumentation inst = getInstrumentation();
inst.runOnMainSync(new Runnable()
{
public void run()
{
int d =a.findAll("something"); // this method runs fine on the object and i get the desired result
WebSettings settings = a.getSettings();
settings.setJavaScriptEnabled(true);
a.loadUrl("javascript:document.location = document.getElementById('google').getAttribute('href')"); // this javascript is never executed and that is my problem
}
});
}
You can inject javascript in a loaded page much the same way you can do it in desktop browsers - via inline javascript entered into navigation bar.
Bind some Java object so that it can be called from Javascript with WebView:
addJavascriptInterface(javaObjectExposed, "JSname")
Force execute javascript within an existing page by
WebView.loadUrl("javascript:window.JSname.passData("some data from page");");

Categories

Resources