Changeset 244243 in webkit


Ignore:
Timestamp:
Apr 13, 2019 9:22:34 PM (5 years ago)
Author:
Chris Dumez
Message:

[ Mac Debug ] TestWebKitAPI.ProcessSwap.ReuseSuspendedProcessForRegularNavigationRetainBundlePage is a flaky crash
https://bugs.webkit.org/show_bug.cgi?id=196548
<rdar://problem/49567254>

Reviewed by Darin Adler.

Update ProvisionalPageProxy methods to more consistently ignore unexpected IPC from the process. Previously,
some of the methods were doing this, but some other like didFailProvisionalLoadForFrame() weren't and this
was leading to this flaky crash. The issue is that if we do the load in an existing process that was recently
doing, there may be leftover IPC for the same pageID and this IPC gets received by the ProvisionalPageProxy
even though it is from a previous navigation. For this reason, the ProvisionalPageProxy should ignore all
incoming IPC that is not for its associated navigation.

  • UIProcess/ProvisionalPageProxy.cpp:

(WebKit::ProvisionalPageProxy::didPerformClientRedirect):
(WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
(WebKit::ProvisionalPageProxy::didNavigateWithNavigationData):
(WebKit::ProvisionalPageProxy::didChangeProvisionalURLForFrame):
(WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::ProvisionalPageProxy::decidePolicyForResponse):
(WebKit::ProvisionalPageProxy::didPerformServerRedirect):
(WebKit::ProvisionalPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionSync):

Location:
trunk/Source/WebKit
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r244242 r244243  
     12019-04-13  Chris Dumez  <cdumez@apple.com>
     2
     3        [ Mac Debug ] TestWebKitAPI.ProcessSwap.ReuseSuspendedProcessForRegularNavigationRetainBundlePage is a flaky crash
     4        https://bugs.webkit.org/show_bug.cgi?id=196548
     5        <rdar://problem/49567254>
     6
     7        Reviewed by Darin Adler.
     8
     9        Update ProvisionalPageProxy methods to more consistently ignore unexpected IPC from the process. Previously,
     10        some of the methods were doing this, but some other like didFailProvisionalLoadForFrame() weren't and this
     11        was leading to this flaky crash. The issue is that if we do the load in an existing process that was recently
     12        doing, there may be leftover IPC for the same pageID and this IPC gets received by the ProvisionalPageProxy
     13        even though it is from a previous navigation. For this reason, the ProvisionalPageProxy should ignore all
     14        incoming IPC that is not for its associated navigation.
     15
     16        * UIProcess/ProvisionalPageProxy.cpp:
     17        (WebKit::ProvisionalPageProxy::didPerformClientRedirect):
     18        (WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
     19        (WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
     20        (WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
     21        (WebKit::ProvisionalPageProxy::didNavigateWithNavigationData):
     22        (WebKit::ProvisionalPageProxy::didChangeProvisionalURLForFrame):
     23        (WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionAsync):
     24        (WebKit::ProvisionalPageProxy::decidePolicyForResponse):
     25        (WebKit::ProvisionalPageProxy::didPerformServerRedirect):
     26        (WebKit::ProvisionalPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame):
     27        (WebKit::ProvisionalPageProxy::decidePolicyForNavigationActionSync):
     28
    1292019-04-13  Wenson Hsieh  <wenson_hsieh@apple.com>
    230
  • trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp

    r244161 r244243  
    184184}
    185185
     186inline bool ProvisionalPageProxy::validateInput(uint64_t frameID, const Optional<uint64_t>& navigationID)
     187{
     188    // If the previous provisional load used an existing process, we may receive leftover IPC for a previous navigation, which we need to ignore.
     189    if (!m_mainFrame || m_mainFrame->frameID() != frameID)
     190        return false;
     191
     192    return !navigationID || *navigationID == m_navigationID;
     193}
     194
    186195void ProvisionalPageProxy::didCreateMainFrame(uint64_t frameID)
    187196{
     
    213222void ProvisionalPageProxy::didPerformClientRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
    214223{
     224    if (!validateInput(frameID))
     225        return;
     226
    215227    m_page.didPerformClientRedirectShared(m_process.copyRef(), sourceURLString, destinationURLString, frameID);
    216228}
     
    218230void ProvisionalPageProxy::didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&& url, URL&& unreachableURL, const UserData& userData)
    219231{
    220     // If the previous provisional load used the same process, we may receive IPC for this previous provisional's main frame that we need to ignore.
    221     if (!m_mainFrame || m_mainFrame->frameID() != frameID)
     232    if (!validateInput(frameID, navigationID))
    222233        return;
    223234
     
    239250void ProvisionalPageProxy::didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError& error, const UserData& userData)
    240251{
     252    if (!validateInput(frameID, navigationID))
     253        return;
     254
    241255    RELEASE_LOG_ERROR_IF_ALLOWED(ProcessSwapping, "didFailProvisionalLoadForFrame: pageID = %" PRIu64 ", frameID = %" PRIu64 ", navigationID = %" PRIu64, m_page.pageID(), frameID, navigationID);
     256    ASSERT(!m_provisionalLoadURL.isNull());
    242257    m_provisionalLoadURL = { };
    243258
     
    251266void ProvisionalPageProxy::didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo& certificateInfo, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData& userData)
    252267{
    253     // If the previous provisional load used the same process, we may receive IPC for this previous provisional's main frame that we need to ignore.
    254     if (!m_mainFrame || m_mainFrame->frameID() != frameID)
     268    if (!validateInput(frameID, navigationID))
    255269        return;
    256270
     
    265279void ProvisionalPageProxy::didNavigateWithNavigationData(const WebNavigationDataStore& store, uint64_t frameID)
    266280{
     281    if (!validateInput(frameID))
     282        return;
     283
    267284    m_page.didNavigateWithNavigationDataShared(m_process.copyRef(), store, frameID);
    268285}
     
    270287void ProvisionalPageProxy::didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&& url)
    271288{
     289    if (!validateInput(frameID, navigationID))
     290        return;
     291
    272292    m_page.didChangeProvisionalURLForFrameShared(m_process.copyRef(), frameID, navigationID, WTFMove(url));
    273293}
     
    277297    WebCore::ResourceRequest&& request, IPC::FormDataReference&& requestBody, WebCore::ResourceResponse&& redirectResponse, const UserData& userData, uint64_t listenerID)
    278298{
    279     ASSERT(m_mainFrame);
    280     ASSERT(m_mainFrame->frameID() == frameID);
     299    if (!validateInput(frameID, navigationID))
     300        return;
     301
    281302    m_page.decidePolicyForNavigationActionAsyncShared(m_process.copyRef(), frameID, WTFMove(frameSecurityOrigin), identifier, navigationID, WTFMove(navigationActionData),
    282303        WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, listenerID);
     
    286307    uint64_t navigationID, const WebCore::ResourceResponse& response, const WebCore::ResourceRequest& request, bool canShowMIMEType, const String& downloadAttribute, uint64_t listenerID, const UserData& userData)
    287308{
     309    if (!validateInput(frameID, navigationID))
     310        return;
     311
    288312    m_page.decidePolicyForResponseShared(m_process.copyRef(), frameID, frameSecurityOrigin, identifier, navigationID, response, request, canShowMIMEType, downloadAttribute, listenerID, userData);
    289313}
     
    291315void ProvisionalPageProxy::didPerformServerRedirect(const String& sourceURLString, const String& destinationURLString, uint64_t frameID)
    292316{
     317    if (!validateInput(frameID))
     318        return;
     319
    293320    m_page.didPerformServerRedirectShared(m_process.copyRef(), sourceURLString, destinationURLString, frameID);
    294321}
     
    296323void ProvisionalPageProxy::didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&& request, const UserData& userData)
    297324{
     325    if (!validateInput(frameID, navigationID))
     326        return;
     327
    298328    m_page.didReceiveServerRedirectForProvisionalLoadForFrameShared(m_process.copyRef(), frameID, navigationID, WTFMove(request), userData);
    299329}
     
    314344    const UserData& userData, Messages::WebPageProxy::DecidePolicyForNavigationActionSync::DelayedReply&& reply)
    315345{
    316     ASSERT(isMainFrame);
    317     ASSERT(!m_mainFrame || m_mainFrame->frameID() == frameID);
    318 
    319     if (!isMainFrame || (m_mainFrame && m_mainFrame->frameID() != frameID)) {
     346    if (!isMainFrame || (m_mainFrame && m_mainFrame->frameID() != frameID) || navigationID != m_navigationID) {
    320347        reply(identifier, WebCore::PolicyAction::Ignore, navigationID, DownloadID(), WTF::nullopt);
    321348        return;
  • trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.h

    r244225 r244243  
    119119
    120120    void initializeWebPage();
     121    bool validateInput(uint64_t frameID, const Optional<uint64_t>& navigationID = WTF::nullopt);
    121122
    122123    WebPageProxy& m_page;
Note: See TracChangeset for help on using the changeset viewer.