package ch.unifr.pai.twice.widgets.mpproxy.client; /* * Copyright 2013 Oliver Schmid * 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. */ import java.util.ArrayList; import java.util.List; import ch.unifr.pai.twice.multipointer.client.widgets.MultiFocusTextBox; import ch.unifr.pai.twice.widgets.mpproxy.client.navig.Navigation; import ch.unifr.pai.twice.widgets.mpproxy.shared.Rewriter; import ch.unifr.pai.twice.widgets.mpproxy.shared.URLParser; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.AnchorElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.EventTarget; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.storage.client.Storage; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.Event.NativePreviewHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; /** * Standard (non-multi pointer proxy) * * @author Oliver Schmid * */ public class ProxyBody { private static String[] attributesToManipulate = { "src", "href", "action" }; private final ScreenShotDistributor screenShot = new ScreenShotDistributor(); private static Navigation navigation = GWT.create(Navigation.class); protected static List<MultiFocusTextBox> replacements = new ArrayList<MultiFocusTextBox>(); /** * Register required listeners and set up the basic objects */ public void initialize() { Event.addNativePreviewHandler(new NativePreviewHandler() { /** * Rewrites the URLs on mouse down if somebody clicks on an anchor element * * @see com.google.gwt.user.client.Event.NativePreviewHandler#onPreviewNativeEvent(com.google.gwt.user.client.Event.NativePreviewEvent) */ @Override public void onPreviewNativeEvent(NativePreviewEvent event) { if (event.getTypeInt() == Event.ONMOUSEDOWN) { EventTarget t = event.getNativeEvent().getEventTarget(); Element e = (Element) Element.as(t); if (e != null && e.getTagName().equalsIgnoreCase("a")) rewriteUrls(e); } } }); Storage s = Storage.getSessionStorageIfSupported(); if (s != null) { RootPanel.get().add(new Label("Multicursor: " + s.getItem("ch.unifr.pai.mice.deviceType"))); } publishInterfaces(); rewriteUrls((Element) Document.get().getDocumentElement()); addDomChangeEvents(); // screenShot.start(); if (!isParentFrame()) { Element e = DOM.getElementById("miceNavigation"); if (e != null) e.removeFromParent(); } } /** * Client side logic to rewrite a given URL * * @param e */ private static void rewriteUrls(Element e) { URLParser parser = new URLParser(Window.Location.getHref(), Rewriter.getServletPath(Window.Location.getHref())); if (parser.getServletPath() != null && !parser.getServletPath().isEmpty() && parser.getProxyBasePath() != null && !parser.getProxyBasePath().isEmpty()) rewriteUrl(e, parser.getServletPath(), parser.getProxyBasePath()); } /** * Client side logic to rewrite a given URL * * @param element * @param servletPath * @param proxyPath */ public static void rewriteUrl(com.google.gwt.dom.client.Element element, String servletPath, String proxyPath) { NodeList<Node> nodes = element.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node n = nodes.getItem(i); if (com.google.gwt.dom.client.Element.is(n)) { com.google.gwt.dom.client.Element e = com.google.gwt.dom.client.Element.as(n); if (e != null && e.getTagName() != null && e.getTagName().equalsIgnoreCase("a")) { AnchorElement anchor = AnchorElement.as(e); if (anchor.getHref() != null && !anchor.getHref().isEmpty()) anchor.removeAttribute("onmousedown"); } for (String att : attributesToManipulate) { String value = e.getAttribute(att); if (value != null && !value.startsWith(servletPath) && value.matches("((http)|/).*")) { String transformed = Rewriter.translateCleanUrl(value, servletPath, proxyPath); if (!transformed.equals(value)) e.setAttribute(att, transformed); } } rewriteUrl(e, servletPath, proxyPath); } } } /** * If something in the DOM has changed, call the different handlers and replace the standard widgets * * @param evt */ public static void onDomChanged(Event evt) { if (Element.is(evt.getEventTarget())) { Element e = (Element) Element.as(evt.getEventTarget()); rewriteUrls(e); for (DOMChangeHandler h : domChangeHandler) h.onDomChanged(evt); for (MultiFocusTextBox b : replacements) b.refreshDisplay(); } } private static List<DOMChangeHandler> domChangeHandler = new ArrayList<DOMChangeHandler>(); /** * Add a dom change handler * * @param handler */ public static void addDOMChangeHandler(DOMChangeHandler handler) { domChangeHandler.add(handler); } /** * Add a listener for dom change events */ private native void addDomChangeEvents() /*-{ $wnd.document.addEventListener('DOMSubtreeModified', @ch.unifr.pai.twice.widgets.mpproxy.client.ProxyBody::onDomChanged(Lcom/google/gwt/user/client/Event;), false); }-*/; /** * @return true if this is the parent frame */ private native boolean isParentFrame() /*-{ return $wnd.location == $wnd.parent.location; }-*/; /** * Set up the JS-callable signature as a global JS function. * */ private native void publishInterfaces() /*-{ $wnd.backInHistory = @com.google.gwt.user.client.History::back(); $wnd.forwardInHistory = @com.google.gwt.user.client.History::forward(); $wnd.reloadFrame = @com.google.gwt.user.client.Window.Location::reload(); }-*/; }