Fixes Safari history implementation to correctly decode the URL hash.

Issue: 1621
Patch by: colesbury, jgw
Review by: rdayal


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1900 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 e05c7e9..d30582d 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplSafari.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * 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
@@ -18,6 +18,9 @@
 /**
  * Safari implementation of
  * {@link com.google.gwt.user.client.impl.HistoryImplStandard}.
+ * 
+ * This implementation works on both Safari 2 and 3, by detecting the version
+ * and reverting to a stub implementation for Safari 2.
  */
 class HistoryImplSafari extends HistoryImplStandard {
 
@@ -63,13 +66,26 @@
     super.newItem(historyToken);
   }
 
+  protected native String decode(String historyToken) /*-{
+    try {
+      // Unlike most other browsers, Safari does not unescape location.hash.
+      return decodeURIComponent(historyToken);
+    } catch (e) {
+      // This is very unlikely to be malformed, since it comes directly from
+      // location.hash.
+      return "";
+    }
+  }-*/;
+
   private native void initImpl() /*-{
     $wnd.__gwt_historyToken = '';
 
     // Get the initial token from the url's hash component.
     var hash = $wnd.location.hash;
-    if (hash.length > 0)
-      $wnd.__gwt_historyToken = decodeURIComponent(hash.substring(1));
+    if (hash.length > 0) {
+      $wnd.__gwt_historyToken =
+        this.@com.google.gwt.user.client.impl.HistoryImplStandard::decode(Ljava/lang/String;)(hash.substring(1));
+    }
 
     @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)($wnd.__gwt_historyToken);
   }-*/;
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java b/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
index 963a4ba..bac0dff 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007 Google Inc.
+ * 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
@@ -30,10 +30,14 @@
       $wnd.__gwt_historyToken = hash.substring(1);
 
     // Create the timer that checks the browser's url hash every 1/4 s.
+    var historyImpl = this;
     $wnd.__checkHistory = function() {
       var token = '', hash = $wnd.location.hash;
-      if (hash.length > 0)
-        token = hash.substring(1);
+      if (hash.length > 0) {
+        // Not all browsers decode location.hash the same way, so the
+        // implementation needs an opportunity to handle decoding.
+        token = historyImpl.@com.google.gwt.user.client.impl.HistoryImplStandard::decode(Ljava/lang/String;)(hash.substring(1));
+      }
 
       if (token != $wnd.__gwt_historyToken) {
         $wnd.__gwt_historyToken = token;
@@ -56,4 +60,8 @@
     }
     $wnd.location.hash = encodeURIComponent(historyToken);
   }-*/;
+
+  protected String decode(String historyToken) {
+    return historyToken;
+  }
 }