/* @VaadinApache2LicenseForJavaFiles@ */ /* * Copyright 2008 Google Inc. * * 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. */ package com.vaadin.terminal.gwt.client; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.impl.HistoryImpl; /** * A slightly modified version of GWT's HistoryImplIE6 to bypass bug #2931. Also * combined with HistoryImplFrame. * * This class should be removed if GWT issue 3890 gets resolved. (Also remember * to removed deferred binding rule from .gwt.xml file). */ public class HistoryImplIEVaadin extends HistoryImpl { private static native Element findHistoryFrame() /*-{ return $doc.getElementById('__gwt_historyFrame'); }-*/; private static native Element getTokenElement(Element historyFrame) /*-{ // Initialize the history iframe. If '__gwt_historyToken' already exists, then // we're probably backing into the app, so _don't_ set the iframe's location. if (historyFrame.contentWindow) { var doc = historyFrame.contentWindow.document; return doc.getElementById('__gwt_historyToken'); } }-*/; protected Element historyFrame; @Override protected final void nativeUpdate(String historyToken) { /* * Must update the location hash since it isn't already correct. */ updateHash(historyToken); navigateFrame(historyToken); } @Override protected final void nativeUpdateOnEvent(String historyToken) { updateHash(historyToken); } /** * Sanitizes an untrusted string to be used in an HTML context. NOTE: This * method of escaping strings should only be used on Internet Explorer. * * @param maybeHtml * untrusted string that may contain html * @return sanitized string */ private static String escapeHtml(String maybeHtml) { final Element div = DOM.createDiv(); DOM.setInnerText(div, maybeHtml); return DOM.getInnerHTML(div); } /** * For IE6, reading from $wnd.location.hash drops part of the fragment if * the fragment contains a '?'. To avoid this bug, we use location.href * instead. */ private static native String getLocationHash() /*-{ var href = $wnd.location.href; var hashLoc = href.lastIndexOf("#"); return (hashLoc > 0) ? href.substring(hashLoc) : ""; }-*/; @Override public boolean init() { historyFrame = findHistoryFrame(); if (historyFrame == null) { return false; } initHistoryToken(); // Initialize the history iframe. If a token element already exists, // then // we're probably backing into the app, so _don't_ create a new item. Element tokenElement = getTokenElement(historyFrame); if (tokenElement != null) { setToken(getTokenElementContent(tokenElement)); } else { navigateFrame(getToken()); } injectGlobalHandler(); initUrlCheckTimer(); return true; } protected native String getTokenElementContent(Element tokenElement) /*-{ return tokenElement.innerText; }-*/; protected native void initHistoryToken() /*-{ // Assume an empty token. var token = ''; // Get the initial token from the url's hash component. // $entry not needed as function is not exported var hash = @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::getLocationHash()(); if (hash.length > 0) { try { token = this.@com.google.gwt.user.client.impl.HistoryImpl::decodeFragment(Ljava/lang/String;)(hash.substring(1)); } catch (e) { // Clear the bad hash (this can't have been a valid token). $wnd.location.hash = ''; } } @com.google.gwt.user.client.impl.HistoryImpl::setToken(Ljava/lang/String;)(token); }-*/; protected native void injectGlobalHandler() /*-{ var historyImplRef = this; $wnd.__gwt_onHistoryLoad = $entry(function(token) { historyImplRef.@com.google.gwt.user.client.impl.HistoryImpl::newItemOnEvent(Ljava/lang/String;)(token); }); }-*/; protected native void navigateFrame(String token) /*-{ // $entry not needed as function is not exported var escaped = @com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::escapeHtml(Ljava/lang/String;)(token); var doc = this.@com.vaadin.terminal.gwt.client.HistoryImplIEVaadin::historyFrame.contentWindow.document; doc.open(); doc.write('