I have a native (windows) application that has an embedded web browser. Currently I'm invoking a javascript function from the backend (c++/c#). However, if javascript is disabled this fails and I'd like to provide a fallback mechanism. Is there a way to determine if javascript is disabled?
In the IE Web Control, you can simply force JavaScript on. Please refer to the following interfaces, which your host has to implement:
IDocHostUIHandler
IDocHostShowUI
IInternetSecurityManager
IServiceProvider
Another approach would be for your HTML page to query the window.external object and call a method on it, which you implement in your host, which sets a flag to true. Not being called would mean the JavaScript was not executed.
Wow, using web browser under mfc is really pain in the ass, you can do it by getting the IInternetSecurityManager, and check if is enabled to execute javascript by current policy, if user select to disable javascript on his IE, you will need to overwrite the value in the registry.
HRESULT hr = CoCreateInstance(CLSID_InternetSecurityManager, NULL,
CLSCTX_INPROC_SERVER,IID_IInternetSecurityManager, (void**)&pSecurityMgr);
int policy = URLPOLICY_ALLOW;
hr = pSecurityMgr->ProcessUrlAction(L"http://www.google.com", URLACTION_SCRIPT_RUN,
(BYTE*)&policy, sizeof(policy), NULL, 0, PUAF_TRUSTED, 0);
if hr = S_FALSE, javascript execution is disabled...
Related
Say we have a standard login page like the one below:
We can access the HTML elements in the DOM using jQuery or plain JavaScript like this:
In other words, the way to get the pixel location of an element in a web page is quite simply by using element.getBoundingClientRect():
var rect = element.getBoundingClientRect();
console.log(rect.top, rect.right, rect.bottom, rect.left);
So we can do this from the console or programmatically from a web app.
Now, say we have an Android browser (Chrome/Mozilla/WebView) in the foreground at any time. I can retrieve the URL of the web page in the browser. In this case:
https://login.microsoftonline.com/
So my question is, given the URL of a login page, how do I similarly get access to the same input field on an Android browser?
I need to be able to access the HTML elements of a web page in an Android browser, and calculate its pixel location. As input, I have the URL of a web page in any Android browser.
I am talking about doing this from an Android app, within the Android runtime, i.e. programmatically using Java/JS code.
In case someone needs the DOM structure of the page as text, it can be obtained programmatically with the following (Java) code:
URL url;
HttpURLConnection urlConnection;
String DOMContent = null;
try {
url = new URL("https://login.microsoftonline.com/");
urlConnection = (HttpURLConnection) url.openConnection();
int responseCode = urlConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
DOMContent = readStream(urlConnection.getInputStream());
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
I need access to the HTML elements of a mobile web page within the Android runtime, just as we would in a web app or extension in a desktop browser. Or in other words, I need to be able to access/manipulate the DOM content of a mobile browser from an Android app.
How can this be done?
Update:
JavaScriptBridge looks promising. DocumentBuilder could help us convert the DOM into Java objects which may then be accessed/manipulated natively from Android.
References:
1. How to execute JavaScript on Android?
2. Calling JavaScript functions in WebView
3. How to run Javascript code in a background Service on Android
4. Is there any way to get access to DOM structure in Android's WebView?
5. Android webview Access the DOM
6. In Android Webview, am I able to modify a webpage's DOM?
7. Android WebViews and the JavaScript to Java bridge
8. Using Javascript bridge in android
9. Alternative way for communication between WebView and native
Use the following code after the page has been loaded (implement a custom WebViewClient and check the onPageFinished)
String query = "document.getElementById(\"WhateverElement\").getBoundingClientRect();"
webView.evaluateJavascript(query, new ValueCallback<String>() {
#Override
public void onReceiveValue(String s) {
Log.d("LogName", s); // s has the getBoundingClientRect
}
});
The webpage needs to be rendered first in order to get the pixel position of the input field. and to manipulate dom content in android, the best way is to go with JS Interface. The way mentioned by ZUN is also helpful. You can execute arbitrary JavaScript at runtime either way.
However, there is one particular library that can catch your attention i.e. jsoup
From the jsoup website:
jsoup is a Java library for working with real-world HTML. It provides
a very convenient API for extracting and manipulating data, using the
best of DOM, CSS, and jquery-like methods. jsoup implements the WHATWG HTML5 specification and parses HTML to the same DOM as modern browsers do.
Side note: if you don't want to show webpage to the user till all of your calculations are done, you might be interested in playing with Visibility of WebView
I have a very simple javascript code in oracle procedure which us used for fetching the Username for Active Directory as my application don't have any user interface.
htp.p('function disp_alert()');
htp.p('{');
htp.p('var WinNetwork = new ActiveXObject("WScript.Network")');
htp.p(' WinNetwork = WinNetwork.UserName');
htp.p('alert(WinNetwork)');
htp.p('}');
It throws exception ActiveXObject creation error: Automation server can't create object
I tried changing browser setting script ActiveX controls marked safe for scripting to enable and it worked.
But in my case the application is accessed by users in client network and we can't tweak security settings for each machine in network. Can anyone suggest an alternative solution or any other method for fetching the windows username?
If you absolutely have to use WScript.Shell for whatever you want to accomplish, you may set the option for your intranet zone by GPO.
You may find the corresponding GPO setting with the help of that site: https://getadmx.com/?Category=InternetExplorer&Policy=Microsoft.Policies.InternetExplorer::IZ_PolicyScriptActiveXMarkedSafe_3
I need a way to use a Java API (jar) from the javascript code on the local client. Can this be achieved and how?
Context
I have a Java API (jar file) that allows to connect to a real time information feed. You can submit a query and, for example, print the events you will receive:
service.subscribe(query, evt -> print(evt));
That API can only be used on the client machine for legal reasons so I can't expose it as a web service from a server.
Goal
I would like to create a web page that gets data from a web service and combines it with the real time information data obtained from the Java API locally.
I am using angular 2 but happy to consider any suggestions.
Web service
I have seen various similar questions but the answers tend to be: expose the API via a web service - that is not possible in my case.
You can use java applets for this purpose.
You should start by making an applet that encloses the call to your method:
public class TestApplet extends Applet{
private ? service = ...;
public Object subscribe(Object query) {
return service.subscribe(query, evt -> print(evt));;
}
}
This applet can then be included in the html of the webpage:
<script src="https://www.java.com/js/deployJava.js"></script>
<script>
<!-- applet id can be used to get a reference to the applet object -->
var attributes = { id:'testApplet', code:'yourpackage.TestApplet', width:1, height:1} ;
var parameters = {jnlp_href: 'test_applet.jnlp'} ;
deployJava.runApplet(attributes, parameters, '1.6');
</script>
Then you can use javascript to call the methods:
var greeting = testApplet.subscribe("Test");
Note that applets are being phased out because of their security problems, but this is ok in an controlled and embedded environment.
The following oracle tutorial gives more information about this technique: Invoking Applet Methods From JavaScript Code
The only way I can think of is using the javafx webview: http://docs.oracle.com/javafx/2/webview/jfxpub-webview.htm
Basically:
you create your own java-based-"webbrowser" withjavafx
you can then expose the java api into the webview
you can open a normal html page (i.e. http://server.tld/mypage.html) within the webview and use javascript to access the api
in the javascript you can check if the site has been opened with a normal browser or with you custom webview by checking if the exposed api is available:
the java code for something like that:
WebView webView = new WebView();
jfxPanel.setScene(new Scene(webView));
webEngine = webView.getEngine();
webEngine.setJavaScriptEnabled(true);
webEngine.setConfirmHandler(new ModalConfirmDialog(self));
// get the window and pass the required daos
JSObject jsobj = (JSObject) webEngine.executeScript("window");
// pass the dataaccess to the js context
jsobj.setMember("javaapi", getApiInstance());
webEngine.load("http://whatever.tld/mypage.html");
in javascript:
if(!window.javaapi) {
alert("Unable to get local java api");
return;
}
Other possibilities:
Applets: they wont work because they need to be downloaded from the same source as the webpage (which you cant use because of licensing restrictions)
JSP/Servlet: cant be used because this means the api must reside on the server (again licensing restriction)
Java Javascript Engine: You can call javascript directly from java, but since you want the javascript in a webpage, this wont work either...
Simply you cannot run .jar file from java script (But you can execute from nodejs) You can use applet to do that. You can refer this link.
It might sound really weird but actually, there's such tool that enable's you to 'convert' from java to js. But of course it has it's limitations and in order to successfully apply it in your particular case w/o doing modifications and dancing with a tambourine, you should be extremely lucky. this tool is able to convert it to js and allows you to create a JS API for the converted JS, so that it can be accessible from other js scripts. What I'm talking about is GWT. You must have source files of a jar (it might be decompiled sources) including all sources of dependencies that are used by lib.
Maybe you can invest in building a bridge between your JS code and the jar using Nashorn.
It allows you to evaluate JS code and invoke JS functions from Java, so it may serve your usecase. You can build a Java layer to connect to the API from the jar and then publish the results to JS by calling some function using Nashorn.
Or you can make use of the ability to directly call Java functions from JS.
Here is a simple tutorial
I have an old html page that creates a script file and executes it using:
fsoObject = new ActiveXObject("Scripting.FileSystemObject")
wshObject = new ActiveXObject("WScript.Shell")
I am trying to modify it and make it usable also from other browsers. If you know the answer stop reading and please answer. If there is no quick answer, here is the description of my attempts. I was successful in doing the job, but only when the script is shorter than 2000 characters. I need help for scripts longer than 2000 characters.
The webpage is for internal use only, so it is easy for me to create a custom URL protocol on each computer that runs a VBScript file from a network drive.
I created my custom URL Protocol that starts a VBScript file like this:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\MyUrlProtocol]
"URL Protocol"=""
#="Url:MyUrlProtocol"
"UseOriginalUrlEncoding"=dword:00000001
[HKEY_CLASSES_ROOT\MyUrlProtocol\DefaultIcon]
#="C:\\Windows\\System32\\WScript.exe"
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open]
[HKEY_CLASSES_ROOT\MyUrlProtocol\shell\open\command]
#="C:\\Windows\\System32\\WScript.exe \"X:\\MyUrlProtocol.vbs\" \"%1\""
In MyUrlProtocol.vbs I have this:
MsgBox "The length of the link is " & Len(WScript.Arguments(0)) & " characters"
MsgBox "The content of the link is: " & WScript.Arguments(0)
When I click on click me I see two messages, so everything works well (tested with Chrome and IE in Windows 7.)
It works also when I execute document.getElementById("test").click()
I thought this could be the solution: I would pass the text of the script to the VBS static script, which would create the dynamic script and run it, but with this system I can't pass more than ~2000 characters.
So I tried to split the text of the script in chunks smaller than 2000 characters and simulate several clicks on the link, but only the first one works.
So I tried with xmlhttp.open("GET","MyUrlProtocol:test",false);, but Chrome says Cross origin requests are only supported for HTTP.
Is it possible to pass more than 2000 characters to a VBScript script via a custom URL protocol?
If not, is it possible to call several custom URL protocols in sequence?
If not, is there another way to create a script file and run it from Javascript?
EDIT 1
I found a solution, but in Chrome only works when it likes, so I'm back to square one.
The code below in IE executes the script 4 times (correct), but in Chrome only the first execution runs.
If I change it to delay += 2000, then Chrome usually runs the script 2 times, but sometimes 1 and sometimes 3 or even 4 times.
If I change it to delay += 10000, then it usually runs the script 4 times, but sometimes misses one.
The function is always executed 4 times, both in Chrome and IE. What is weird is that the sr.click() sometimes does nothing and the function execution continues.
<HTML>
<HEAD>
<script>
var delay;
function runScript(text) {
setTimeout(function(){runScript2(text)}, delay);
delay += 100;
}
function runScript2(text) {
var sr = document.getElementById('scriptRunner');
sr.href='intelliclad:'+text;
sr.click();
}
function test(){
delay = 0;
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
</script>
</HEAD>
<BODY>
<input type="button" value="Run test" onclick="test()">
scriptRunner
</BODY>
</HMTL>
EDIT 2
I tried with Luke's suggestion of setting the next timeout from inside the call back but nothing changed (IE works always, Chrome whenever it likes).
Here is the new code:
var scripts;
var delay = 2000;
function runScript() {
var sr = document.getElementById('scriptRunner');
sr.href = 'intelliclad:' + scripts.shift();
sr.click();
if(scripts.length)
setTimeout(function() {runScript()}, delay);
}
function test(){
scripts = ["uno", "due", "tre", "quattro"];
runScript();
}
Some background: The page asks for the shape of a panel, which can be just a few parameters [nfaces=1, shape1='square', width1=100] or hundreds of parameters for panels with many faces, many slots, many fasteners, etc. After asking for all the parameters a script for our internal 3D CAD (which can be larger than 20KB) is generated and the CAD is started and asked to execute the script.
I would like to do all on the client side, because the page is served by a Domino web server, which can't even dream of managing such a complex script.
I didn't read your whole post...have an answer:
I too wish that custom url protocols can handle long urls. They simply do not. IE is even worse as some OSs only accept 800 chars.
So, here's the solution:
For long urls, only pass a single use token. The vbscript uses the token
and does a url get to your web server to get all of the data.
This is the only way I've been able to successfully pass lots of data around. If you ever find a clearer solution, please remember to post it here.
Update:
Note that this is the best way I have found to deal with the url protocol limitations. I too wish this was not necessary. This does work and works well.
You mentioned Dominos, so possibly you need something in a POS environment... I create a web based POS system, so we could face a lot of the same issues.
Suppose you want a custom url to print a pdf to the default printer without the annoying popup window. We need to do this thousands of times a day...
When building the web page, add the print button which when pressed calls the custom url: myproto://printpdf?id=12345&tocken=onetimetoken
this will execute your vbscript on the local desktop
in your vbscript, parse the arguments and react. In this case, your command is printpdf and the id is 123456 and you have a onetime tocken key.
have the vb script to an https get to: https://mydomain.com/APIs/printpdf.whatever?id=12345&key=onetimetoken
check the credentials based on the ip address and token, if all aligns, then return the contents of the pdf (you may want to convert the pdf to a byte array string)
now the vbscript has the pdf, assemble it and write it to a temp folder then execute a silent pdf print command (I use Sumatra PDF http://blog.kowalczyk.info/software/sumatrapdf/free-pdf-reader.html)
mission accomplished.
Since I do know what you what to do in your custom url and the general workflow, I can only describe how I've solved the sort url issue.
Using this technique, the possibilities are limitless. You have full control over the local computer running the web browser, you have a onetime use token which grants access to a web API with can return any sort of information you program.
You could write a custom url protocol to turn on the pizza oven if you wanted :)
If you are not able to create the server side code which is listening for vbscript's get request then this would not work.
You might be able to pass the data from the browser to the vbscript using the clipboard.
Update 2:
Since in this case the data is on the client (one single form can define hundreds of parameters), the server API doesn't know what to answer to the vb script request. So the workflow described above must be preceded by these two steps:
The onkeypress event executes a submit to send the current parameters to the server
The server replies with the refreshed form, adding to the body onload a call to a function which uses another submit to call the custom url, as described on point 1 listed above.
Update 3:
stenci, what you've added (in Update 2) will work. I would do it like this:
user presses a button saying I'm done editing the form
ajax post the form to the server
the server saves the data and attaches unique key to the datastore
the server returns the key to ajax callback function
now the client has a single use key and invokes the url schema passing the key
vbscript does an https get to the server and passes the key
server returns the data to the vbscript
It is a bit long winded. Once coded it will work like a charm.
The only other alternative I can see is to copy the form data to the clipboard using something like: http://zeroclipboard.org/
and then in vbscript see if you can read the clipboard like: Use clipboard from VBScript
How about creating an iFrame for each instance?
Something like this:
function runScript(text) {
var iframe = document.createElement('iframe');
iframe.src = 'intelliclad:'+text;
document.body.appendChild(iframe);
}
function test(){
runScript("uno");
runScript("due");
runScript("tre");
runScript("quattro");
}
You can then use css styling to make these iframes transparent / hidden.
You might not like this answer, but I've used this method in the past and it works.
Instead of relying on ActiveX, consider using a Java Applet, and JNI.
Basically, you have to make sure the native scripts you want to run are available on your client machine, along with a JNI wrapper.
The applet will have to be at least self signed, for the browser to allow it to load and access a native library. Once the JNI libraries are loaded, you can easily call methods from the page / applet.
As a consequence of using Java, you could possibly use the same applet for windows as well as linux clients, provided of course you have native libraries present on the respective clients.
This series of articles talks about precisely your problem : http://www.javaworld.com/article/2076775/java-security/escape-the-sandbox--access-native-methods-from-an-applet.html
P.S the article is really old, but the concept remains unchanged.
How to call a Javascript function declared in my extension, using a html button from my web page?
I have a html page, with a button inside. When the user click the button, it will call a function that I already declared inside my own firefox extension.
Since you control the web page, the easiest and the safest method to do what you want would be to dispatch a custom DOM event in the web page and listen to it in the extension code:
https://developer.mozilla.org/En/Code_snippets/Interaction_between_privileged_and_non-privileged_pages
Here's an example extension I wrote that does exactly this http://mozilla.doslash.org/cw/ (not updated to the most recent Firefox version, but it's clean and should be easy to update).
Your Firefox extension runs in a different Javascript context to your HTML page, so the extension cannot be directly called from the Javascript in your HTML page.
However, you can design the extension to allow access from HTML. HTML Javascript isn't generally allowed to access the Component object, so you need to allow the HTML code a way to get at the object in your extension. To do this, create an XPCOM component in your extension, and set the object in the "JavaScript global property" category through the nsICategoryManager object. The entry name is the string used from unprivileged Javascript, the value is the contract ID for your XPCOM class.
However, you also need to allow unprivileged Javascript access to your object, or the script security manager will block access. To allow this, implement nsISecurityCheckedComponent - providing canCreateWrapper(in nsIIDPtr iid), canCallMethod(in nsIIDPtr iid, in wstring methodName), canGetProperty(in nsIIDPtr iid, in wstring propertyName) and canSetProperty(in nsIIDPtr iid, in wstring propertyName) to return allAccess for the allowed properties, and noAccess otherwise.
Be careful what you do with user input, and what you allow access to - it is very easy to accidentally create a security hole in the browser doing this.
Try to put this at the beginning of your javascript function that tries to access a local file:
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
This will give the user the choice as to whether they want to allow your code to access the local filesystem.