Intercepting Links

When a web application runs inside an Eclipse workbench it would be nice if links in the application could do interesting workbench actions.  Opening a new view or a wizard, for example.  It would be nicer still, if the web application’s HTML or JavaScript could remain unchanged.

Luckily intercepting links is easy to do with:

org.eclipse.swt.browser.Browser.addLocationListener(LocationListener listener)

Here is code from a ViewPart implementation that creates an instance of org.eclipse.swt.browser.Browser and adds a new LocationListener to it:


    public void createPartControl(Composite parent) {
        browser = new Browser(parent, SWT.NONE);
        browser.setUrl(Perspective.gmailURL);

        // Hooks the link intercept code
        browser.addLocationListener(new LinkInterceptListener());
    }

The implementer must also provide an implementation for the interface:

org.eclipse.swt.browser.LocationListener

LocationListener specifies two methods:

  1. changing(LocationEvent event)
  2. changed(LocationEvent event)

changing() is called before the browser widget opens a new location and provides a mechanism for preventing the browser from doing so.  changed() is called after the browser has opened the location.

A sample implementation of a LocationListener might look like:

	/**
	 * Implement a LocationListener to intercept links and decide what to do.
	 */
	private class LinkInterceptListener implements LocationListener {
		// method called when the user clicks a link but before the link is opened.
		public void changing(LocationEvent event) {
			try {
				// Call user code to process link as desired and return
				// true if the link should be opened in place.
				boolean shouldOpenLinkInPlace = !openView(event.location);

				// Setting event.doit to false prevents the link from opening in place
				event.doit = shouldOpenLinkInPlace;
			} catch (PartInitException e) {
				e.printStackTrace();
			}
		}

		// method called after the link has been opened in place.
		public void changed(LocationEvent event) {
			// Not used in this example
		}
	}

Line 10 gets the URL the browser is attempting to open and calls the implementer’s method to determine what to do based on the link.  Line 13 sets the event field that controls whether the browser opens the location in place or not.  The implementer could decide to open their own view and let the browser open the link in place, but I suspect this is not typical.

It is also useful to remember that the LocationListener is invoked each time the browser’s location changes.  This includes when content is first loaded by a call to browser.setURL(), redirects in a loaded page and the user clicking a link.

And finally, a simple example of inspecting the links and taking an apporpriate action.  You will notice that this method is returning true when it intercepts a link and opens a workbench element.  The caller above is setting event.doit to the negation of the return value.  That is, the browser should open the link in place if the link was NOT intercepted.

	private boolean openView(String location) throws PartInitException {
		// Open a view
		if (location.equals("http://www.google.com/intl/en_CA/mobile/mail/#utm_source=en_CA-cpp-g4mc-gmhp&utm_medium=cpp&utm_campaign=en_CA")) {
			IViewPart newView = getViewSite().getPage().showView("url.link.1");
			((LinkView) newView).setURL(location);

			return false;
		// Open a wizard
		} else if (location.contains("/accounts/recovery")) {
			BasicNewFileResourceWizard wizard = new BasicNewFileResourceWizard();
			wizard.init(getSite().getWorkbenchWindow().getWorkbench(), new StructuredSelection());
			WizardDialog dialog = new WizardDialog(getSite().getShell(), wizard);
			dialog.create();
			dialog.open();

			return false;
		}

		// Do not intercept link.  Allow browser widget to open link in place
		return true;
	}

In a real implementation there would likely be a better mapping strategy than an if-else statement.

Runnable Example

There is a working example of this code can be checked out from CVS.  This page has the details.the following location:

Discussion

Going back to my first post, this is where the feedback is needed.

To me, this appears to be all that is needed for intercepting web application links in a meaningful way.  But am I right?  Without specific domain knowledge about the types of web applications the community is trying to embed in the Eclipse workbench I have no way of knowing if this simple approach is sufficient or if more is required.  Sometimes less is more, sometimes less is just … less.

For example, I made the assumption that it is beneficial if the web application does not change.  Since the implementer is creating a new workbench view, it was natural to encapsulate all the link mapping in the workbench code.

Does anybody want to make an argument for a contribution mechanism whereby a web application can make API calls to register interceptable links?  My gut tells me no, but perhaps your experience tells you yes.

About these ads
This entry was posted in Web UI/Workbench Integration. Bookmark the permalink.

2 Responses to Intercepting Links

  1. LocationListener has been available since 3.0. In actual use you often deal with Authentication to access pages and also need AuthenticationListener. This is available since 3.5.

    • Dean says:

      Ah yes, there is certainly “no API like old API” :-)

      You are right, AuthenticationListener is very handy when a web application running within an Eclipse workbench attempts to open a link to a web resource that will issue an authentication challenge. It seems different enough from this example to want its own post. For those that are interested there is an excellent SWT snippet demonstrating the use of AuthenticationListener.

Comments are closed.