Skip to content

Commit

Permalink
Back button needs to be pressed twice to go back on https://www.livei…
Browse files Browse the repository at this point in the history
…lpalazzoapartments.com

https://bugs.webkit.org/show_bug.cgi?id=260682
rdar://113772385

Reviewed by Brent Fulgham.

WebKit normally ignores history entries added by the JavaScript without user
interaction when navigating back or forward.

Here, the site is adding a history entry using `history.pushState()`, without
user interaction but it was incorrectly not getting ignored when navigating
back.

The reason for this is that they are calling `history.pushState()` from a
subframe. Navigations in subframes still create a top-level back/forward
list item. However, we had a bug in HistoryController::pushState() where
we would set the `wasCreatedByJSWithoutUserInteraction` flag on m_currentItem
instead of topItem. topItem and m_currentItem are the same when
`history.pushState()` gets called on the main frame but not in this case.

* Source/WebCore/loader/HistoryController.cpp:
(WebCore::FrameLoader::HistoryController::pushState):
* Tools/TestWebKitAPI/Tests/WebKit/WKBackForwardListTests.mm:
(TEST):

Canonical link: https://commits.webkit.org/267287@main
  • Loading branch information
cdumez committed Aug 25, 2023
1 parent 97a9155 commit 6fb0e85
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
4 changes: 2 additions & 2 deletions Source/WebCore/loader/HistoryController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,8 +892,8 @@ void FrameLoader::HistoryController::pushState(RefPtr<SerializedScriptValue>&& s

auto* document = m_frame.document();
if (document && !document->hasRecentUserInteractionForNavigationFromJS())
m_currentItem->setWasCreatedByJSWithoutUserInteraction(true);
topItem->setWasCreatedByJSWithoutUserInteraction(true);

// Override data in the current item (created by createItemTree) to reflect
// the pushState() arguments.
m_currentItem->setTitle(title);
Expand Down
39 changes: 39 additions & 0 deletions Tools/TestWebKitAPI/Tests/WebKit/WKBackForwardListTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,45 @@ static void runBackForwardNavigationSkipsItemsWithoutUserGestureTest(Function<vo
});
}

TEST(WKBackForwardList, BackForwardNavigationSkipsItemsWithoutUserGestureSubframe)
{
TestWebKitAPI::HTTPServer server({
{ "/source.html"_s, { "foo"_s } },
{ "/destination.html"_s, { "<iframe src='iframe.html'></iframe>"_s } },
{ "/iframe.html"_s, { "<script>onload = () => { setTimeout(() => { history.pushState(null, document.title, '#'); }, 0); };</script>"_s } },
}, TestWebKitAPI::HTTPServer::Protocol::Http);

auto webView = adoptNS([[WKWebView alloc] init]);

auto navigationDelegate = adoptNS([WKBackForwardNavigationDelegate new]);
webView.get().navigationDelegate = navigationDelegate.get();

[webView loadRequest:server.request("/source.html"_s)];
[navigationDelegate waitForDidFinishNavigationOrDidSameDocumentNavigation];

[webView loadRequest:server.request("/destination.html"_s)];
[navigationDelegate waitForDidFinishNavigationOrDidSameDocumentNavigation];

// Wait for the subframe to call pushState().
while ([webView backForwardList].backList.count != 2)
TestWebKitAPI::Util::spinRunLoop();

[webView goBack];
[navigationDelegate waitForDidFinishNavigationOrDidSameDocumentNavigation];

// We should be back to source.html since we would have ignored the history item
// added by the subframe without user interaction.
EXPECT_EQ([webView backForwardList].backList.count, 0U);
EXPECT_STREQ([webView URL].absoluteString.UTF8String, server.request("/source.html"_s).URL.absoluteString.UTF8String);

[webView goForward];
[navigationDelegate waitForDidFinishNavigationOrDidSameDocumentNavigation];

EXPECT_EQ([webView backForwardList].backList.count, 2U);
EXPECT_EQ([webView backForwardList].forwardList.count, 0U);
EXPECT_STREQ([webView URL].absoluteString.UTF8String, server.request("/destination.html"_s).URL.absoluteString.UTF8String);
}

static void runBackForwardNavigationDoesNotSkipItemsWithUserGestureTest(Function<void(WKWebView *, ASCIILiteral fragment)>&& navigate)
{
auto webView = adoptNS([[WKWebView alloc] init]);
Expand Down

0 comments on commit 6fb0e85

Please sign in to comment.