[562040] Provide support for donation from within the IDE

Open links that open a new tab/window in the external browser.

https://bugs.eclipse.org/bugs/show_bug.cgi?id=562040
diff --git a/plugins/org.eclipse.oomph.setup.editor/src/org/eclipse/oomph/setup/presentation/handlers/DonateHandler.java b/plugins/org.eclipse.oomph.setup.editor/src/org/eclipse/oomph/setup/presentation/handlers/DonateHandler.java
index f40cabf..c628d43 100644
--- a/plugins/org.eclipse.oomph.setup.editor/src/org/eclipse/oomph/setup/presentation/handlers/DonateHandler.java
+++ b/plugins/org.eclipse.oomph.setup.editor/src/org/eclipse/oomph/setup/presentation/handlers/DonateHandler.java
@@ -12,12 +12,22 @@
 
 import org.eclipse.oomph.setup.presentation.SetupEditorPlugin;
 import org.eclipse.oomph.setup.ui.SetupPropertyTester;
+import org.eclipse.oomph.ui.UIUtil;
 import org.eclipse.oomph.util.PropertiesUtil;
+import org.eclipse.oomph.util.ReflectUtil;
 
 import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.swt.browser.Browser;
+import org.eclipse.swt.browser.LocationAdapter;
+import org.eclipse.swt.browser.LocationEvent;
+import org.eclipse.swt.browser.OpenWindowListener;
+import org.eclipse.swt.browser.WindowEvent;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
 import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.browser.IWebBrowser;
 import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
@@ -37,10 +47,10 @@
 
   public Object execute(ExecutionEvent event) throws ExecutionException
   {
-    IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
+    final IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport();
     try
     {
-      String donating = SetupPropertyTester.getDonating();
+      final String donating = SetupPropertyTester.getDonating();
       int style = IWorkbenchBrowserSupport.AS_EDITOR;
       if ("true".equals(PropertiesUtil.getProperty("org.eclipse.oomph.setup.donate.navigation", "false"))) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
       {
@@ -54,6 +64,69 @@
 
       IWebBrowser browser = browserSupport.createBrowser(style, "donate", SetupEditorPlugin.INSTANCE.getString("_UI_Donate_label"), donating); //$NON-NLS-1$ //$NON-NLS-2$
       browser.openURL(new URL(donating));
+
+      // Look for the internal browser instance.
+      IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+      if (workbenchWindow != null)
+      {
+        IWorkbenchPage activePage = workbenchWindow.getActivePage();
+        if (activePage != null)
+        {
+          IWorkbenchPart activePart = activePage.getActivePart();
+          if (activePart != null)
+          {
+            try
+            {
+              // Extract the browser reflectively because it's all hidden implementation detail.
+              Object webBrowser = ReflectUtil.getValue("webBrowser", activePart); //$NON-NLS-1$
+              Browser newBrowser = ReflectUtil.getValue("browser", webBrowser); //$NON-NLS-1$
+
+              // Add a listener for when a new browser window is opened so that we can open an external browser.
+              newBrowser.addOpenWindowListener(new OpenWindowListener()
+              {
+                public void open(WindowEvent event)
+                {
+                  // Listen for the URL changing for this new browser.
+                  final Browser newBrowser = event.browser;
+                  newBrowser.addLocationListener(new LocationAdapter()
+                  {
+                    @Override
+                    public void changing(LocationEvent event)
+                    {
+                      event.doit = false;
+
+                      // Close this browser's shell.
+                      UIUtil.asyncExec(newBrowser, new Runnable()
+                      {
+                        public void run()
+                        {
+                          newBrowser.getShell().close();
+                        }
+                      });
+
+                      try
+                      {
+                        // Instead open the link in an external browser.
+                        IWebBrowser browser = browserSupport.createBrowser(IWorkbenchBrowserSupport.AS_EXTERNAL, "external_donate", //$NON-NLS-1$
+                            SetupEditorPlugin.INSTANCE.getString("_UI_Donate_label"), donating); //$NON-NLS-1$
+                        browser.openURL(new URL(event.location));
+                      }
+                      catch (Exception ex)
+                      {
+                        SetupEditorPlugin.INSTANCE.log(ex, IStatus.WARNING);
+                      }
+                    }
+                  });
+                }
+              });
+            }
+            catch (Exception ex)
+            {
+              // Ignore reflection exceptions.
+            }
+          }
+        }
+      }
     }
     catch (Exception ex)
     {