Java web start launch app with javascript [duplicate] - java

I have made a Java webstart application, and created an HTML page with the link to launch it. The problem is, in Google Chrome, there is no option to just 'Open' a file without saving it. I want to make an HTML page that can automatically launch a JNLP file without having to save it. Or rather, without the user having to open their file explorer to launch it) Is this possible?

After getting fed up this problem, I wrote my own work around extension.
It's written under ubuntu, but should be portable (even to win32 with some work/reading).
Single click launches a jnlp file without prompting, or downloading. it just passes the url for the jnlp file to javaws directly. no cluttered Downloads folder, no extra clicks.
It's simple, crude and effective. I filtered the URL so it would only apply to my own internal server so I don't accidentally launch some random jnlp file. Lots more could be done to improve it, I'm sure. Use AS-IS, no warranty, etc, etc.
The files:
/usr/local/bin/jnlp-launcher
#!/usr/bin/env python
import struct
import sys
import threading
import Queue
import json
import os
# On Windows, the default I/O mode is O_TEXT. Set this to O_BINARY
# to avoid unwanted modifications of the input/output streams.
if sys.platform == "win32":
import os, msvcrt
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
# Helper function that sends a message to the webapp.
def send_message(message):
# Write message size.
sys.stdout.write(struct.pack('I', len(message)))
# Write the message itself.
sys.stdout.write(message)
sys.stdout.flush()
# Thread that reads messages from the webapp.
def read_thread_func(queue):
message_number = 0
while 1:
# Read the message length (first 4 bytes).
text_length_bytes = sys.stdin.read(4)
if len(text_length_bytes) == 0:
if queue:
queue.put(None)
sys.exit(0)
# Unpack message length as 4 byte integer.
text_length = struct.unpack('i', text_length_bytes)[0]
# Read the text (JSON object) of the message.
text = sys.stdin.read(text_length).decode('utf-8')
decoded = json.loads(text);
os.system("javaws " + decoded['url']);
def Main():
read_thread_func(None)
send_message('"complete"')
sys.exit(0)
if __name__ == '__main__':
Main()
The chrome extension is 2 files placed in a local directory:
manifest.json
{
"manifest_version": 2,
"background": {
"persistent": false,
"scripts": [ "bg.js" ]
},
"name": "JNLP Fixer",
"description": "Handle JNLPs",
"version": "1.0",
"permissions": [
"downloads", "nativeMessaging"
]
}
And bg.js (edit as needed for host filters)
chrome.downloads.onCreated.addListener(function(downloadId) {
var expr = /\.jnlp$/;
//this is to limit where we apply the auto-launch.
//for our use, i only wanted it for internal jnlps.
var hostExpr = /(http|https):\/\/internal.company.com\//;
if (hostExpr.test(downloadId.url)) {
if (downloadId.state == "in_progress") {
console.log(downloadId.url);
chrome.downloads.cancel(downloadId.id,function() {
console.log("cancelled");
});
chrome.runtime.sendNativeMessage("com.hcs.jnlplauncher",
{url:downloadId.url},
function(response)
{
console.log(chrome.runtime.lastError);
console.log(response);
}
);
}
}
})
Put manifest.json and bg.js in a folder and load it as an Unpacked extension in chrome in developer mode under chrome://extensions
Get the ID for the extension from the chrome://extensions pages.
Next is the bridge between the extension and the shell script.
File: com.hcs.jnlplauncher.json
{
"name": "com.hcs.jnlplauncher",
"description": "JNLP Launcher",
"path": "/usr/local/bin/jnlp-launcher",
"type": "stdio",
"allowed_origins": [
"chrome-extension://iacomlhfiphkdfjjjmlgckdkhmkhkibe/"
]
}
Place this under "~/.config/google-chrome/NativeMessagingHosts" (for linux). see google for windows locations.
Put your extension ID from the previous step into that file.
Make sure javaws is in the path. (that chrome runs with). link to /usr/bin is easiest way to be sure.
Click on a jnlp file and enjoy!!! No prompt, no ClickToOpen, and no file saved in the Downloads directory.!
If someone would like to bundle this all together into a nice packaged installer and/or chrome extension feel free. Please credit me (Chris Holt -- hobie744#gmail.com) and let me know. At first glance, I couldn't see how to bundle the NativeMessagingHosts piece into the extension. Perhaps it has to be 2 pieces? This is my first adventure in Chrome Extensions and NativeMessaging. Most of the code comes from the API docs and examples, and there are probably a few bugs.

Launch the JNLP using an embedded applet deployed using web start.
Start with a Swing based JApplet that accepts an image path (icon) and a string for the button. Deploy the applet (embedded in the web page, where the link would be) using JWS.
When the user clicks the button, use the BasicService.showDocument(URL) method to launch the JWS (frame based) app. As I note in the demo. of the BasicService..
..In Java 6+, a call to show another web start launch file (e.g. BasiceService.showDocument(another.jnlp)) will be handed directly to JavaWS, with no browser window appearing.

Unfortunately this is a bug(/feature?) in Google Chrome which still exists, however it is partly fixed: you can now automatically open jnlp files, but it they are still saved to the downloads folder
download the jnlp
right click in the download bar and select to always open files of this type
clicking the jnlp now directly launches it

This sample(Embedding JavaFX 2 in Swing) and articles are a great sample and they also work with modern browsers
sample http://www.oracle.com/technetwork/java/javase/overview/javafx-samples-2158687.html
documentation : https://docs.oracle.com/javase/8/docs/technotes/guides/deploy/deployment_toolkit.html#BABIJEHC

For testing or webscraping (when you cannot change or control jnlp handling) I found a workaround via Selenium + Python (but similar thing should be feasible in Java or other language too). In Python I just click programmatically on the notification in Chrome to allow downloading and installation of the jnlp file (with help of win32api and win32con, but similar approach could work also on Linux or Mac, after code rework). You can see details here

Related

Applet right click copy and past function [duplicate]

I've a signed applet (which verifies correctly with jarsigner) that for some reason will not allow copy and paste from the system clipboard into a JTextField despite the documentation telling me that it is supposed to work for signed applets.
Furthermore, I've other applets which are signed with the same keyfile that do let me copy and paste text. I have searched high and low on the internet and can't seem to find any clues. What is making me pull my hair out is that there seems to be no way to debug this (no output in the console - no thrown exceptions).
Does any one have any ideas on how I can debug this to find out why Java doesn't like this particular applet?
Many thanks for any suggestions!
Well, it turns out with the release of the Java Plug-in 1.6.0_24 in February 2011, copy and paste from the system clipboard was deemed a security hole and disabled. You can copy and paste BETWEEN applets. But if you try to use something from your main clipboard, it can't be copied in.
So there are a couple of options for a workaround. You can roll back to an earlier version of the plug-in. That will work, but chances are all future releases will still keep copy and paste disabled, so you'd never be able to upgrade.
The other alternative is to provide a custom java security policy file which enables access to the system clipboard again.
First locate your local Java Security Policy file. The file is named java.policy and should be in the lib\security folder of your Java installation. On Windows 7, it can be found at C:\Program Files (x86)\Java\jre6\lib\security.
Copy this file to your home folder (ex. C:\Users\Kyle).
Rename the file to .java.policy (note the period at the beginning).
Edit the file in a text editor. Locate this line of text:
// "standard" properies that can be read by anyone
Add the following line just below it like so:
// "standard" properies that can be read by anyone
permission java.awt.AWTPermission "accessClipboard";
Save the file.
Close any open browsers and ensure that Java is not running before testing.
source: http://blogs.oracle.com/kyle/entry/copy_and_paste_in_java
Besides Dennis' overview, see Copy in sand-boxed app. in 1.6.0_24+ at the OTN.
While Ctrl-c copy no longer works by default, it is possible to add the functionality back in for any applet run in a 'Next Generation' Java Plug-In. Since Java Web Start existed, JWS provided sand-boxed copy via. the JNLP API's javax.jnlp.ClipboardService, & since Sun 1.6.0_10, & the next gen. plug-in, embedded applets can be deployed using JWS & can access the JNLP API.
See also
http://pscode.org/prop/js.html. Direct link to the test applet used in that thread. It offers copy ability in a sand-boxed applet. If it works on the problem machine (browser, set-up ..whatever) you should be able to rework it to offer (unprompted) paste in a signed applet.
Frame based Demo. of the ClipboardService, with source and build file.
I'm not sure why, but the JTextField object I'm using doesn't seem to be properly connected to the key events (maybe because I added a FocusListener?) - but adding the following code:
searchTextField.addKeyListener(new java.awt.event.KeyListener() {
public void keyPressed(KeyEvent e) {
//System.out.println("KEY:"+e);
if (e.getKeyCode() == 86 && ((e.getModifiers() & KeyEvent.CTRL_MASK) != 0)) {
java.awt.datatransfer.Clipboard clipboard = java.awt.Toolkit.getDefaultToolkit().getSystemClipboard();
java.awt.datatransfer.Transferable clipData = clipboard.getContents(clipboard);
String s;
try {
s = (String)(clipData.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor));
} catch (Exception ex) {
s = ex.toString();
}
searchTextField.setText(s);
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
});
...allows me to paste into the field.
Take a backup of java.policy which is at (Ex: C:\Program Files (x86)\Java\jre7\lib\security)
Look for line in java.policy file
// "standard" properies that can be read by anyone
Then modify java.policy and add as below
// "standard" properies that can be read by anyone
permission java.security.AllPermission;

Chrome native messaging cannot execute batch file

Here is the manifest of my host :
{
"allowed_origins" :
[
"chrome-extension://EXTENSION_ID/"
],
"description" : "my.app.host",
"name" : "my.app.host",
"path" : "‪C:\\chromejar\\launch.bat",
"type" : "stdio"
}
Here is the content of my launch.bat file :
setlocal enableextensions disabledelayedexpansion
for %%a in ("%~dp0\ChromeConnector.jar") do set "JARFILE=%%~fa"
java -jar "%JARFILE%"
pause
When I launch my Batch file separately, it works.
When I launch my extension from my website using an EXE file (developed in c#), it works.
But when I launch my extension from my website using the BAT file, it does not seem to work.
Can I test only the BAT part of it ? (put an echo text from the BAT to see the result on my app ?)
I tried to enable logging in chrome using this line : start chrome --enable-logging --v=1 but no particular log seems to be found in AppData\Local\Google\Chrome\User Data\chrome_debug.log, Do I need to add something to log particular errors ?
My Java code is as simple as this for the moment :
public static void main(String[] args) {
while(true) { }
}
Is there another way to test the jar application ?
Thanks in advance
Here are some answers to your questions:
1. Can I test only the BAT part of it ? (put an echo text from the BAT to see the result on my app ?)
In your BAT, you can send the output of your Java program to a text file. If the file exists after trying the call, it means the extension was able to launch the native app and you will be able to see the app output. For example, in the fourth line of your BAT you can do this:
java -jar "%JARFILE%" >> mybatfile.log
2. I tried to enable logging in chrome using this line : start chrome --enable-logging --v=1 but no particular log seems to be found in AppData\Local\Google\Chrome\User Data\chrome_debug.log, Do I need to add something to log particular errors ?
Look for messages including "native_message_process_host.cc", for example:
[4680:5612:0809/194917:ERROR:native_message_process_host.cc(291)] Native Messaging host tried sending a message that is 2036688930 bytes long.
3. My Java code is as simple as this for the moment :
public static void main(String[] args) {
while(true) { }
}
Refer to this post for receiving and sending stdio messages from java:
Java native messaging with chrome extension - cannot correctly write length
4. Is there another way to test the jar application ?
I suggest to generate logs from your java app, so you can review the received and sent messages, including the initial 4 bytes denoting the messages length.

Chrome-application: Launch a external application (shell script or jar) using native messaging hosts

I'm developing a google-chrome application and I need to launch a Java application. (Really, I need to read and save files without a choosefile pop-up).
As NPAPI library has been deprecated, I have looked for alternatives and I have decided to use "Native messaging hosts" to launch the external application.
To create my first example, I have tried to launch a shell script because I think that is more easy. However I have not managed to launch the script. I'm developing in linux
The manifest file is in this path
"/etc/opt/chrome/native-messaing-hosts/com.centeropenmiddleware.l3p1.xmleditor.json":
and the contain is:
{
"name": "com.centeropenmiddleware.l3p1.xmleditor",
"description": "Saving a file",
"path": "/home/paco2/pp.sh",
"type": "stdio",
"allowed_origins": [
"chrome-extension://plfnjepfbddljeogeacemcpceiofapnm/"
]
}
The application id is plfnjepfbddljeogeacemcpceiofapnm
the script creates a file:
#!/bin/bash
echo hola mundo >> aaa
The application code fails in this line:
try {
var port = chrome.runtime.connectNative ('com.centeropenmiddleware.l3p1.xmleditor')
} catch (e) {
console.log(e);
return;
}
The error caught is
{
message : "Error connecting to native app: com.centeropenmiddleware.l3p1.xmleditor",
stack : "Error: Error connecting to native app: com.centeropenmiddleware.l3p1.xmleditor
at Object.<anonymous> (extensions::runtime:189:11)
at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
at Object.handleRequest (extensions::binding:55:27)
at Function.target.(anonymous function) (extensions::SafeBuiltins:19:14)
at Object.<anonymous> (extensions::binding:318:32)
at saveas (chrome-extension://plfnjepfbddljeogeacemcpceiofapnm/js/editorRoutines.js:104:35)
at HTMLButtonElement.sendFileContentFromEditor (chrome-extension://plfnjepfbddljeogeacemcpceiofapnm/js/editorRoutines.js:89:27)"
}
To launch the application I have used these commands
google-chrome --load-and-launch-app=/home/paco2/Projects/UPM/XMLEditor/XMLEditor/ --native-messaging-hosts="com.centeropenmiddleware.l3p1.xmleditor.json=/etc/opt/chrome/native-messaing-hosts/com.centeropenmiddleware.l3p1.xmleditor.json"
google-chrome --load-and-launch-app=/home/paco2/Projects/UPM/XMLEditor/XMLEditor/
I use the stablish google chrome version (34.0.1847.132)
Are there any wrong?
Bash is a bad choice to handle the Chromiums Native Messaging API.
It cannot handle binary info in any efficient way, see this question
I did manage to launch a bash script though. For that I used sendNativeMessage. Sending just once
chrome.runtime.sendNativeMessage('com.centeropenmiddleware.l3p1.xmleditor',
{text: "send"},
function(response) {console.log("Received " +
chrome.runtime.lastError.message);
});
It will launch /home/paco2/pp.sh, but parsing the message will be difficult in bash, even if it's a short as send.
In short don't use bash for this, try C++, or Python in between and use subprocess.

How can I associate a file type in mac within Java code?

How can I associate a file type like .vlan in mac within java code?
Runtime.getRuntime().exec("defaults write com.apple.LaunchServices LSHandlers -array-add
\"<dict><key>LSHandlerContentTag</key>
<string>.vlan</string><key>LSHandlerContentTagClass</key>
<string>public.filename-extension</string><key>LSHandlerRoleAll</key>
<string>org.category.program</string></dict>\"");
If the app. has a GUI, deploy it using Java Web Start and declare the file extension/type in the JNLP (launch) file. Here is a demo. of the JNLP API file services which should be able to associate the text/sleepytime content type of .zzz file with the (small) app.
Adding an association for a file type is supported to work on Windows, OS X & *nix (for all permissions, as well as sand-boxed apps. (the latter prompted)).
Try this :
Runtime.getRuntime().exec(
new String[] {
"defaults",
"write",
"com.apple.LaunchServices",
"LSHandlers",
"-array-add",
"<dict><key>LSHandlerContentTag</key><string>.vlan</string><key>LSHandlerContentTagClass</key><string>public.filename-extension</string><key>LSHandlerRoleAll</key><string>org.category.program</string></dict>"
}
);
And just to add, Runtime's exec has quite some pitfalls one need to be aware of.

Determing class path for jar html embed

I'm trying to serve an a JAR executable as a web app. I'm having issues figuring out the class path for the "code" attribute. The JAR was originally packaged on a CD-ROM.
Double clicking on the JAR itself (BDH.jar) executes "C:\Program Files\Java\jre6\bin\javaw.exe" -jar "C:\Documents and Settings\xxxx\My Documents\3. Current Projects\BDH\BDH.jar"
Double clicking on the bundled .exe executes "Differential Equations.exe" "C:\Documents and Settings\xxxx\My Documents\3. Current Projects\BDH\jre\bin\javaw.exe" -Xms134217728 -Xmx268435456 -classpath "C:\Documents and Settings\xxxx\My Documents\3. Current Projects\BDH\BDH.jar;C:\Documents and Settings\xxxx\My Documents\3. Current Projects\BDH\lax.jar;" com.zerog.lax.LAX "C:/Documents and Settings/xxxx/My Documents/3. Current Projects/BDH/Differential Equations.lax" "C:/Documents and Settings/xxxx/Local Settings/Temp/lax29DC.tmp"
Both of these launch the app successfully.
Oh, I'm using "applet-fu.js" to try and load this. I found a bunch of likely classes inside BDH.jar and have tried loading them without luck:
applet_fu.run(
{'width':'550','height':'320'},
{
'archive':'BDH.jar',
'code':'com/artmedialab/main/BDH.class'
},
'1.4.2',
'<p>Please install Java.</p>'
);
Any hope of making this work?
Since this is a double-clickable app, turns out I can't use it as an applet (not without changes, anyway). Apparently the way to distribute desktop apps over the web is by using JavaWebStart (sometimes called JNLP). See http://download.oracle.com/javase/tutorial/deployment/webstart/index.html for more details.

Categories