Fixes Safari history issues stemming from setting location.hash to the empty
string.
Patch by: jgw
Review by: jat
Issues: 2905, 2909
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@3681 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
index a37a6c2..2f72256 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
@@ -59,9 +59,9 @@
@Override
protected void nativeUpdate(String historyToken) {
if (isOldSafari) {
- nativeUpdateImpl(historyToken);
+ oldNativeUpdate(historyToken);
} else {
- super.nativeUpdate(historyToken);
+ newNativeUpdate(historyToken);
}
}
@@ -79,7 +79,16 @@
@com.google.gwt.user.client.impl.HistoryImpl::fireHistoryChangedImpl(Ljava/lang/String;)($wnd.__gwt_historyToken);
}-*/;
- private native void nativeUpdateImpl(String historyToken) /*-{
+ private native void newNativeUpdate(String historyToken) /*-{
+ // Safari gets into a weird state (issue 2905) when setting the hash
+ // component of the url to an empty string, but works fine as long as you
+ // at least add a '#' to the end of the url. So we get around this by
+ // recreating the url, rather than just setting location.hash.
+ $wnd.location = $wnd.location.href.split('#')[0] + '#' +
+ this.@com.google.gwt.user.client.impl.HistoryImpl::encodeFragment(Ljava/lang/String;)(historyToken);
+ }-*/;
+
+ private native void oldNativeUpdate(String historyToken) /*-{
// Use a bizarre meta refresh trick to update the url's hash, without
// creating a history entry.
var meta = $doc.createElement('meta');
diff --git a/user/test/com/google/gwt/user/client/ui/HistoryTest.java b/user/test/com/google/gwt/user/client/ui/HistoryTest.java
index aff7103..cdafbe8 100644
--- a/user/test/com/google/gwt/user/client/ui/HistoryTest.java
+++ b/user/test/com/google/gwt/user/client/ui/HistoryTest.java
@@ -15,13 +15,15 @@
*/
package com.google.gwt.user.client.ui;
+import java.util.ArrayList;
+
+import com.google.gwt.dom.client.Document;
+import com.google.gwt.dom.client.Element;
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.HistoryListener;
import com.google.gwt.user.client.Timer;
-import java.util.ArrayList;
-
/**
* Tests for the history system.
*
@@ -277,6 +279,33 @@
History.newItem(token);
}
+ /**
+ * Test that using an empty history token works properly. There have been
+ * problems (see issue 2905) with this in the past on Safari.
+ */
+ public void testEmptyHistoryToken() {
+ final ArrayList<Object> counter = new ArrayList<Object>();
+
+ addHistoryListenerImpl(new HistoryListener() {
+ public void onHistoryChanged(String historyToken) {
+ counter.add(new Object());
+ assertFalse("Browser is borked by empty history token", isBorked());
+ }
+ });
+
+ History.newItem("x");
+ History.newItem("");
+
+ assertEquals("Expected two history events", 2, counter.size());
+ }
+
+ // Used by testEmptyHistoryToken() to catch a bizarre failure mode on Safari.
+ private static boolean isBorked() {
+ Element e = Document.get().createDivElement();
+ e.setInnerHTML("string");
+ return e.getInnerHTML().length() == 0;
+ }
+
@Override
protected void gwtTearDown() throws Exception {
if (historyListener != null) {