Change to make HistoryImplIE6 no longer need to actually load history.html from the server, saving round trips.  Also includes a refactoring of HistoryImplIE6/Saf.

Review by: jgw


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1048 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/core/public/history.html b/user/src/com/google/gwt/core/public/history.html
index cefb9ac..4ba2dce 100644
--- a/user/src/com/google/gwt/core/public/history.html
+++ b/user/src/com/google/gwt/core/public/history.html
@@ -7,14 +7,15 @@
   if (search.length > 0)
     historyToken = search.substring(1);
 
-  document.getElementById('__historyToken').value = historyToken;
-  if (parent.__onHistoryChanged)
-    parent.__onHistoryChanged(historyToken);
+  document.getElementById('__gwt_historyToken').value = historyToken;
+  if (parent.__gwt_onHistoryLoad) {
+    parent.__gwt_onHistoryLoad(historyToken);
+  }
 }
 </script></head>
 <body onload='hst()'>
 
-<input type='text' id='__historyToken'>
+<input type='text' id='__gwt_historyToken'>
 
 </body>
 </html>
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
index 59ea0b1..7feb616 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImpl.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -27,9 +27,15 @@
     History.onHistoryChanged(historyToken);
   }
 
-  public abstract String getToken();
+  public native String getToken() /*-{
+    return $wnd.__gwt_historyToken;
+  }-*/;
 
   public abstract boolean init();
 
   public abstract void newItem(String historyToken);
+
+  protected native void setToken(String token) /*-{
+    $wnd.__gwt_historyToken = token;
+  }-*/;
 }
diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java b/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
new file mode 100644
index 0000000..e7847f5
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplFrame.java
@@ -0,0 +1,83 @@
+/*

+ * Copyright 2007 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.google.gwt.user.client.impl;

+

+import com.google.gwt.user.client.Element;

+

+/**

+ * An IFRAME implementation of

+ * {@link com.google.gwt.user.client.impl.HistoryImpl}.

+ */

+abstract class HistoryImplFrame extends HistoryImpl {

+

+  private static native Element findHistoryFrame() /*-{

+    var historyFrame = $doc.getElementById('__gwt_historyFrame');

+    return historyFrame || null;

+  }-*/;

+

+  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.

+    var tokenElement = null;

+    if (historyFrame.contentWindow) {

+      var doc = historyFrame.contentWindow.document;

+      tokenElement = doc.getElementById('__gwt_historyToken') || null;

+    }

+    return tokenElement;

+  }-*/;

+

+  private static native void initHistoryToken() /*-{

+    // Get the initial token from the url's hash component.

+    var hash = $wnd.location.hash;

+    if (hash.length > 0)

+      $wnd.__gwt_historyToken = hash.substring(1);

+    else

+      $wnd.__gwt_historyToken = '';

+  }-*/;

+  

+  private Element historyFrame;

+

+  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 {

+      newItem(getToken());

+    }

+

+    injectGlobalHandler();

+    return true;

+  }

+

+  public void newItem(String historyToken) {

+    newItemImpl(historyFrame, historyToken);

+  }

+

+  protected abstract String getTokenElementContent(Element tokenElement);

+

+  protected abstract void injectGlobalHandler();

+

+  protected abstract void newItemImpl(Element historyFrame2, String historyToken);

+}

diff --git a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
index f569314..ded227a 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplIE6.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,55 +15,15 @@
  */
 package com.google.gwt.user.client.impl;
 
+import com.google.gwt.user.client.Element;
+
 /**
  * Internet Explorer 6 implementation of
- * {@link com.google.gwt.user.client.impl.HistoryImpl}.
+ * {@link com.google.gwt.user.client.impl.HistoryImplFrame}.
  */
-class HistoryImplIE6 extends HistoryImpl {
+class HistoryImplIE6 extends HistoryImplFrame {
 
-  public native String getToken() /*-{
-    return $wnd.__historyToken;
-  }-*/;
-
-  public native boolean init() /*-{
-    // Check for existence of the history frame.
-    var historyFrame = $doc.getElementById('__gwt_historyFrame');
-    if (!historyFrame)
-      return false;
-
-    // Get the initial token from the url's hash component.
-    var hash = $wnd.location.hash;
-    if (hash.length > 0)
-      $wnd.__historyToken = hash.substring(1);
-    else
-      $wnd.__historyToken = '';
-
-    // Initialize the history iframe.  If '__historyToken' already exists, then
-    // we're probably backing into the app, so _don't_ set the iframe's location.
-    var tokenElement = null;
-    if (historyFrame.contentWindow) {
-      var doc = historyFrame.contentWindow.document;
-      tokenElement = doc ? doc.getElementById('__historyToken') : null;
-    }
-
-    if (tokenElement)
-      $wnd.__historyToken = tokenElement.value;
-    else
-      historyFrame.src = 'history.html?' + $wnd.__historyToken;
-
-    // Expose the '__onHistoryChanged' function, which will be called by
-    // the history frame when it loads.
-    $wnd.__onHistoryChanged = function(token) {
-      // Change the URL and notify the application that its history frame
-      // is changing.  Note that setting location.hash does _not_ add a history
-      // frame on IE, so we don't have to do a 'location.replace()'.
-      if (token != $wnd.__historyToken) {
-        $wnd.__historyToken = token;
-        $wnd.location.hash = encodeURIComponent(token);
-        @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
-      }
-    };
-
+  private static native void initUrlCheckTimer() /*-{
     // This is the URL check timer.  It detects when an unexpected change
     // occurs in the document's URL (e.g. when the user enters one manually
     // or selects a 'favorite', but only the #hash part changes).  When this
@@ -74,21 +34,43 @@
       var hash = $wnd.location.hash;
       if (hash.length > 0) {
         var token = hash.substring(1);
-        if ($wnd.__historyToken && (token != $wnd.__historyToken))
+        if ($wnd.__gwt_historyToken && (token != $wnd.__gwt_historyToken))
           $wnd.location.reload();
       }
       $wnd.setTimeout(urlChecker, 250);
     };
     urlChecker();
-
-    return true;
   }-*/;
 
-  public native void newItem(String historyToken) /*-{
-    var iframe = $doc.getElementById('__gwt_historyFrame');
-    if (historyToken == null) {
-      historyToken = "";
+  public boolean init() {
+    if (!super.init()) {
+      return false;
     }
-    iframe.contentWindow.location.href = 'history.html?' + historyToken;
+    initUrlCheckTimer();
+    return true;
+  }
+
+  protected native String getTokenElementContent(Element tokenElement) /*-{
+    return tokenElement.innerText;
+  }-*/;
+
+  protected native void injectGlobalHandler() /*-{
+    $wnd.__gwt_onHistoryLoad = function(token) {
+      // Change the URL and notify the application that its history frame
+      // is changing.
+      if (token != $wnd.__gwt_historyToken) {
+        $wnd.__gwt_historyToken = token;
+        $wnd.location.hash = encodeURIComponent(token);
+        @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
+      }
+    };
+  }-*/;
+  
+  protected native void newItemImpl(Element historyFrame, String historyToken) /*-{
+    historyToken = historyToken || "";
+    var doc = historyFrame.contentWindow.document;
+    doc.open();
+    doc.write('<html><body onload="if(parent.__gwt_onHistoryLoad)parent.__gwt_onHistoryLoad(__gwt_historyToken.innerText)"><div id="__gwt_historyToken">' + historyToken + '</div></body></html>');
+    doc.close();
   }-*/;
 }
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 6879013..9f8e63f 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 2006 Google Inc.
+ * Copyright 2007 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
@@ -15,70 +15,36 @@
  */
 package com.google.gwt.user.client.impl;
 
+import com.google.gwt.user.client.Element;
+
 /**
- * Safari implementation of {@link com.google.gwt.user.client.impl.HistoryImpl}.
+ * Safari implementation of
+ * {@link com.google.gwt.user.client.impl.HistoryImplFrame}.
  */
-class HistoryImplSafari extends HistoryImpl {
+class HistoryImplSafari extends HistoryImplFrame {
 
-  public native String getToken() /*-{
-    return $wnd.__historyToken;
+  protected native String getTokenElementContent(Element tokenElement) /*-{
+    return tokenElement.value;
   }-*/;
-
-  public native boolean init() /*-{
-    // Check for existence of the history frame.
-    var historyFrame = $doc.getElementById('__gwt_historyFrame');
-    if (!historyFrame)
-      return false;
-
-    // Get the initial token from the url's hash component.
-    var hash = $wnd.location.hash;
-    if (hash.length > 0)
-      $wnd.__historyToken = hash.substring(1);
-    else
-      $wnd.__historyToken = '';
-
-    // Initialize the history iframe.  If '__historyToken' already exists, then
-    // we're probably backing into the app, so _don't_ set the iframe's location.
-    var tokenElement = null;
-    if (historyFrame.contentWindow) {
-      var doc = historyFrame.contentWindow.document;
-      tokenElement = doc ? doc.getElementById('__historyToken') : null;
-    }
-
-    if (tokenElement)
-      $wnd.__historyToken = tokenElement.value;
-    else
-      historyFrame.src = 'history.html?' + encodeURIComponent($wnd.__historyToken);
-
-    // Expose the '__onHistoryChanged' function, which will be called by
-    // the history frame when it loads.
-    $wnd.__onHistoryChanged = function(token) {
+  
+  protected native void injectGlobalHandler() /*-{
+    $wnd.__gwt_onHistoryLoad = function(token) {
       // Change the URL and notify the application that its history frame
       // is changing.
-      if (token != $wnd.__historyToken) {
-        $wnd.__historyToken = token;
-
+      if (token != $wnd.__gwt_historyToken) {
+        $wnd.__gwt_historyToken = token;
         // TODO(jgw): fix the bookmark update, if possible.  The following code
         // screws up the browser by (a) making it pretend that it's loading the
         // page indefinitely, and (b) causing all text to disappear (!)
-//        var base = $wnd.location.href;
-//        var hashIdx = base.indexOf('#');
-//        if (hashIdx != -1)
-//          base = base.substring(0, hashIdx);
-//        $wnd.location.replace(base + '#' + token);
-
+//        $wnd.location.hash = encodeURIComponent(token);
         @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
       }
     };
-
-    return true;
+  }-*/;
+  
+  protected native void newItemImpl(Element historyFrame, String historyToken) /*-{
+    historyToken = historyToken || "";
+    historyFrame.contentWindow.location.href = 'history.html?' + historyToken;
   }-*/;
 
-  public native void newItem(String historyToken) /*-{
-    var iframe = $doc.getElementById('__gwt_historyFrame');
-    if (historyToken == null) {
-      historyToken = "";
-    }
-    iframe.contentWindow.location.href = 'history.html?' + 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 0a61d7f..f4ef953 100644
--- a/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
+++ b/user/src/com/google/gwt/user/client/impl/HistoryImplStandard.java
@@ -20,17 +20,13 @@
  */
 class HistoryImplStandard extends HistoryImpl {
 
-  public native String getToken() /*-{
-    return $wnd.__historyToken;
-  }-*/;
-
   public native boolean init() /*-{
-    $wnd.__historyToken = '';
+    $wnd.__gwt_historyToken = '';
 
     // Get the initial token from the url's hash component.
     var hash = $wnd.location.hash;
     if (hash.length > 0)
-      $wnd.__historyToken = hash.substring(1);
+      $wnd.__gwt_historyToken = hash.substring(1);
 
     // Create the timer that checks the browser's url hash every 1/4 s.
     $wnd.__checkHistory = function() {
@@ -38,8 +34,8 @@
       if (hash.length > 0)
         token = hash.substring(1);
 
-      if (token != $wnd.__historyToken) {
-        $wnd.__historyToken = token;
+      if (token != $wnd.__gwt_historyToken) {
+        $wnd.__gwt_historyToken = token;
         @com.google.gwt.user.client.impl.HistoryImpl::onHistoryChanged(Ljava/lang/String;)(token);
       }