Title: [240442] trunk
Revision
240442
Author
[email protected]
Date
2019-01-24 10:30:35 -0800 (Thu, 24 Jan 2019)

Log Message

Regression(PSON) Back/Forward list items' URL sometimes gets replaced with the URL of a subframe
https://bugs.webkit.org/show_bug.cgi?id=193761
<rdar://problem/47456405>

Reviewed by Alex Christensen.

Source/WebKit:

When doing a history navigation cross-process, the UIProcess would first send the back/forward list items
to the destination WebProcess via WebPage::updateBackForwardListForReattach(), then ask the process to
navigate to the expected back/forward list item.

WebPage::updateBackForwardListForReattach() would call restoreSessionInternal(), which would call
toHistoryItem() on each BackForwardListItem. This may end up creating more than one HistoryItem for each
BackForwardListItem because HistoryItems are part of a tree (each frame has its own list of history items).

Note that BackForwardListItems and HistoryItem share a BackForwardItemIdentifier which is a
(processIdentifier, itemIdentifier) pair. We normally generate the HistoryItem's identifier from inside
its constructor like so:
`{ Process::identifier(), generateObjectIdentifier<BackForwardItemIdentifier::ItemIdentifierType>() }`

However, when calling updateBackForwardListForReattach() and constructing children HistoryItem,
applyFrameState() would generate the identifier by itself and passing it to the HistoryItem constructor.
Its genegates the ID the exact same way so this would in theory not be a problem. Unfortunately, both
calls to generateObjectIdentifier() get inlined and both call sites end up with their own static counter
to generate ids. As a result, we may end up with conflicts as HistoryItems for child frames (restored
by restoreSessionInternal()) can end up with the same identifier as HistoryItems for top frames.

This confusion would lead to the WebContent process sending the UIProcess bad information and the URL
of subframes could end up as the WebBackForwardListItem's mainframe URL.

* WebProcess/WebCoreSupport/SessionStateConversion.cpp:
(WebKit::applyFrameState):
Stop calling generateObjectIdentifier() explicitly and let the HistoryItem constructor take care of it.
Calling generateObjectIdentifier() for the same type from different places is not safe due to inlining.

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

Modified Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (240441 => 240442)


--- trunk/Source/WebKit/ChangeLog	2019-01-24 18:30:24 UTC (rev 240441)
+++ trunk/Source/WebKit/ChangeLog	2019-01-24 18:30:35 UTC (rev 240442)
@@ -1,3 +1,39 @@
+2019-01-24  Chris Dumez  <[email protected]>
+
+        Regression(PSON) Back/Forward list items' URL sometimes gets replaced with the URL of a subframe
+        https://bugs.webkit.org/show_bug.cgi?id=193761
+        <rdar://problem/47456405>
+
+        Reviewed by Alex Christensen.
+
+        When doing a history navigation cross-process, the UIProcess would first send the back/forward list items
+        to the destination WebProcess via WebPage::updateBackForwardListForReattach(), then ask the process to
+        navigate to the expected back/forward list item.
+
+        WebPage::updateBackForwardListForReattach() would call restoreSessionInternal(), which would call
+        toHistoryItem() on each BackForwardListItem. This may end up creating more than one HistoryItem for each
+        BackForwardListItem because HistoryItems are part of a tree (each frame has its own list of history items).
+
+        Note that BackForwardListItems and HistoryItem share a BackForwardItemIdentifier which is a
+        (processIdentifier, itemIdentifier) pair. We normally generate the HistoryItem's identifier from inside
+        its constructor like so:
+        `{ Process::identifier(), generateObjectIdentifier<BackForwardItemIdentifier::ItemIdentifierType>() }`
+
+        However, when calling updateBackForwardListForReattach() and constructing children HistoryItem,
+        applyFrameState() would generate the identifier by itself and passing it to the HistoryItem constructor.
+        Its genegates the ID the exact same way so this would in theory not be a problem. Unfortunately, both
+        calls to generateObjectIdentifier() get inlined and both call sites end up with their own static counter
+        to generate ids. As a result, we may end up with conflicts as HistoryItems for child frames (restored
+        by restoreSessionInternal()) can end up with the same identifier as HistoryItems for top frames.
+
+        This confusion would lead to the WebContent process sending the UIProcess bad information and the URL
+        of subframes could end up as the WebBackForwardListItem's mainframe URL.
+
+        * WebProcess/WebCoreSupport/SessionStateConversion.cpp:
+        (WebKit::applyFrameState):
+        Stop calling generateObjectIdentifier() explicitly and let the HistoryItem constructor take care of it.
+        Calling generateObjectIdentifier() for the same type from different places is not safe due to inlining.
+
 2019-01-24  Ross Kirsling  <[email protected]>
 
         Move FileSystem to WTF

Modified: trunk/Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp (240441 => 240442)


--- trunk/Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp	2019-01-24 18:30:24 UTC (rev 240441)
+++ trunk/Source/WebKit/WebProcess/WebCoreSupport/SessionStateConversion.cpp	2019-01-24 18:30:35 UTC (rev 240442)
@@ -178,7 +178,7 @@
 #endif
 
     for (const auto& childFrameState : frameState.children) {
-        Ref<HistoryItem> childHistoryItem = HistoryItem::create(childFrameState.urlString, { }, { }, { Process::identifier(), generateObjectIdentifier<BackForwardItemIdentifier::ItemIdentifierType>() });
+        Ref<HistoryItem> childHistoryItem = HistoryItem::create(childFrameState.urlString, { }, { });
         applyFrameState(childHistoryItem, childFrameState);
 
         historyItem.addChildItem(WTFMove(childHistoryItem));

Modified: trunk/Tools/ChangeLog (240441 => 240442)


--- trunk/Tools/ChangeLog	2019-01-24 18:30:24 UTC (rev 240441)
+++ trunk/Tools/ChangeLog	2019-01-24 18:30:35 UTC (rev 240442)
@@ -1,3 +1,15 @@
+2019-01-24  Chris Dumez  <[email protected]>
+
+        Regression(PSON) Back/Forward list items' URL sometimes gets replaced with the URL of a subframe
+        https://bugs.webkit.org/show_bug.cgi?id=193761
+        <rdar://problem/47456405>
+
+        Reviewed by Alex Christensen.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
+
 2019-01-24  Jonathan Bedard  <[email protected]>
 
         webkitpy: Missing PID in crashlog name should not be fatal

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm (240441 => 240442)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-01-24 18:30:24 UTC (rev 240441)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm	2019-01-24 18:30:35 UTC (rev 240442)
@@ -2063,6 +2063,79 @@
     EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
 }
 
+static const char* withSubframesTestBytes = R"PSONRESOURCE(
+<body>
+<iframe src=""
+<iframe src=""
+</body>
+)PSONRESOURCE";
+
+TEST(ProcessSwap, HistoryItemIDConfusion)
+{
+    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
+    [processPoolConfiguration setProcessSwapsOnNavigation:YES];
+    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
+
+    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    [webViewConfiguration setProcessPool:processPool.get()];
+    auto handler = adoptNS([[PSONScheme alloc] init]);
+    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:failsToEnterPageCacheTestBytes];
+    [handler addMappingFromURLString:@"pson://www.apple.com/main.html" toData:withSubframesTestBytes];
+    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
+
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
+    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
+    [webView setNavigationDelegate:delegate.get()];
+
+    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto webkitPID = [webView _webProcessIdentifier];
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto applePID = [webView _webProcessIdentifier];
+    EXPECT_NE(webkitPID, applePID);
+
+    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
+    [webView loadRequest:request];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    auto googlePID = [webView _webProcessIdentifier];
+    EXPECT_NE(applePID, googlePID);
+    EXPECT_NE(webkitPID, googlePID);
+
+    [webView goBack];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_EQ(applePID, [webView _webProcessIdentifier]);
+
+    [webView goBack];
+
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
+
+    auto* backForwardList = [webView backForwardList];
+    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html", [backForwardList.currentItem.URL absoluteString]);
+    EXPECT_EQ(2U, backForwardList.forwardList.count);
+    EXPECT_EQ(0U, backForwardList.backList.count);
+    EXPECT_WK_STREQ(@"pson://www.apple.com/main.html", [backForwardList.forwardList[0].URL absoluteString]);
+    EXPECT_WK_STREQ(@"pson://www.google.com/main.html", [backForwardList.forwardList[1].URL absoluteString]);
+}
+
 static const char* mainFramesOnlyMainFrame = R"PSONRESOURCE(
 <script>
 function loaded() {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to