Bug 525305 – [API]Provide SWT.OpenUrl event (Linux implementation)

(For review/merge)

Linux implementation for OpenUrl event, with use of GDBus.
(As per original patch *1).

URL vs file detection done via "new URI(file).getScheme()".
I tested, this distinguishes URI's from files quite well.

I.e:
  /myfile/  ./file  file  .. ->  (OpenFile)
  http://www.eclipse.org   mailto:my@mail.com  ..  -> (OpenUrl)

I've tested with latest launcher:
1) Via launcher:
eclipse http://www.eclipse.org /tmp/myFile

2) Via gdbus calls:
gdbus call --session --dest org.eclipse.swt --object-path
/org/eclipse/swt --method org.eclipse.swt.FileOpen
"['http://www.google.com', '/tmp/myFile']"

Patchset 2:
- Updated URL detection logic so that files/urls are properly
distinguished.

Links:
[1] Original patch:
https://git.eclipse.org/r/#/c/30107/14/bundles/org.eclipse.swt/Eclipse+SWT/gtk/org/eclipse/swt/widgets/Display.java

Bug: https://bugs.eclipse.org/bugs/show_bug.cgi?id=525305
Change-Id: I6531989e3eb766fdf0715a0a9cb86c9ed2b973f3
Signed-off-by: Leo Ufimtsev <lufimtse@redhat.com>
diff --git a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
index 126bad8..11043ae 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT PI/gtk/org/eclipse/swt/internal/gtk/OS.java
@@ -115,6 +115,7 @@
 			System.out.print("SWT_LIB_Gtk:"+gtk_major_version()+"."+gtk_minor_version()+"."+gtk_micro_version());
 			if (System.getProperty(GDBUS_SYSTEM_PROPERTY) != null) {
 				System.out.print(" (DBus enabled)");
+				System.out.print(" (OpenUrl/OpenDocument supported)");
 			} else {
 				System.out.print(" (DBus dissabled)");
 			}
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java
index 13df5fe..af92613 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/SWT.java
@@ -848,7 +848,6 @@
 	 * This event is sent when SWT receives notification that a URL
 	 * should be opened.
 	 * </p>
-	 * Note that this event is not sent on Linux/GTK platforms.
 	 *
 	 * @see org.eclipse.swt.widgets.Display#addListener
 	 * @see org.eclipse.swt.widgets.Event
diff --git a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
index 1c9e721..7e8ac7d 100644
--- a/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
+++ b/bundles/org.eclipse.swt/Eclipse SWT/gtk/org/eclipse/swt/widgets/Display.java
@@ -12,6 +12,7 @@
 
 
 import java.io.*;
+import java.net.*;
 import java.util.*;
 import java.util.function.*;
 import java.util.regex.*;
@@ -1106,16 +1107,15 @@
 	OS.g_signal_connect (OS.gdk_keymap_get_default (), OS.keys_changed, keysChangedProc, 0);
 
 
-
 	// Handle gdbus on 'org.eclipse.swt' DBus session.
-	// E.g equinox launcher passes files to SWT via gdbus. "./eclipse myFile".
+	// E.g equinox launcher passes files/urls to SWT via gdbus. "./eclipse myFile" or "./eclipse http://www.google.com"
 	//
 	// Only one SWT instance can hold the unique and well-known name at one time, so we have to be mindful
 	// of the case where an SWT app could steal the well-known name and make the equinox launcher confused.
 	// We only initiate GDBus if system property is set.
 	//
 	// To force enable this, in a run-configuration, under arguments, append to the "VM arguments" : -Dswt.dbus.init
-	// For equinox launcher, See eclipseGtk.c:argVM_JAVA
+	// For equinox launcher, See eclipseGtk.c:gtkPlatformJavaSystemProperties
 	if (System.getProperty(OS.GDBUS_SYSTEM_PROPERTY) != null) {
 		GDBusMethod[] methods = {
 				new GDBusMethod(
@@ -1124,15 +1124,25 @@
 						// In a child eclipse, this will open the files in a new editor.
 						// This is reached by equinox launcher from eclipseGtk.c. Look for "g_dbus_proxy_call_sync"
 						"FileOpen",
-						new String [][] {{OS.DBUS_TYPE_STRING_ARRAY,"A String array containing file paths for OpenDocument signal"}},
+						new String [][] {{OS.DBUS_TYPE_STRING_ARRAY,"A String array containing file paths or URLs for OpenDocument/OpenUrl signal"}},
 						new String [0][0],
 						(args) -> {
-							// Dev note: GDBus Arguments are typically packaged into an Object of sort. First step is normally to un-pack them.
-							String[] fileNames = (String[]) args[0]; // Arg 1 is an array of strings.
-							for (int i = 0; i < fileNames.length; i++) {
-								Event event = new Event ();
-								event.text = fileNames[i];
-								sendEvent (SWT.OpenDocument, event);
+								String[] fileNames = (String[]) args[0];
+								for (int i = 0; i < fileNames.length; i++) {
+									Event event = new Event ();
+									event.text = fileNames[i];
+									try {
+										if (new URI (fileNames[i]).getScheme() != null) { // For specs, see: https://docs.oracle.com/javase/8/docs/api/java/net/URI.html
+											// E.g: eclipse http://www.google.com
+											sendEvent (SWT.OpenUrl, event);
+										} else {
+											throw new URISyntaxException(fileNames[i], "Not a valid Url. Probably file.");
+										}
+									} catch (URISyntaxException e) {
+										// E.g eclipse /tmp/myfile (absolute)   or  eclipse myfile  (relative)
+										sendEvent (SWT.OpenDocument, event);
+
+									}
 							}
 							return null;
 						})
diff --git a/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525305_Browser_OpenUrl.java b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525305_Browser_OpenUrl.java
new file mode 100644
index 0000000..261582c
--- /dev/null
+++ b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525305_Browser_OpenUrl.java
@@ -0,0 +1,47 @@
+package org.eclipse.swt.tests.gtk.snippets;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+/*
+ * Title: Handle files or URLs from eclipse launcher or gdbus.
+ * How to run: 
+    - Open snippet with Launch Configuration VM Argument: -Dswt.dbus.init
+    - Run launcher with file or url
+      eclipse /myFile  htpp://www.google.com 
+ * Bug description:
+ * Expected results: Browser opens URLs, filenames printed.
+ * GTK Version(s): 3.22/2.24
+ */
+public class Bug525305_Browser_OpenUrl {
+
+	public static void main(String[] args) {
+		Display display = new Display();
+		Shell shell = new Shell(display);
+		shell.setSize(500, 600);
+		shell.setLayout(new FillLayout());
+
+		final Browser browser = new Browser(shell, SWT.NONE);
+		browser.setText("hello <b>world!</b>");
+
+		display.addListener(SWT.OpenUrl, e -> {
+			System.out.println("OpenUrl with:" + e.text);
+			browser.setUrl(e.text);
+		});
+
+		display.addListener(SWT.OpenDocument, e -> {
+			System.out.println("OpenDocument with: " + e.text);
+			browser.setText("OpenDocument was called with arg: " + e.text);
+		});
+
+		shell.open();
+		while (!shell.isDisposed()) {
+			if (!display.readAndDispatch())
+				display.sleep();
+		}
+		display.dispose();
+	}
+}