Bug 6309

Summary: multiple problems prevent bookmarking/back button technique for AJAX/DHTML applications from working
Product: WebKit Reporter: Brad Neuberg <bkn3>
Component: JavaScriptCoreAssignee: Anders Carlsson <andersca>
Status: RESOLVED FIXED    
Severity: Major CC: adele, alice.barraclough, andersca, bkn3, bugs-webkit, christopher, darin, ddkilzer, eric, Kevin, mjs, sjoerdmulder, sjt, trey
Priority: P1 Keywords: InRadar
Version: 420+   
Hardware: All   
OS: OS X 10.4   
Bug Depends on: 7058    
Bug Blocks: 9610, 6628    
Attachments:
Description Flags
Test case
none
Patch v1 (probably not final fix)
darin: review-
Testcase using Back button
none
Patch darin: review+

Brad Neuberg
Reported 2005-12-31 02:46:39 PST
I'm the designer of the Really Simple History library, an open source framework that makes it possible to support bookmarking and the back/forward buttons in AJAX/DHTML applications (for an intro to the framework see an O'Reilly Net article at http://www.onjava.com/pub/a/onjava/2005/10/26/ajax-handling-bookmarks-and-back-button.html). This framework is being integrated into the Dojo project (http://dojotoolkit.org), a popular library for AJAX/DHTML applications, and was recently brought into Google for their own applications. Unfortunately, RSH does not support Safari/WebKit, primarily because it is impossible to do so; RSH works on Firefox and IE. I spent about two weeks full time attempting to explore work arounds for Safari, but it turns out to be impossible for a number of reasons I blogged about here: http://codinginparadise.org/weblog/2005/09/safari-no-dhtml-history-possible.html The RSH home page: http://codinginparadise.org/projects/dhtml_history/README.html Here is what Safari/WebKit _should_ do: 1) If JavaScript updates the location of the web page to an anchor: window.location.href = "#some_new_location" The URL location toolbar _should_ update with the new location (and the browser throbber should stop spinning; it currently goes into a continious loop in some conditions). In addition, every time JavaScript updates the location, this entry should be placed into the browser's history, so that it affects the back and forward buttons, just like Firefox. In addition, if I create a timer to check the location of the page: var checkLocation = function(){ var newLoc = document.location.href; // do something with the hash location }; window.setInterval(checkLocation, 200); It _should_ always be able to see the _current_ location of the document, including the new hash value, and _should_ return the hash value as well (sometimes you don't get the hash value). The ability to do bookmarking and back button support is very important to the kind of large scale AJAX/DHTML apps that are appearing, such as the new AJAX Yahoo Mail, the new Google RSS Reader, and others. Just as a side note, I should let you know that more and more AJAX/DHTML developers are abandoning Safari as a platform for these advanced apps, which does not bode well for Safari. In addition, many of the ones doing this are the ones creating the frameworks and libraries that others will use, which will lock Safari/WebKit even more out of some of the really cool things that are going on on the web right now. Feel free to contact me at bkn3@columbia.edu if you have any questions; many people I know really want to see this bug fixed.
Attachments
Test case (910 bytes, text/html)
2006-01-31 20:35 PST, David Kilzer (:ddkilzer)
no flags
Patch v1 (probably not final fix) (756 bytes, patch)
2006-01-31 21:59 PST, David Kilzer (:ddkilzer)
darin: review-
Testcase using Back button (1.20 KB, text/html)
2006-02-08 01:30 PST, Sjoerd Mulder
no flags
Patch (19.94 KB, patch)
2006-06-01 07:51 PDT, Anders Carlsson
darin: review+
Dave Hyatt
Comment 1 2006-01-31 14:48:59 PST
If you have any simple reduced test cases (if you can host them) would be very helpful. The issues with window.location.href are pretty well known, but reading your linked blog entry, I didn't quite follow what your issue was with iframes/forms.
Dave Hyatt
Comment 2 2006-01-31 14:58:22 PST
Inifnite loop = p1. This is probably related to 6958.
Brad Neuberg
Comment 3 2006-01-31 15:08:32 PST
Iframe history support is more of a hack to support history and bookmarking on IE. If you were to work exactly like Firefox, which is much better at these things, it would be better. Here's what Firefox does: 1) If you change the window.location.href to an anchor: window.location.href = "#foobar" Then this anchor should go into the browsers history. I.e., if I start at the website http://foobar.com, and add three anchors: window.location.href = "#location1"; window.location.href = "#location2"; window.location.href = "#location3"; there should now be four things on the history stack: http://foobar.com http://foobar.com#location1 http://foobar.com#location2 http://foobar.com#location3 If I hit the back button, the browser should jump through each of these locations, changing the browser's location bar to show each of them. At the same time, if I have a JavaScript interval timer running checking the browser's location: window.setInterval(function(){ var location = window.location.href; // check the location for a change }, 200) this timer should be able to see anchor location changes. This is exactly how Firefox works, by the way, and it is the basis for AJAX history support in that browser.
Brad Neuberg
Comment 4 2006-01-31 15:10:04 PST
By the way, it doesn't matter how you handle iframes and history if you support the process above. IE also doesn't work correctly with updating the anchor location (it doesn't always go into history), so IE needed to use a deeper hack using hidden iframes to register history events (it's nasty).
Dave Hyatt
Comment 5 2006-01-31 15:18:50 PST
I'm pretty sure we intended to put # URLS into the session history. Probably just a bug (or design flaw) that we lose intermediate ones. Our session history code is 3 years old and Firefox's is 7, so it's unsurprising that we have more bugs. :)
Dave Hyatt
Comment 6 2006-01-31 15:20:28 PST
BTW whenever you have problems with Safari/WebKit, you can come to #webkit on Freenode to ask for help. No need to beat against something for 2 weeks when you can ask for help from the actual developers.
David Kilzer (:ddkilzer)
Comment 7 2006-01-31 20:35:31 PST
Created attachment 6173 [details] Test case Test case for setting window.location.href using relative links.
David Kilzer (:ddkilzer)
Comment 8 2006-01-31 21:59:17 PST
Created attachment 6174 [details] Patch v1 (probably not final fix) Poking around kjs_window.cpp, I found that the change in this patch would fix the attached test case (Attachment 6173 [details]). The change from calling scheduleLocationChange() to changeLocation() causes the Redirection Timer not to spin endlessly after the test case is done. The change from "!userGesture" to "false" in the third argument causes the history to be written for each change to the URL fragment/reference (#locationX). I have no idea if this is the correct fix, though, since it takes a while for the "Back" history button to update after the test case is run, and the test case seems to reload the entire page every time. It seems like there is a missing optimization where loading a URL fragment (#locationX) on the same page shouldn't force the entire page to be reloaded.
Darin Adler
Comment 9 2006-01-31 22:22:42 PST
Comment on attachment 6174 [details] Patch v1 (probably not final fix) We definitely can't do this. It sill introduce all sorts of problems to try to actually change the location right away. Sadly, I don't know exactly which problem it will cause -- it would be great to have the test cases, but I don't think we do.
Trey Matteson
Comment 10 2006-01-31 23:13:32 PST
I would expect that passing "false" instead of "!userGesture", as proposed in the patch, would break a large number of sites that implement redirects using pure JS. In fact, the attached test case of changing the location in onload() is a perfect example. We solved a lot of conflicting bugs when we realized the existing "userGesture" flag in khtml was the way to distinguish whether window.location=foo should add to the history. You might try a test case that acts in response to a user event to see if it changes the behavior of TOT. If I'm right, I realize this situation might not be good enough to meet your original goals.
Brad Neuberg
Comment 11 2006-02-01 11:33:01 PST
By the way, setting an anchor location should _not_ reload the page, reset the DOM, etc. Other browsers don't do this.
Darin Adler
Comment 12 2006-02-02 10:20:09 PST
(In reply to comment #11) > By the way, setting an anchor location should _not_ reload the page, reset the > DOM, etc. Other browsers don't do this. Good point. Maybe we can break that part of this out into a separate bug report. This one seems to be about a set of related issues, and so it's a little hard to understand and fix.
Darin Adler
Comment 13 2006-02-02 10:21:03 PST
In general, the most helpful thing here would be to break this up into discrete pieces that are each easy to understand.
Sjoerd Mulder
Comment 14 2006-02-03 00:23:20 PST
This bug is also in Radar: <rdar://4432143>
David Kilzer (:ddkilzer)
Comment 15 2006-02-04 12:25:51 PST
(In reply to comment #12) > (In reply to comment #11) > > By the way, setting an anchor location should _not_ reload the page, reset the > > DOM, etc. Other browsers don't do this. > > Good point. Maybe we can break that part of this out into a separate bug > report. This one seems to be about a set of related issues, and so it's a > little hard to understand and fix. Actually, as far as I can tell (using ethereal to trace network activity), the page is NOT reloaded during the test case. (It's only loaded once to load the page in the first place.) It may look like it is reloaded because the spinner (via RedirectionTimer) is fired up, but WebKit doesn't actually go back out to the network to request the page. This means that two things should happen to fix this bug, e.g., when JavaScript requests a '#name' URL on the same page: 1. The RedirectionTimer should NOT fire when requesting a '#name' URL on the same page. 2. The current URL should be pushed onto the history stack before jumping to the new '#name' URL. (This could be taken care of by introducing a local 'lockHistory' variable that is always false for a '#name' URL on the same page regardless of source, but !userGesture otherwise.) I just tested the attached Test case (Attachment 6173 [details]) on MSIE 6, and it's in "denial" about additional history entries when the "Test case" link is clicked after opening this bug (the count of "3" comes from the default page opening when MSIE 6 starts, the Bug 6309 page opening, then the Attachment 6173 [details] opening): One Two Three Status: FAIL initialLength = 3 window.history.length = 3 However, if one right-clicks on the "Test case" link and opens it in a new window, the test passes! What the heck?!
David Kilzer (:ddkilzer)
Comment 16 2006-02-04 19:38:13 PST
(In reply to comment #15) > 1. The RedirectionTimer should NOT fire when requesting a '#name' URL on the > same page. Hmm...it would seem that Bug 3552 covers this issue!
David Kilzer (:ddkilzer)
Comment 17 2006-02-07 21:21:30 PST
This bug was fixed with the commit for Bug 7058 (confirmed locally by applying the patch in reverse and rebuilding r12652), so marking it a duplicate of that bug. Bug 3552 was also fixed at the same time. Reporter, please verify that this was fixed with nightly r12598 or newer. Should a test case be prepared and checked in for WebKit to make sure this doesn't regress? *** This bug has been marked as a duplicate of 7058 ***
Sjoerd Mulder
Comment 18 2006-02-08 01:26:59 PST
This bug is definitly NOT a duplicate of bug 7058! This bug is about Safari supporting back / forward button in AJAX applications, I agree it's come one step closer by fixing bug 7058 but it still has some problems! Attaching a better testcase! (where you actually have to use the history by pressing Back)
Sjoerd Mulder
Comment 19 2006-02-08 01:30:50 PST
Created attachment 6339 [details] Testcase using Back button
Brad Neuberg
Comment 20 2006-02-08 01:48:12 PST
Here is a test page using the Really Simple History library which works on IE and Firefox: http://www.onjava.com/onjava/2005/10/26/examples/examples/oreillymail/oreillymail.html You can use this to make sure that your fixes work. This is a simple, fake AJAX/DHTML email client put together to show AJAX history, bookmarking, and back/button support. What you should do is click around on the left hand sidebar; make sure that the page location changes at the top, showing a new anchor location. Then, press the back and forward buttons, and make sure that the history changes in the anchor bar. Press the reload button and make sure the page stays the same, then press back and forward again to make sure the history is still there. Manually change the anchor location to a new place (such as #drafts), then press enter; the page should correctly change; continue using the history to make sure this manual change doesn't break things, by clicking on the sidebar more. Then, go to http://google.com in this window, let Google load, and then press the back button to jump back to the test page; you should be on the last history location you left it at. Continue pressing the back button to jump through your history state, ensuring that leaving the page and then returning has not cleared out your AJAX history. This all works in IE and Firefox. It should work in Safari. Google has adopted this library for some of their own projects, so getting it working in Safari would be nice.
David Kilzer (:ddkilzer)
Comment 21 2006-02-08 05:06:12 PST
Adding Bug 7058 to depends-on list since it fixed part of the issue originally described in the description of this bug. I apologize for missing the "location.hash does not get updated" issue when I wrote the initial test case (Attachment 6173 [details]), but "(sometimes you don't get the hash value)" in the original description didn't inform me that "location.hash" wasn't getting updated. I thought that meant the hash value wasn't available in location.href. In the future if you want Software X or Web Site Y to work with WebKit and there are multiple individual issues that are able to be identified, please set up a "Master" or "Tracking" bug (like Bug 6628 for Backbase or Bug 6627 for TinyMCE) and then reference existing bugs or create additional bugs (with test cases!) that block the master/tracking bug. Thanks!
Kevin Newman
Comment 22 2006-04-11 11:10:57 PDT
Hello. I just wanted to let you know of another project that relies on this functionality to implement a history for AJAX and Flash RIAs. You can find it a simple test page here: http://www.unfocus.com/projects/source/historykeeper.html and another one using flash here: http://www.unfocus.com/projects/source/#About . These pages are not always stable, as they are WIP pages, I will try to send some specific bug test cases when I find time (increasingly scarce time). BTW, there is a bit of a workaround for this that has been implemented in my script, which is to watch the history.length property. This property seems to incorrectly change as you go back through the history (is this another bug?). I mentioned on webkit-dev mailing list, that I think this is kind of a missing feature on the web platform. It would be great if we could get some kind of more robust history interface in javascript for AJAX and Flash RIAs, since they are becoming more popular (maybe this is a feature request?). Even just a new (onHistoryChange or something) event on the History or location element would be good. Anyway, if there is anything I can do to help (test cases, help with the dojo scripts, etc.), please let me know. I have no mac osx Tiger to test with unfortunately though..
Darin Adler
Comment 23 2006-04-11 12:02:37 PDT
The most helpful thing anyone could do about this bug would be to write some small specific bug reports. This giant one about a whole category of problems is very difficult to work on. Individual specific ones, each with a small, specific set of steps would be a lot easier to resolve.
Anders Carlsson
Comment 24 2006-05-27 05:03:29 PDT
I'm working on this. I have a patch which fixes most problems, it just needs some more testing
Darin Adler
Comment 25 2006-05-30 10:57:44 PDT
Anders says he's working on this, so assigning to him to reflect that fact.
Anders Carlsson
Comment 26 2006-06-01 07:51:59 PDT
Created attachment 8642 [details] Patch This patch fixes the issues described above
Darin Adler
Comment 27 2006-06-01 13:00:36 PDT
Comment on attachment 8642 [details] Patch Since == already works on KURL, it seems to me that we only need a function that does the "== ignoring hash" operation. Also, for symmetric operations like equality, I prefer functions to members. So I'd like to see the isEqualTo function renamed and remove the boolean parameter and be a "free" function rather than a member function. In historyURL: we should not use braces around single-line if statements. Otherwise looks good, and those are nitpicks, so r=me.
David Kilzer (:ddkilzer)
Comment 28 2006-06-01 17:38:34 PDT
*** Bug 8522 has been marked as a duplicate of this bug. ***
David Kilzer (:ddkilzer)
Comment 29 2006-06-02 09:53:05 PDT
*** Bug 7516 has been marked as a duplicate of this bug. ***
David Kilzer (:ddkilzer)
Comment 30 2006-06-02 09:57:52 PDT
*** Bug 9184 has been marked as a duplicate of this bug. ***
David Kilzer (:ddkilzer)
Comment 31 2006-06-02 20:43:18 PDT
*** Bug 9281 has been marked as a duplicate of this bug. ***
David Kilzer (:ddkilzer)
Comment 32 2006-06-02 20:51:00 PDT
*** Bug 9266 has been marked as a duplicate of this bug. ***
Anders Carlsson
Comment 33 2006-07-09 14:35:22 PDT
*** Bug 9711 has been marked as a duplicate of this bug. ***
Note You need to log in before you can comment on or make changes to this bug.