/******************************************************************************* * Copyright (c) 2013 Rene Schneider, GEBIT Solutions GmbH and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html *******************************************************************************/ package de.gebit.integrity.ui; import java.lang.reflect.Field; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.browser.LocationEvent; import org.eclipse.swt.browser.LocationListener; import org.eclipse.ui.IPageListener; import org.eclipse.ui.IPartListener; import org.eclipse.ui.IStartup; import org.eclipse.ui.IWindowListener; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.internal.browser.BrowserViewer; import org.eclipse.ui.internal.browser.WebBrowserEditor; import org.eclipse.ui.internal.browser.WebBrowserView; import com.google.inject.Inject; import de.gebit.integrity.ui.linking.IntegrityURLResolver; /** * This startup code is run when the Integrity UI bundle is started. * * @author Rene Schneider - initial API and implementation * */ @SuppressWarnings("restriction") public class IntegrityUIStartup implements IStartup { /** * The {@link IntegrityURLResolver}. */ @Inject private IntegrityURLResolver urlResolver; @Override public void earlyStartup() { registerBrowserLocationListener(); } /** * Registers a location listener on every browser created. This is a rather ugly way to do it, but unfortunately I * don't know about any better way, maybe not involving accessing private attributes via reflection. This * implementation was basically taken from a <a * href="http://stackoverflow.com/questions/10391090/how-to-hook-into-the-internal-eclipse-browser">StackOverflow * thread</a>. */ private void registerBrowserLocationListener() { final IPartListener partListener = new IPartListener() { @Override public void partOpened(IWorkbenchPart aPart) { if (aPart instanceof WebBrowserEditor) { WebBrowserEditor tempEditor = (WebBrowserEditor) aPart; try { Field tempWebBrowserField = tempEditor.getClass().getDeclaredField("webBrowser"); tempWebBrowserField.setAccessible(true); BrowserViewer tempViewer = (BrowserViewer) tempWebBrowserField.get(tempEditor); Field tempBrowserField = tempViewer.getClass().getDeclaredField("browser"); tempBrowserField.setAccessible(true); Browser tempBrowser = (Browser) tempBrowserField.get(tempViewer); tempBrowser.addLocationListener(new IntegrityURLLocationListener()); } catch (SecurityException exc) { exc.printStackTrace(); } catch (NoSuchFieldException exc) { exc.printStackTrace(); } catch (IllegalArgumentException exc) { exc.printStackTrace(); } catch (IllegalAccessException exc) { exc.printStackTrace(); } } else if (aPart instanceof WebBrowserView) { WebBrowserView tempView = (WebBrowserView) aPart; try { Field tempViewerField = tempView.getClass().getDeclaredField("viewer"); tempViewerField.setAccessible(true); BrowserViewer tempViewer = (BrowserViewer) tempViewerField.get(tempView); Field tempBrowserField = tempViewer.getClass().getDeclaredField("browser"); tempBrowserField.setAccessible(true); Browser tempBrowser = (Browser) tempBrowserField.get(tempViewer); tempBrowser.addLocationListener(new IntegrityURLLocationListener()); } catch (SecurityException exc) { exc.printStackTrace(); } catch (NoSuchFieldException exc) { exc.printStackTrace(); } catch (IllegalArgumentException exc) { exc.printStackTrace(); } catch (IllegalAccessException exc) { exc.printStackTrace(); } } } @Override public void partActivated(IWorkbenchPart aPart) { // nothing to do here } @Override public void partBroughtToTop(IWorkbenchPart aPart) { // nothing to do here } @Override public void partClosed(IWorkbenchPart aPart) { // nothing to do here } @Override public void partDeactivated(IWorkbenchPart aPart) { // nothing to do here } }; final IPageListener pageListener = new IPageListener() { @Override public void pageOpened(IWorkbenchPage aPart) { aPart.addPartListener(partListener); } @Override public void pageActivated(IWorkbenchPage aPart) { // nothing to do here } @Override public void pageClosed(IWorkbenchPage aPart) { // nothing to do here } }; final IWindowListener windowListener = new IWindowListener() { @Override public void windowOpened(IWorkbenchWindow aWindow) { aWindow.addPageListener(pageListener); } @Override public void windowActivated(IWorkbenchWindow aWindow) { // nothing to do here } @Override public void windowDeactivated(IWorkbenchWindow aWindow) { // nothing to do here } @Override public void windowClosed(IWorkbenchWindow aWindow) { // nothing to do here } }; IWorkbenchWindow tempActiveWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (tempActiveWindow != null) { IWorkbenchPage tempActivePage = tempActiveWindow.getActivePage(); if (tempActivePage != null) { tempActivePage.addPartListener(partListener); } else { tempActiveWindow.addPageListener(pageListener); } } else { for (IWorkbenchWindow tempWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) { for (IWorkbenchPage tempPage : tempWindow.getPages()) { tempPage.addPartListener(partListener); } tempWindow.addPageListener(pageListener); } PlatformUI.getWorkbench().addWindowListener(windowListener); } } /** * This location listener intercepts any location changes and sends URLs to the Integrity URL parser. * * * @author Rene Schneider - initial API and implementation * */ class IntegrityURLLocationListener implements LocationListener { @Override public void changed(LocationEvent anEvent) { return; } @Override public void changing(LocationEvent anEvent) { if (urlResolver.parseURL(anEvent.location)) { anEvent.doit = false; } } } }