Bug 289294
Summary: | Calling history.back() in an iframe stops all pending network requests | ||
---|---|---|---|
Product: | WebKit | Reporter: | Ben Nham <nham> |
Component: | History | Assignee: | Ben Nham <nham> |
Status: | RESOLVED FIXED | ||
Severity: | Normal | CC: | paroga, webkit-bug-importer |
Priority: | P2 | Keywords: | InRadar |
Version: | WebKit Nightly Build | ||
Hardware: | Unspecified | ||
OS: | Unspecified |
Ben Nham
Follow these steps:
1. Go to https://nham.me/misc/iframefetch/
2. Click on "Navigate to Hash"
3. Click on "Start Fetch"
4. Click "Go Back"
Notice that the fetch immediately terminates.
The reason for this is that we sometimes eagerly stop all pending network requests when navigating history. In`Page::goToItem`, we are doing that here:
if (frame.loader().protectedHistory()->shouldStopLoadingForHistoryItem(item))
frame.protectedLoader()->stopAllLoadersAndCheckCompleteness();
`HistoryController::shouldStopLoadingForHistoryItem` asks `HistoryItem::shouldDoSameDocumentNavigationTo` whether or not the navigation is same-document. If it's a cross-doc navigation, we eagerly stop all outstanding loaders. And here is the very first line of `HistoryItem::shouldDoSameDocumentNavigationTo` is
if (m_itemID == otherItem.itemID())
return false;
So navigating to a history item with the same ID is actually considered a *cross-document* navigation, which then stops all pending network requests. That's what's happening here:
1. We navigate to a fragment in the iframe, it modifies the history item further down the history tree, but the root history item's ID is unchanged.
2. When we call history.back(), that calls `Page::goToItem` with the old root history item, which has the same ID as the current root history item. So this is considered a cross-doc navigation.
It looks like this behavior was added back in 2010 in bug 35532 (http://commits.webkit.org/r55375):
> Telling a Page/FrameLoader to go to the same HistoryItem that is its current HistoryItem is supposed to effectively reload the page. creating a new load and new document.
Note in particular the `item != currentItem` addition to FrameLoader.cpp, which eventually made its way to `HistoryController::shouldStopLoadingForHistoryItem` after refactoring.
It's not clear what the best solution here is:
- We could possibly remove the `m_itemID == otherItem.itemID()` logic from `shouldStopLoadingForHistoryItem`.
- We could also possibly just remove this whole eager FrameLoader stopping logic entirely and count on some other logic to stop the FrameLoader when a new navigation commits in a frame. Maybe the call to stopAllLoaders in FrameLoader::continueLoadAfterNavigationPolicy already takes care of this?
Attachments | ||
---|---|---|
Add attachment proposed patch, testcase, etc. |
Radar WebKit Bug Importer
<rdar://problem/146430092>
Ben Nham
*** Bug 22165 has been marked as a duplicate of this bug. ***
Ben Nham
Pull request: https://github.com/WebKit/WebKit/pull/42050
EWS
Committed 291823@main (c71c8ea9721a): <https://commits.webkit.org/291823@main>
Reviewed commits have been landed. Closing PR #42050 and removing active labels.