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

Changeset 274565 in webkit


Ignore:
Timestamp:
Mar 17, 2021, 10:09:04 AM (5 years ago)
Author:
Chris Dumez
Message:

Maybe-regression(STP121): window.open flakily returning null
https://bugs.webkit.org/show_bug.cgi?id=222590
<rdar://problem/75211786>

Reviewed by Geoffrey Garen.

Source/WebKit:

This was an IPC ordering bug. WebPageProxy::DidCommitLoadForFrame is async and WebPageProxy::CreateNewPage is
sync. As a result, it was possible for the WebPageProxy::CreateNewPage to get processed *BEFORE* the
WebPageProxy::DidCommitLoadForFrame IPC. This was causing trouble because Safari rejects the popup opening if
the main frame is doing a provisional load.

To address the issue, introduce a new IPC::SendSyncOption::MaintainOrderingWithAsyncMessages flag and
use it on WebPageProxy::CreateNewPage sync IPC so that it gets processed in order with surrounding async
messages.

  • Platform/IPC/Connection.cpp:

(IPC::Connection::SyncMessageState::processIncomingMessage):
(IPC::Connection::sendSyncMessage):

  • Platform/IPC/Connection.h:
  • Platform/IPC/Decoder.cpp:

(IPC::Decoder::shouldMaintainOrderingWithAsyncMessages const):

  • Platform/IPC/Decoder.h:
  • Platform/IPC/Encoder.cpp:

(IPC::Encoder::setShouldMaintainOrderingWithAsyncMessages):

  • Platform/IPC/Encoder.h:
  • Platform/IPC/MessageFlags.h:
  • WebProcess/WebCoreSupport/WebChromeClient.cpp:

(WebKit::WebChromeClient::createWindow):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKit/ModalAlertsSPI.cpp:

(TestWebKitAPI::TEST):
(TestWebKitAPI::checkFrameLoadStateAndCreateNewPage):

Location:
trunk
Files:
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r274563 r274565  
     12021-03-17  Chris Dumez  <cdumez@apple.com>
     2
     3        Maybe-regression(STP121): window.open flakily returning null
     4        https://bugs.webkit.org/show_bug.cgi?id=222590
     5        <rdar://problem/75211786>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        This was an IPC ordering bug. WebPageProxy::DidCommitLoadForFrame is async and WebPageProxy::CreateNewPage is
     10        sync. As a result, it was possible for the WebPageProxy::CreateNewPage to get processed *BEFORE* the
     11        WebPageProxy::DidCommitLoadForFrame IPC. This was causing trouble because Safari rejects the popup opening if
     12        the main frame is doing a provisional load.
     13
     14        To address the issue, introduce a new IPC::SendSyncOption::MaintainOrderingWithAsyncMessages flag and
     15        use it on WebPageProxy::CreateNewPage sync IPC so that it gets processed in order with surrounding async
     16        messages.
     17
     18        * Platform/IPC/Connection.cpp:
     19        (IPC::Connection::SyncMessageState::processIncomingMessage):
     20        (IPC::Connection::sendSyncMessage):
     21        * Platform/IPC/Connection.h:
     22        * Platform/IPC/Decoder.cpp:
     23        (IPC::Decoder::shouldMaintainOrderingWithAsyncMessages const):
     24        * Platform/IPC/Decoder.h:
     25        * Platform/IPC/Encoder.cpp:
     26        (IPC::Encoder::setShouldMaintainOrderingWithAsyncMessages):
     27        * Platform/IPC/Encoder.h:
     28        * Platform/IPC/MessageFlags.h:
     29        * WebProcess/WebCoreSupport/WebChromeClient.cpp:
     30        (WebKit::WebChromeClient::createWindow):
     31
    1322021-03-17  Peng Liu  <peng.liu6@apple.com>
    233
  • trunk/Source/WebKit/Platform/IPC/Connection.cpp

    r274433 r274565  
    150150        auto locker = holdLock(m_mutex);
    151151        shouldDispatch = m_didScheduleDispatchMessagesWorkSet.add(&connection).isNewEntry;
     152        ASSERT(connection.m_incomingMessagesMutex.isHeld());
     153        if (message->shouldMaintainOrderingWithAsyncMessages()) {
     154            // This sync message should maintain ordering with async messages so we need to process the pending async messages first.
     155            while (!connection.m_incomingMessages.isEmpty())
     156                m_messagesToDispatchWhileWaitingForSyncReply.append(ConnectionAndIncomingMessage { connection, connection.m_incomingMessages.takeFirst() });
     157        }
    152158        m_messagesToDispatchWhileWaitingForSyncReply.append(ConnectionAndIncomingMessage { connection, WTFMove(message) });
    153159    }
     
    604610        sendOptions = sendOptions | IPC::SendOption::DispatchMessageEvenWhenWaitingForUnboundedSyncReply;
    605611
     612    if (sendSyncOptions.contains(IPC::SendSyncOption::MaintainOrderingWithAsyncMessages))
     613        encoder->setShouldMaintainOrderingWithAsyncMessages();
     614
    606615    auto messageName = encoder->messageName();
    607616    sendMessage(WTFMove(encoder), sendOptions);
  • trunk/Source/WebKit/Platform/IPC/Connection.h

    r274433 r274565  
    7272    UseFullySynchronousModeForTesting = 1 << 1,
    7373    ForceDispatchWhenDestinationIsWaitingForUnboundedSyncReply = 1 << 2,
     74    MaintainOrderingWithAsyncMessages = 1 << 3,
    7475};
    7576
  • trunk/Source/WebKit/Platform/IPC/Decoder.cpp

    r273204 r274565  
    148148}
    149149
     150bool Decoder::shouldMaintainOrderingWithAsyncMessages() const
     151{
     152    return m_messageFlags.contains(MessageFlags::MaintainOrderingWithAsyncMessages);
     153}
     154
    150155#if PLATFORM(MAC)
    151156void Decoder::setImportanceAssertion(std::unique_ptr<ImportanceAssertion> assertion)
  • trunk/Source/WebKit/Platform/IPC/Decoder.h

    r273204 r274565  
    6565    ShouldDispatchWhenWaitingForSyncReply shouldDispatchMessageWhenWaitingForSyncReply() const;
    6666    bool shouldUseFullySynchronousModeForTesting() const;
     67    bool shouldMaintainOrderingWithAsyncMessages() const;
    6768
    6869#if PLATFORM(MAC)
  • trunk/Source/WebKit/Platform/IPC/Encoder.cpp

    r274189 r274565  
    124124}
    125125
     126void Encoder::setShouldMaintainOrderingWithAsyncMessages()
     127{
     128    messageFlags().add(MessageFlags::MaintainOrderingWithAsyncMessages);
     129}
     130
    126131void Encoder::wrapForTesting(UniqueRef<Encoder>&& original)
    127132{
  • trunk/Source/WebKit/Platform/IPC/Encoder.h

    r274189 r274565  
    5757
    5858    void setFullySynchronousModeForTesting();
     59    void setShouldMaintainOrderingWithAsyncMessages();
    5960
    6061    void wrapForTesting(UniqueRef<Encoder>&&);
  • trunk/Source/WebKit/Platform/IPC/MessageFlags.h

    r271243 r274565  
    3232    DispatchMessageWhenWaitingForUnboundedSyncReply = 1 << 1,
    3333    UseFullySynchronousModeForTesting = 1 << 2,
     34    MaintainOrderingWithAsyncMessages = 1 << 3,
    3435};
    3536
     
    4950        IPC::MessageFlags::DispatchMessageWhenWaitingForSyncReply,
    5051        IPC::MessageFlags::DispatchMessageWhenWaitingForUnboundedSyncReply,
    51         IPC::MessageFlags::UseFullySynchronousModeForTesting
     52        IPC::MessageFlags::UseFullySynchronousModeForTesting,
     53        IPC::MessageFlags::MaintainOrderingWithAsyncMessages
    5254    >;
    5355};
  • trunk/Source/WebKit/WebProcess/WebCoreSupport/WebChromeClient.cpp

    r274521 r274565  
    284284    Optional<PageIdentifier> newPageID;
    285285    Optional<WebPageCreationParameters> parameters;
    286     if (!webProcess.parentProcessConnection()->sendSync(Messages::WebPageProxy::CreateNewPage(webFrame->info(), webFrame->page()->webPageProxyIdentifier(), navigationAction.resourceRequest(), windowFeatures, navigationActionData), Messages::WebPageProxy::CreateNewPage::Reply(newPageID, parameters), m_page.identifier()))
     286    if (!webProcess.parentProcessConnection()->sendSync(Messages::WebPageProxy::CreateNewPage(webFrame->info(), webFrame->page()->webPageProxyIdentifier(), navigationAction.resourceRequest(), windowFeatures, navigationActionData), Messages::WebPageProxy::CreateNewPage::Reply(newPageID, parameters), m_page.identifier(), IPC::Timeout::infinity(), IPC::SendSyncOption::MaintainOrderingWithAsyncMessages))
    287287        return nullptr;
    288288
  • trunk/Tools/ChangeLog

    r274562 r274565  
     12021-03-17  Chris Dumez  <cdumez@apple.com>
     2
     3        Maybe-regression(STP121): window.open flakily returning null
     4        https://bugs.webkit.org/show_bug.cgi?id=222590
     5        <rdar://problem/75211786>
     6
     7        Reviewed by Geoffrey Garen.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKit/ModalAlertsSPI.cpp:
     12        (TestWebKitAPI::TEST):
     13        (TestWebKitAPI::checkFrameLoadStateAndCreateNewPage):
     14
    1152021-03-17  Brent Fulgham  <bfulgham@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebKit/ModalAlertsSPI.cpp

    r248846 r274565  
    138138
    139139    Util::run(&done);
     140    openedWebView = nil;
     141}
     142
     143static WKPageRef checkFrameLoadStateAndCreateNewPage(WKPageRef page, WKURLRequestRef urlRequest, WKDictionaryRef features, WKEventModifiers modifiers, WKEventMouseButton mouseButton, const void *clientInfo)
     144{
     145    auto mainFrame = WKPageGetMainFrame(page);
     146    ASSERT(mainFrame);
     147    EXPECT_EQ(kWKFrameLoadStateCommitted, WKFrameGetFrameLoadState(mainFrame));
     148    done = true;
     149    return createNewPage(page, urlRequest, features, modifiers, mouseButton, clientInfo);
     150}
     151
     152TEST(WebKit, CreateNewPageDelegateFrameLoadState)
     153{
     154    for (unsigned i = 0; i < 25; ++i) {
     155        done = false;
     156        auto context = adoptWK(WKContextCreateWithConfiguration(nullptr));
     157        PlatformWebView webView(context.get());
     158
     159        WKPageUIClientV5 uiClient;
     160        memset(&uiClient, 0, sizeof(uiClient));
     161        uiClient.base.version = 5;
     162        uiClient.createNewPage = checkFrameLoadStateAndCreateNewPage;
     163        WKPageSetPageUIClient(webView.page(), &uiClient.base);
     164
     165        auto htmlString = Util::toWK("<script>open('about:blank', '_blank')</script>");
     166        WKPageLoadHTMLString(webView.page(), htmlString.get(), nullptr);
     167        Util::run(&done);
     168        openedWebView = nil;
     169    }
    140170}
    141171
Note: See TracChangeset for help on using the changeset viewer.