Changeset 241950 in webkit


Ignore:
Timestamp:
Feb 22, 2019 10:24:57 AM (5 years ago)
Author:
Chris Dumez
Message:

REGRESSION(PSON) Scroll position is sometimes not restored on history navigation
https://bugs.webkit.org/show_bug.cgi?id=194924
<rdar://problem/48216125>

Reviewed by Geoffrey Garen.

Source/WebKit:

When process-swapping, we would create a new WebPage in the new process, which would
call restoreSessionInternal() to restore the HistoryItems based on the UIProcess's
backforward list. The issue is that this session restoring would send HistoryItem
updates back to the UIProcess. Without PSON, this would be unnecessary but harmless.
With PSON though, this may end up overwriting values set by the previous process,
such as the scroll position.

Address the issue by temporarily disabling the HistoryItem update notifications to
the UIProcess while restoring a session.

  • UIProcess/API/Cocoa/WKBackForwardListItem.mm:

(-[WKBackForwardListItem _scrollPosition]):

  • UIProcess/API/Cocoa/WKBackForwardListItemPrivate.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::restoreSessionInternal):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r241936 r241950  
     12019-02-22  Chris Dumez  <cdumez@apple.com>
     2
     3        REGRESSION(PSON) Scroll position is sometimes not restored on history navigation
     4        https://bugs.webkit.org/show_bug.cgi?id=194924
     5        <rdar://problem/48216125>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        When process-swapping, we would create a new WebPage in the new process, which would
     10        call restoreSessionInternal() to restore the HistoryItems based on the UIProcess's
     11        backforward list. The issue is that this session restoring would send HistoryItem
     12        updates back to the UIProcess. Without PSON, this would be unnecessary but harmless.
     13        With PSON though, this may end up overwriting values set by the previous process,
     14        such as the scroll position.
     15
     16        Address the issue by temporarily disabling the HistoryItem update notifications to
     17        the UIProcess while restoring a session.
     18
     19        * UIProcess/API/Cocoa/WKBackForwardListItem.mm:
     20        (-[WKBackForwardListItem _scrollPosition]):
     21        * UIProcess/API/Cocoa/WKBackForwardListItemPrivate.h:
     22        * WebProcess/WebPage/WebPage.cpp:
     23        (WebKit::WebPage::restoreSessionInternal):
     24
    1252019-02-21  Adrian Perez de Castro  <aperez@igalia.com>
    226
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKBackForwardListItem.mm

    r235828 r241950  
    7272}
    7373
     74- (CGPoint) _scrollPosition
     75{
     76    return CGPointMake(_item->pageState().mainFrameState.scrollPosition.x(), _item->pageState().mainFrameState.scrollPosition.y());
     77}
     78
    7479#pragma mark WKObject protocol implementation
    7580
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKBackForwardListItemPrivate.h

    r218444 r241950  
    3333- (CGImageRef)_copySnapshotForTesting WK_API_AVAILABLE(macosx(10.12.3), ios(10.3));
    3434
     35@property (nonatomic) CGPoint _scrollPosition WK_API_AVAILABLE(macosx(WK_MAC_TBA), ios(WK_IOS_TBA));
     36
    3537@end
    3638
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r241899 r241950  
    27052705void WebPage::restoreSessionInternal(const Vector<BackForwardListItemState>& itemStates, WasRestoredByAPIRequest restoredByAPIRequest, WebBackForwardListProxy::OverwriteExistingItem overwrite)
    27062706{
     2707    // Since we're merely restoring HistoryItems from the UIProcess, there is no need to send HistoryItem update notifications back to the UIProcess.
     2708    // Also, with process-swap on navigation, these updates may actually overwrite important state in the UIProcess such as the scroll position.
     2709    SetForScope<void (*)(WebCore::HistoryItem&)> bypassHistoryItemUpdateNotifications(WebCore::notifyHistoryItemChanged, [](WebCore::HistoryItem&){});
    27072710    for (const auto& itemState : itemStates) {
    27082711        auto historyItem = toHistoryItem(itemState);
  • trunk/Tools/ChangeLog

    r241948 r241950  
     12019-02-22  Chris Dumez  <cdumez@apple.com>
     2
     3        REGRESSION(PSON) Scroll position is sometimes not restored on history navigation
     4        https://bugs.webkit.org/show_bug.cgi?id=194924
     5        <rdar://problem/48216125>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     12
    1132019-02-22  Chris Dumez  <cdumez@apple.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r241948 r241950  
    3030#import "TestNavigationDelegate.h"
    3131#import "TestWKWebView.h"
     32#import <WebKit/WKBackForwardListItemPrivate.h>
    3233#import <WebKit/WKContentRuleListStore.h>
    3334#import <WebKit/WKNavigationDelegatePrivate.h>
     
    48624863}
    48634864
     4865#endif // PLATFORM(MAC)
     4866
    48644867static const char* tallPageBytes = R"PSONRESOURCE(
    48654868<!DOCTYPE html>
     
    48764879</head>
    48774880<body>
     4881<script>
     4882// Pages with dedicated workers do not go into page cache.
     4883var myWorker = new Worker('worker.js');
     4884</script>
    48784885<a id="testLink" href="pson://www.apple.com/main.html">Test</a>
    48794886</body>
     
    48814888)PSONRESOURCE";
    48824889
     4890static unsigned waitUntilScrollPositionIsRestored(WKWebView *webView)
     4891{
     4892    unsigned scrollPosition = 0;
     4893    do {
     4894        [webView evaluateJavaScript:@"window.scrollY" completionHandler: [&] (id result, NSError *error) {
     4895            scrollPosition = [result integerValue];
     4896            done = true;
     4897        }];
     4898        TestWebKitAPI::Util::run(&done);
     4899        done = false;
     4900    } while (!scrollPosition);
     4901
     4902    return scrollPosition;
     4903}
     4904
    48834905TEST(ProcessSwap, ScrollPositionRestoration)
    48844906{
     
    48914913    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:tallPageBytes];
    48924914    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
    4893 
    4894     [[webViewConfiguration preferences] _setUsesPageCache:NO];
    48954915
    48964916    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     
    49084928    TestWebKitAPI::Util::run(&done);
    49094929    done = false;
     4930
     4931    do {
     4932        TestWebKitAPI::Util::sleep(0.05);
     4933    } while (lroundf([[[webView backForwardList] currentItem] _scrollPosition].y) != 5000);
    49104934
    49114935    [webView evaluateJavaScript:@"testLink.click()" completionHandler: nil];
     
    49254949    done = false;
    49264950
    4927     [webView evaluateJavaScript:@"window.scrollY" completionHandler: [&] (id result, NSError *error) {
    4928         EXPECT_EQ(5000, [result integerValue]);
     4951    auto scrollPosition = waitUntilScrollPositionIsRestored(webView.get());
     4952    EXPECT_EQ(5000U, scrollPosition);
     4953
     4954    [webView evaluateJavaScript:@"scroll(0, 4000)" completionHandler: [&] (id result, NSError *error) {
    49294955        done = true;
    49304956    }];
    49314957    TestWebKitAPI::Util::run(&done);
    49324958    done = false;
    4933 }
    4934 
    4935 #endif // PLATFORM(MAC)
     4959
     4960    do {
     4961        TestWebKitAPI::Util::sleep(0.05);
     4962    } while (lroundf([[[webView backForwardList] currentItem] _scrollPosition].y) != 4000);
     4963
     4964    [webView evaluateJavaScript:@"testLink.click()" completionHandler: nil];
     4965
     4966    TestWebKitAPI::Util::run(&done);
     4967    done = false;
     4968
     4969    [webView evaluateJavaScript:@"window.scrollY" completionHandler: [&] (id result, NSError *error) {
     4970        EXPECT_EQ(0, [result integerValue]);
     4971        done = true;
     4972    }];
     4973    TestWebKitAPI::Util::run(&done);
     4974    done = false;
     4975
     4976    [webView goBack];
     4977    TestWebKitAPI::Util::run(&done);
     4978    done = false;
     4979
     4980    scrollPosition = waitUntilScrollPositionIsRestored(webView.get());
     4981    EXPECT_EQ(4000U, scrollPosition);
     4982}
    49364983
    49374984static NSString *blockmeFilter = @"[{\"action\":{\"type\":\"block\"},\"trigger\":{\"url-filter\":\".*blockme.html\"}}]";
Note: See TracChangeset for help on using the changeset viewer.