⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 244075 in webkit


Ignore:
Timestamp:
Apr 9, 2019, 7:20:12 AM (7 years ago)
Author:
Chris Dumez
Message:

Loads using loadHTMLString() cause flashing when process-swapping
https://bugs.webkit.org/show_bug.cgi?id=196714
<rdar://problem/49637354>

Reviewed by Antti Koivisto.

Source/WebKit:

Our logic to decide if we should construct a SuspendedPageProxy on process-swap was assuming
a SuspendedPageProxy is only useful for PageCache and would therefore not create one if PageCache
is disabled or if there is no associated WebBackForwardListItem. However, constructing a
SuspendedPageProxy is also useful to prevent flashing when process-swapping as we need to keep
displaying the layer of the previous process until there is something meaningful to show in the
new process.

This patch makes it so that we now construct a SuspendedPageProxy on process-swap, even if
PageCache is disabled or if there is no associated WebBackForwardListItem. The process in
question will not be useful for PageCache but it will avoid flashing. The SuspendedPageProxy's
process may also get used for future navigations to the same site (as demonstrated by the
API test) which is beneficial for performance.

  • UIProcess/SuspendedPageProxy.cpp:

(WebKit::SuspendedPageProxy::SuspendedPageProxy):

  • UIProcess/SuspendedPageProxy.h:
  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::suspendCurrentPageIfPossible):

  • UIProcess/WebProcessPool.cpp:

(WebKit::WebProcessPool::findReusableSuspendedPageProcess):

Tools:

Add API test coverage.

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

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r244065 r244075  
     12019-04-09  Chris Dumez  <cdumez@apple.com>
     2
     3        Loads using loadHTMLString() cause flashing when process-swapping
     4        https://bugs.webkit.org/show_bug.cgi?id=196714
     5        <rdar://problem/49637354>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Our logic to decide if we should construct a SuspendedPageProxy on process-swap was assuming
     10        a SuspendedPageProxy is only useful for PageCache and would therefore not create one if PageCache
     11        is disabled or if there is no associated WebBackForwardListItem. However, constructing a
     12        SuspendedPageProxy is also useful to prevent flashing when process-swapping as we need to keep
     13        displaying the layer of the previous process until there is something meaningful to show in the
     14        new process.
     15
     16        This patch makes it so that we now construct a SuspendedPageProxy on process-swap, even if
     17        PageCache is disabled or if there is no associated WebBackForwardListItem. The process in
     18        question will not be useful for PageCache but it will avoid flashing. The SuspendedPageProxy's
     19        process may also get used for future navigations to the same site (as demonstrated by the
     20        API test) which is beneficial for performance.
     21
     22        * UIProcess/SuspendedPageProxy.cpp:
     23        (WebKit::SuspendedPageProxy::SuspendedPageProxy):
     24        * UIProcess/SuspendedPageProxy.h:
     25        * UIProcess/WebPageProxy.cpp:
     26        (WebKit::WebPageProxy::suspendCurrentPageIfPossible):
     27        * UIProcess/WebProcessPool.cpp:
     28        (WebKit::WebProcessPool::findReusableSuspendedPageProcess):
     29
    1302019-04-08  Don Olmstead  <don.olmstead@sony.com>
    231
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp

    r242889 r244075  
    7979#endif
    8080
    81 SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, Ref<WebProcessProxy>&& process, WebBackForwardListItem& item, uint64_t mainFrameID)
     81SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, Ref<WebProcessProxy>&& process, uint64_t mainFrameID)
    8282    : m_page(page)
    8383    , m_process(WTFMove(process))
    8484    , m_mainFrameID(mainFrameID)
    85     , m_registrableDomain(URL(URL(), item.url()))
    8685    , m_suspensionTimeoutTimer(RunLoop::main(), this, &SuspendedPageProxy::suspensionTimedOut)
    8786#if PLATFORM(IOS_FAMILY)
     
    8988#endif
    9089{
    91     item.setSuspendedPage(this);
    9290    m_process->incrementSuspendedPageCount();
    9391    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID(), *this);
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h

    r242889 r244075  
    4242    WTF_MAKE_FAST_ALLOCATED;
    4343public:
    44     SuspendedPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, WebBackForwardListItem&, uint64_t mainFrameID);
     44    SuspendedPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, uint64_t mainFrameID);
    4545    ~SuspendedPageProxy();
    4646
     
    4848    WebProcessProxy& process() { return m_process.get(); }
    4949    uint64_t mainFrameID() const { return m_mainFrameID; }
    50     const WebCore::RegistrableDomain& registrableDomain() const { return m_registrableDomain; }
    5150
    5251    bool failedToSuspend() const { return m_suspensionState == SuspensionState::FailedToSuspend; }
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r243961 r244075  
    742742        return false;
    743743
    744     if (!m_preferences->usesPageCache()) {
    745         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because page cache is disabled", m_process->processIdentifier());
    746         return false;
    747     }
    748 
    749744    // If the client forced a swap then it may not be Web-compatible to suspend the previous page because other windows may have an opener link to the page.
    750745    if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes) {
     
    764759
    765760    auto* fromItem = navigation.fromItem();
    766     if (!fromItem) {
    767         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because the navigation does not have a fromItem", m_process->processIdentifier());
    768         return false;
    769     }
    770761
    771762    // If the source and the destination back / forward list items are the same, then this is a client-side redirect. In this case,
    772763    // there is no need to suspend the previous page as there will be no way to get back to it.
    773     if (fromItem == m_backForwardList->currentItem()) {
     764    if (fromItem && fromItem == m_backForwardList->currentItem()) {
    774765        RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because this is a client-side redirect", m_process->processIdentifier());
    775766        return false;
    776767    }
    777768
    778     if (fromItem->url() != pageLoadState().url()) {
     769    if (fromItem && fromItem->url() != pageLoadState().url()) {
    779770        RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because fromItem's URL does not match the page URL.", m_process->processIdentifier());
    780771        ASSERT_NOT_REACHED();
     
    783774
    784775    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Suspending current page for process pid %i", m_process->processIdentifier());
    785     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *fromItem, *mainFrameID);
    786 
    787     LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), fromItem->itemID().logString());
     776    auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *mainFrameID);
     777
     778    LOG(ProcessSwapping, "WebPageProxy %" PRIu64 " created suspended page %s for process pid %i, back/forward item %s" PRIu64, pageID(), suspendedPage->loggingString(), m_process->processIdentifier(), fromItem ? fromItem->itemID().logString() : 0);
     779
     780    if (fromItem && m_preferences->usesPageCache())
     781        fromItem->setSuspendedPage(suspendedPage.get());
    788782
    789783    m_process->processPool().addSuspendedPage(WTFMove(suspendedPage));
  • trunk/Source/WebKit/UIProcess/WebProcessPool.cpp

    r243911 r244075  
    23572357{
    23582358    auto it = m_suspendedPages.findIf([&](auto& suspendedPage) {
    2359         return suspendedPage->registrableDomain() == registrableDomain && &suspendedPage->process().websiteDataStore() == &dataStore;
     2359        return suspendedPage->process().registrableDomain() == registrableDomain && &suspendedPage->process().websiteDataStore() == &dataStore;
    23602360    });
    23612361    if (it == m_suspendedPages.end())
  • trunk/Tools/ChangeLog

    r244073 r244075  
     12019-04-09  Chris Dumez  <cdumez@apple.com>
     2
     3        Loads using loadHTMLString() cause flashing when process-swapping
     4        https://bugs.webkit.org/show_bug.cgi?id=196714
     5        <rdar://problem/49637354>
     6
     7        Reviewed by Antti Koivisto.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     12
    1132019-04-09  Carlos Garcia Campos  <cgarcia@igalia.com>
    214
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r243961 r244075  
    23472347{
    23482348    auto processPoolConfiguration = psonProcessPoolConfiguration();
     2349    processPoolConfiguration.get().usesWebProcessCache = NO;
    23492350    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
    23502351
     
    23872388    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
    23882389    [webView loadRequest:request];
     2390
     2391    TestWebKitAPI::Util::run(&done);
     2392    done = false;
     2393
     2394    // We should have gone back to the apple.com process for this load since we reuse SuspendedPages' process when possible.
     2395    EXPECT_EQ(applePID, [webView _webProcessIdentifier]);
     2396}
     2397
     2398TEST(ProcessSwap, ReuseSuspendedProcessLoadHTMLString)
     2399{
     2400    auto processPoolConfiguration = psonProcessPoolConfiguration();
     2401    processPoolConfiguration.get().usesWebProcessCache = NO;
     2402    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     2403
     2404    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     2405    [webViewConfiguration setProcessPool:processPool.get()];
     2406    auto handler = adoptNS([[PSONScheme alloc] init]);
     2407    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
     2408
     2409    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     2410    auto delegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     2411    [webView setNavigationDelegate:delegate.get()];
     2412
     2413    NSString *htmlString = @"<html><body>TEST</body></html>";
     2414    [webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:@"pson://www.webkit.org/main1.html"]];
     2415
     2416    TestWebKitAPI::Util::run(&done);
     2417    done = false;
     2418
     2419    auto webkitPID = [webView _webProcessIdentifier];
     2420
     2421    [webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:@"pson://www.apple.com/main1.html"]];
     2422
     2423    TestWebKitAPI::Util::run(&done);
     2424    done = false;
     2425
     2426    auto applePID = [webView _webProcessIdentifier];
     2427
     2428    EXPECT_NE(webkitPID, applePID);
     2429
     2430    [webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:@"pson://www.webkit.org/main2.html"]];
     2431
     2432    TestWebKitAPI::Util::run(&done);
     2433    done = false;
     2434
     2435    // We should have gone back to the webkit.org process for this load since we reuse SuspendedPages' process when possible.
     2436    EXPECT_EQ(webkitPID, [webView _webProcessIdentifier]);
     2437
     2438    [webView loadHTMLString:htmlString baseURL:[NSURL URLWithString:@"pson://www.apple.com/main2.html"]];
    23892439
    23902440    TestWebKitAPI::Util::run(&done);
Note: See TracChangeset for help on using the changeset viewer.