Changeset 245601 in webkit


Ignore:
Timestamp:
May 21, 2019 4:44:16 PM (5 years ago)
Author:
Chris Dumez
Message:

[PSON] Assertion hit when navigating back after a process swap forced by the client
https://bugs.webkit.org/show_bug.cgi?id=198006

Reviewed by Alex Christensen.

Source/WebKit:

After r245198, we construct a SuspendedPageProxy when a process-swap is forced by the client
and we delay to closing of the WebPage in the old WebProcess until it is safe to do so without
flashing (by calling SuspendedPageProxy::closeWithoutFlashing()). The issue is that our logic
deciding if we should reuse a SuspendedPageProxy's WebPage relied on the SuspendedPageProxy's
m_suspensionState not being set to FailedToSuspend. In the case of a process-swap forced by the
client with delayed page closing, the suspended state may be suspended but is still not usable
because it is about to get closed. We would wrongly believe there is a WebPage to be reused so
the ProvisionalPageProxy would construct a proxy for the main frame in its constructor, we would
then hit the ASSERT(!m_mainFrame) assertion in ProvisionalPageProxy::didCreateMainFrame() when
the WebContent process would unexpectedly create a main frame.

To address the issue, stop relying on the suspended state to determine if we can reuse a WebPage
or not and introduce a new pageIsClosedOrClosing() getter on the SuspendedPageProxy instead
which indicates if the WebPage in the WebContent process has been closed or is about to be.

  • UIProcess/ProvisionalPageProxy.cpp:

(WebKit::ProvisionalPageProxy::ProvisionalPageProxy):

  • UIProcess/SuspendedPageProxy.cpp:

(WebKit::SuspendedPageProxy::pageEnteredAcceleratedCompositingMode):
(WebKit::SuspendedPageProxy::pageIsClosedOrClosing const):
(WebKit::SuspendedPageProxy::didProcessRequestToSuspend):

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

(WebKit::WebPageProxy::receivedNavigationPolicyDecision):

Tools:

Add API test coverage.

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

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r245599 r245601  
     12019-05-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [PSON] Assertion hit when navigating back after a process swap forced by the client
     4        https://bugs.webkit.org/show_bug.cgi?id=198006
     5
     6        Reviewed by Alex Christensen.
     7
     8        After r245198, we construct a SuspendedPageProxy when a process-swap is forced by the client
     9        and we delay to closing of the WebPage in the old WebProcess until it is safe to do so without
     10        flashing (by calling SuspendedPageProxy::closeWithoutFlashing()). The issue is that our logic
     11        deciding if we should reuse a SuspendedPageProxy's WebPage relied on the SuspendedPageProxy's
     12        m_suspensionState not being set to FailedToSuspend. In the case of a process-swap forced by the
     13        client with delayed page closing, the suspended state may be suspended but is still not usable
     14        because it is about to get closed. We would wrongly believe there is a WebPage to be reused so
     15        the ProvisionalPageProxy would construct a proxy for the main frame in its constructor, we would
     16        then hit the ASSERT(!m_mainFrame) assertion in ProvisionalPageProxy::didCreateMainFrame() when
     17        the WebContent process would unexpectedly create a main frame.
     18
     19        To address the issue, stop relying on the suspended state to determine if we can reuse a WebPage
     20        or not and introduce a new pageIsClosedOrClosing() getter on the SuspendedPageProxy instead
     21        which indicates if the WebPage in the WebContent process has been closed or is about to be.
     22
     23        * UIProcess/ProvisionalPageProxy.cpp:
     24        (WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
     25        * UIProcess/SuspendedPageProxy.cpp:
     26        (WebKit::SuspendedPageProxy::pageEnteredAcceleratedCompositingMode):
     27        (WebKit::SuspendedPageProxy::pageIsClosedOrClosing const):
     28        (WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
     29        * UIProcess/SuspendedPageProxy.h:
     30        * UIProcess/WebPageProxy.cpp:
     31        (WebKit::WebPageProxy::receivedNavigationPolicyDecision):
     32
    1332019-05-21  Per Arne Vollan  <pvollan@apple.com>
    234
  • trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp

    r244540 r245601  
    6262#endif
    6363{
     64    RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "ProvisionalPageProxy: pageID = %" PRIu64 " navigationID = %" PRIu64 " suspendedPage: %p", m_page.pageID(), navigationID, suspendedPage.get());
     65
    6466    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID(), *this);
    6567    m_process->addProvisionalPageProxy(*this);
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp

    r245198 r245601  
    167167    m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No;
    168168
    169     if (m_suspensionState == SuspensionState::FailedToSuspend || m_shouldCloseWhenEnteringAcceleratedCompositingMode) {
     169    if (m_shouldCloseWhenEnteringAcceleratedCompositingMode) {
    170170        // We needed the suspended page to stay alive to avoid flashing. Now we can get rid of it.
    171171        close();
    172172    }
     173}
     174
     175bool SuspendedPageProxy::pageIsClosedOrClosing() const
     176{
     177    return m_isClosed || m_shouldCloseWhenEnteringAcceleratedCompositingMode;
    173178}
    174179
     
    201206    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
    202207
    203     if (m_suspensionState == SuspensionState::FailedToSuspend && m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode == ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No)
    204         close();
     208    if (m_suspensionState == SuspensionState::FailedToSuspend)
     209        closeWithoutFlashing();
    205210
    206211    if (m_readyToUnsuspendHandler)
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h

    r245198 r245601  
    5050    uint64_t mainFrameID() const { return m_mainFrameID; }
    5151
    52     bool failedToSuspend() const { return m_suspensionState == SuspensionState::FailedToSuspend; }
     52    bool pageIsClosedOrClosing() const;
    5353
    5454    void waitUntilReadyToUnsuspend(CompletionHandler<void(SuspendedPageProxy*)>&&);
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r245595 r245601  
    28272827
    28282828            auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
    2829             if (suspendedPage && suspendedPage->failedToSuspend())
     2829            if (suspendedPage && suspendedPage->pageIsClosedOrClosing())
    28302830                suspendedPage = nullptr;
    28312831
  • trunk/Tools/ChangeLog

    r245566 r245601  
     12019-05-21  Chris Dumez  <cdumez@apple.com>
     2
     3        [PSON] Assertion hit when navigating back after a process swap forced by the client
     4        https://bugs.webkit.org/show_bug.cgi?id=198006
     5
     6        Reviewed by Alex Christensen.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     11
    1122019-05-21  Carlos Garcia Campos  <cgarcia@igalia.com>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r245540 r245601  
    42584258        decisionHandler(_WKNavigationActionPolicyAllowInNewProcess);
    42594259    };
    4260     [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webit.org/3"]]];
     4260    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org/3"]]];
    42614261    TestWebKitAPI::Util::run(&done);
    42624262    done = false;
     
    42664266    EXPECT_EQ(2u, seenPIDs.size());
    42674267    EXPECT_NE(pid1, pid3);
     4268}
     4269
     4270enum class WithDelay : bool { No, Yes };
     4271static void runAPIControlledProcessSwappingThenBackTest(WithDelay withDelay)
     4272{
     4273    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     4274    auto handler = adoptNS([[PSONScheme alloc] initWithBytes:"Hello World!"]);
     4275    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"PSON"];
     4276   
     4277    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     4278    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     4279    [webView setNavigationDelegate:navigationDelegate.get()];
     4280
     4281    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.webkit.org"]]];
     4282    TestWebKitAPI::Util::run(&done);
     4283    done = false;
     4284   
     4285    auto pid1 = [webView _webProcessIdentifier];
     4286   
     4287    navigationDelegate->decidePolicyForNavigationAction = ^(WKNavigationAction *, void (^decisionHandler)(WKNavigationActionPolicy)) {
     4288        decisionHandler(_WKNavigationActionPolicyAllowInNewProcess);
     4289    };
     4290   
     4291    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.apple.com"]]];
     4292    TestWebKitAPI::Util::run(&done);
     4293    done = false;
     4294   
     4295    auto pid2 = [webView _webProcessIdentifier];
     4296    EXPECT_NE(pid1, pid2);
     4297   
     4298    // Give time to the suspended WebPage to close.
     4299    if (withDelay == WithDelay::Yes)
     4300        TestWebKitAPI::Util::sleep(0.1);
     4301   
     4302    navigationDelegate->decidePolicyForNavigationAction = nil;
     4303    [webView goBack];
     4304    TestWebKitAPI::Util::run(&done);
     4305    done = false;
     4306   
     4307    EXPECT_EQ(pid1, [webView _webProcessIdentifier]);
     4308}
     4309
     4310TEST(ProcessSwap, APIControlledProcessSwappingThenBackWithDelay)
     4311{
     4312    runAPIControlledProcessSwappingThenBackTest(WithDelay::Yes);
     4313}
     4314
     4315TEST(ProcessSwap, APIControlledProcessSwappingThenBackWithoutDelay)
     4316{
     4317    runAPIControlledProcessSwappingThenBackTest(WithDelay::No);
    42684318}
    42694319
Note: See TracChangeset for help on using the changeset viewer.