Bug 639771 - Port Bug 597315 [Frameset history does not work properly when restoring a tab] to SeaMonkey. r=Neil
authorMisak Khachatryan <misak.bugzilla@gmail.com>
Tue, 08 Mar 2011 17:41:40 +0400
changeset 7278 382b3365a2e9c19f9ac3227d04e0f43cc6c96ddd
parent 7277 75875cb17fb0a20caabb627fe743b211f8d43eaa
child 7279 6499341dae5e67ecaa141020850bc815ebe8777e
push idunknown
push userunknown
push dateunknown
reviewersNeil
bugs639771, 597315
Bug 639771 - Port Bug 597315 [Frameset history does not work properly when restoring a tab] to SeaMonkey. r=Neil
suite/common/src/nsSessionStore.js
suite/common/tests/browser/Makefile.in
suite/common/tests/browser/browser_597315.js
suite/common/tests/browser/browser_597315_a.html
suite/common/tests/browser/browser_597315_b.html
suite/common/tests/browser/browser_597315_c.html
suite/common/tests/browser/browser_597315_c1.html
suite/common/tests/browser/browser_597315_c2.html
suite/common/tests/browser/browser_597315_index.html
--- a/suite/common/src/nsSessionStore.js
+++ b/suite/common/src/nsSessionStore.js
@@ -1448,16 +1448,17 @@ SessionStoreService.prototype = {
     var cacheKey = aEntry.cacheKey;
     if (cacheKey && cacheKey instanceof Components.interfaces.nsISupportsPRUint32 &&
         cacheKey.data != 0) {
       // XXXbz would be better to have cache keys implement
       // nsISerializable or something.
       entry.cacheKey = cacheKey.data;
     }
     entry.ID = aEntry.ID;
+    entry.docshellID = aEntry.docshellID;
 
     if (aEntry.referrerURI)
       entry.referrer = aEntry.referrerURI.spec;
 
     if (aEntry.contentType)
       entry.contentType = aEntry.contentType;
 
     var x = {}, y = {};
@@ -2527,17 +2528,25 @@ SessionStoreService.prototype = {
       // restore those aspects of the currently active documents which are not
       // preserved in the plain history entries (mainly scroll state and text data)
       browser.__SS_restore_data = tabData.entries[activeIndex] || {};
       browser.__SS_restore_pageStyle = tabData.pageStyle || "";
       browser.__SS_restore_tab = aTab;
 
       didStartLoad = true;
       try {
-        browser.webNavigation.gotoIndex(activeIndex);
+        // In order to work around certain issues in session history, we need to
+        // force session history to update its internal index and call reload
+        // instead of gotoIndex. c.f. bug 597315
+        var sessionHistory = browser.webNavigation.sessionHistory;
+        // delete this after 2.0
+        sessionHistory.QueryInterface(Components.interfaces.nsISHistory_2_0_BRANCH);
+
+        sessionHistory.getEntryAtIndex(activeIndex, true);
+        sessionHistory.reloadCurrentEntry();
       }
       catch (ex) {
         // ignore page load errors
         aTab.removeAttribute("busy");
         didStartLoad = false;
       }
     }
 
@@ -2642,16 +2651,19 @@ SessionStoreService.prototype = {
       if (!id) {
         for (id = Date.now(); id in aIdMap.used; id++);
         aIdMap[aEntry.ID] = id;
         aIdMap.used[id] = true;
       }
       shEntry.ID = id;
     }
 
+    if (aEntry.docshellID)
+      shEntry.docshellID = aEntry.docshellID;
+
     if (aEntry.stateData) {
       shEntry.stateData = aEntry.stateData;
     }
 
     if (aEntry.scroll) {
       var scrollPos = (aEntry.scroll || "0,0").split(",");
       scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
       shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
--- a/suite/common/tests/browser/Makefile.in
+++ b/suite/common/tests/browser/Makefile.in
@@ -87,16 +87,23 @@ include $(topsrcdir)/config/rules.mk
 	browser_bug510890.js \
 	browser_514751.js \
 	browser_bug515006.js \
 	browser_522545.js \
 	browser_524745.js \
 	browser_526613.js \
 	browser_528776.js \
 	browser_586068-cascaded_restore.js \
+	browser_597315.js \
+	browser_597315_index.html \
+	browser_597315_a.html \
+	browser_597315_b.html \
+	browser_597315_c.html \
+	browser_597315_c1.html \
+	browser_597315_c2.html \
 	browser_607016.js \
 	browser_615394-SSWindowState_events.js \
 	browser_isempty.js \
 	browser_markPageAsFollowedLink.js \
 	framedPage.html \
 	frameLeft.html \
 	frameRight.html \
 	$(NULL)
new file mode 100644
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315.js
@@ -0,0 +1,100 @@
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (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.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is sessionstore test code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Paul O’Shannessy <paul@oshannessy.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+let ss = Components.classes["@mozilla.org/suite/sessionstore;1"]
+                     .getService(Components.interfaces.nsISessionStore);
+
+let stateBackup = ss.getBrowserState();
+
+function test() {
+  /** Test for Bug 597315 - Frameset history does not work properly when restoring a tab **/
+  waitForExplicitFinish();
+
+  Services.prefs.setIntPref("browser.tabs.max_tabs_undo", 0);
+
+  let testURL = getRootDirectory(gTestPath) + "browser_597315_index.html";
+  let tab = getBrowser().addTab(testURL);
+  getBrowser().selectedTab = tab;
+
+  waitForLoadsInBrowser(tab.linkedBrowser, 4, function() {
+    let browser_b = tab.linkedBrowser.contentDocument.getElementsByTagName("frame")[1];
+    let document_b = browser_b.contentDocument;
+    let links = document_b.getElementsByTagName("a");
+
+    // We're going to click on the first link, so listen for another load event
+    waitForLoadsInBrowser(tab.linkedBrowser, 1, function() {
+      waitForLoadsInBrowser(tab.linkedBrowser, 1, function() {
+
+        getBrowser().removeTab(tab);
+        // wait for 4 loads again...
+        let newTab = ss.undoCloseTab(window, 0);
+
+        waitForLoadsInBrowser(newTab.linkedBrowser, 4, function() {
+          getBrowser().goBack();
+          waitForLoadsInBrowser(newTab.linkedBrowser, 1, function() {
+
+            let expectedURLEnds = ["a.html", "b.html", "c1.html"];
+            let frames = newTab.linkedBrowser.contentDocument.getElementsByTagName("frame");
+            for (let i = 0; i < frames.length; i++) {
+              is(frames[i].contentDocument.location,
+                 getRootDirectory(gTestPath) + "browser_597315_" + expectedURLEnds[i],
+                 "frame " + i + " has the right url");
+            }
+            Services.prefs.clearUserPref("browser.tabs.max_tabs_undo");
+            getBrowser().removeTab(newTab);
+            ss.setBrowserState(stateBackup);
+            executeSoon(finish);
+          });
+        });
+      });
+      EventUtils.sendMouseEvent({type:"click"}, links[1], browser_b.contentWindow);
+    });
+    EventUtils.sendMouseEvent({type:"click"}, links[0], browser_b.contentWindow);
+  });
+}
+
+// helper function
+function waitForLoadsInBrowser(aBrowser, aLoadCount, aCallback) {
+  let loadCount = 0;
+  aBrowser.addEventListener("load", function(aEvent) {
+    if (++loadCount < aLoadCount)
+      return;
+
+    aBrowser.removeEventListener("load", arguments.callee, true);
+    aCallback();
+  }, true);
+}
new file mode 100755
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_a.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    I'm A!
+  </body>
+</html>
new file mode 100755
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_b.html
@@ -0,0 +1,10 @@
+<html>
+  <body>
+    I'm B!<br/>
+    <a target="c" href="browser_597315_c1.html">click me first</a><br/>
+    <a target="c" href="browser_597315_c2.html">then click me</a><br/>
+    Close this tab.<br/>
+    Restore this tab.<br/>
+    Click back.<br/>
+  </body>
+</html>
new file mode 100755
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_c.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    I'm C!
+  </body>
+</html>
new file mode 100755
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_c1.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    I'm C1!
+  </body>
+</html>
new file mode 100755
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_c2.html
@@ -0,0 +1,5 @@
+<html>
+  <body>
+    I'm C2!
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/suite/common/tests/browser/browser_597315_index.html
@@ -0,0 +1,10 @@
+<html>
+  <frameset cols="20%,80%">
+    <frameset rows="30%,70%">
+      <frame src="browser_597315_a.html"/>
+      <frame src="browser_597315_b.html"/>
+    </frameset>
+    <frame src="browser_597315_c.html" name="c"/>
+  </frameset>
+</html>
+