/*
* Copyright 2013 mpowers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.trsst.ui;
import java.awt.Desktop;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
import javafx.application.Platform;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.PopupFeatures;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javafx.util.Callback;
import com.trsst.Command;
import com.trsst.Common;
/**
* Creates a javafx frame just to embed a real live webkit browser. This exists
* as a stopgap to decouple the development of the web UI from the development
* of the all-javascript client.
*/
public class AppMain extends javafx.application.Application {
private WebView webView;
private static AppleEvents appleEvents;
private static String serviceUrl;
public static void main(String[] argv) {
if (argv.length > 0) {
serviceUrl = argv[0];
}
// register osx-native event handlers if needed
try {
// NOTE: must happen first to collect launch events
appleEvents = new AppleEvents();
// major improvement in font rendering on OSX
//System.setProperty("prism.lcdtext", "false");
} catch (Throwable t) {
// probably wrong platform: ignore
log.warn("Could not load osx events: " + t.getMessage());
}
if (System.getProperty("com.trsst.server.relays") == null) {
// if unspecified, default relay to home.trsst.com
System.setProperty("com.trsst.server.relays",
"https://home.trsst.com/feed");
}
try {
// write to log file if configured
String path = System.getProperty("com.trsst.logfile");
if (path != null) {
Handler handler = new FileHandler(path, 1024 * 1024, 3);
Logger.getLogger("").addHandler(handler);
log.info("Writing log file to: " + path);
}
} catch (SecurityException e) {
log.warn("No permission to write to log file", e);
} catch (IOException e) {
log.warn("Can't write to log file", e);
}
// we connect with our local server with a self-signed certificate:
// we create our server with a random port that would fail to bind
// if there were a mitm that happened to be serving on that port.
Common.enableAnonymousSSL();
// launch the app
launch(argv);
}
public static AppMain instance;
public static AppMain getInstance() {
return instance;
}
@Override
public void start(Stage stage) {
instance = this;
stage.setTitle("trsst");
webView = new WebView();
// intercept target=_blank hyperlinks
webView.getEngine().setCreatePopupHandler(
new Callback<PopupFeatures, WebEngine>() {
public WebEngine call(PopupFeatures config) {
// grab the last hyperlink that has :hover pseudoclass
Object o = webView
.getEngine()
.executeScript(
"var list = document.querySelectorAll( ':hover' );"
+ "for (i=list.length-1; i>-1; i--) "
+ "{ if ( list.item(i).getAttribute('href') ) "
+ "{ list.item(i).getAttribute('href'); break; } }");
// open in native browser
try {
if (o != null) {
Desktop.getDesktop().browse(
new URI(o.toString()));
} else {
log.error("No result from uri detector: " + o);
}
} catch (IOException e) {
log.error("Unexpected error obtaining uri: " + o, e);
} catch (URISyntaxException e) {
log.error("Could not interpret uri: " + o, e);
}
// prevent from opening in webView
return null;
}
});
String url = serviceUrl;
int i = url.lastIndexOf("/");
if (i != -1) {
url = url.substring(0, i);
}
webView.getEngine().load(url);
StackPane root = new StackPane();
root.getChildren().add(webView);
Scene scene = new Scene(root, 900, 900);
stage.setScene(scene);
stage.show();
// registers osx-native event handlers
// NOTE: must happen last to receive non-launch events
try {
appleEvents.run();
} catch (Throwable t) {
// probably wrong platform: ignore
log.warn("Could not start osx events: " + t.getMessage());
}
}
public void openURI(URI uri) {
// log.info("openURI: got this far 1: " + uri);
// mac feed urls use a feed:// protocol; convert to http
String url = uri.toString().replace("feed://", "http://");
final String script = "controller.pushState('/" + url + "');";
// log.info("openURI: got this far 2: " + uri);
Platform.runLater(new Runnable() {
public void run() {
try {
webView.getEngine().executeScript(script);
} catch (Throwable t) {
log.error("Unexpected error: ", t);
}
// log.info("openURI: got this far 3: " + script);
}
});
}
public void openFiles(final List<File> files) {
Platform.runLater(new Runnable() {
public void run() {
// for (File s : files) {
// TODO: read file for path
// TODO: extract link rel=self
// TODO: append that link to browser location
// }
}
});
}
@Override
public void stop() {
System.exit(0);
}
private final static org.slf4j.Logger log = org.slf4j.LoggerFactory
.getLogger(Command.class);
}