Changeset 245198 in webkit


Ignore:
Timestamp:
May 10, 2019 4:25:28 PM (5 years ago)
Author:
Chris Dumez
Message:

[PSON] Prevent flashing when the process-swap is forced by the client
https://bugs.webkit.org/show_bug.cgi?id=197799

Reviewed by Geoffrey Garen.

When the process-swap is forced by the client, we would not construct a SuspendedPageProxy for
the previous page, which would cause a white/black flash upon navigation on macOS. The reason
we did not construct a SuspendedPageProxy is that it would be unsafe to keep the page around
in this case because other windows might have an opener link to the page when the swap is forced
and we need those opener / openee links to get severed.

The new approach to maintain the Web facing behavior without flashing is to create a suspended
page proxy for the previous page when the process swap is forced by the client. We then close
the page as soon as we can do so without flashing (when pageEnteredAcceleratedCompositingMode()
has been called).

  • UIProcess/SuspendedPageProxy.cpp:

(WebKit::SuspendedPageProxy::SuspendedPageProxy):
(WebKit::SuspendedPageProxy::close):
(WebKit::SuspendedPageProxy::pageEnteredAcceleratedCompositingMode):
(WebKit::SuspendedPageProxy::closeWithoutFlashing):
(WebKit::SuspendedPageProxy::didProcessRequestToSuspend):

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

(WebKit::WebPageProxy::suspendCurrentPageIfPossible):
(WebKit::WebPageProxy::commitProvisionalPage):

  • UIProcess/WebPageProxy.h:
Location:
trunk/Source/WebKit
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r245196 r245198  
     12019-05-10  Chris Dumez  <cdumez@apple.com>
     2
     3        [PSON] Prevent flashing when the process-swap is forced by the client
     4        https://bugs.webkit.org/show_bug.cgi?id=197799
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        When the process-swap is forced by the client, we would not construct a SuspendedPageProxy for
     9        the previous page, which would cause a white/black flash upon navigation on macOS. The reason
     10        we did not construct a SuspendedPageProxy is that it would be unsafe to keep the page around
     11        in this case because other windows might have an opener link to the page when the swap is forced
     12        and we need those opener / openee links to get severed.
     13
     14        The new approach to maintain the Web facing behavior without flashing is to create a suspended
     15        page proxy for the previous page when the process swap is forced by the client. We then close
     16        the page as soon as we can do so without flashing (when pageEnteredAcceleratedCompositingMode()
     17        has been called).
     18
     19        * UIProcess/SuspendedPageProxy.cpp:
     20        (WebKit::SuspendedPageProxy::SuspendedPageProxy):
     21        (WebKit::SuspendedPageProxy::close):
     22        (WebKit::SuspendedPageProxy::pageEnteredAcceleratedCompositingMode):
     23        (WebKit::SuspendedPageProxy::closeWithoutFlashing):
     24        (WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
     25        * UIProcess/SuspendedPageProxy.h:
     26        * UIProcess/WebPageProxy.cpp:
     27        (WebKit::WebPageProxy::suspendCurrentPageIfPossible):
     28        (WebKit::WebPageProxy::commitProvisionalPage):
     29        * UIProcess/WebPageProxy.h:
     30
    1312019-05-10  Brent Fulgham  <bfulgham@apple.com>
    232
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp

    r244464 r245198  
    7979#endif
    8080
    81 SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, Ref<WebProcessProxy>&& process, uint64_t mainFrameID)
     81SuspendedPageProxy::SuspendedPageProxy(WebPageProxy& page, Ref<WebProcessProxy>&& process, uint64_t mainFrameID, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode shouldDelayClosingUntilEnteringAcceleratedCompositingMode)
    8282    : m_page(page)
    8383    , m_process(WTFMove(process))
    8484    , m_mainFrameID(mainFrameID)
    85 #if PLATFORM(MAC)
    86     , m_shouldDelayClosingOnFailure(m_page.drawingArea() && m_page.drawingArea()->type() == DrawingAreaTypeTiledCoreAnimation)
    87 #endif
     85    , m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode(shouldDelayClosingUntilEnteringAcceleratedCompositingMode)
    8886    , m_suspensionTimeoutTimer(RunLoop::main(), this, &SuspendedPageProxy::suspensionTimedOut)
    8987#if PLATFORM(IOS_FAMILY)
     
    160158        return;
    161159
     160    RELEASE_LOG(ProcessSwapping, "%p - SuspendedPageProxy::close()", this);
    162161    m_isClosed = true;
    163162    m_process->send(Messages::WebPage::Close(), m_page.pageID());
     
    166165void SuspendedPageProxy::pageEnteredAcceleratedCompositingMode()
    167166{
    168     m_shouldDelayClosingOnFailure = false;
    169 
    170     if (m_suspensionState == SuspensionState::FailedToSuspend) {
    171         // We needed the failed suspended page to stay alive to avoid flashing. Now we can get rid of it.
     167    m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No;
     168
     169    if (m_suspensionState == SuspensionState::FailedToSuspend || m_shouldCloseWhenEnteringAcceleratedCompositingMode) {
     170        // We needed the suspended page to stay alive to avoid flashing. Now we can get rid of it.
    172171        close();
    173172    }
     173}
     174
     175void SuspendedPageProxy::closeWithoutFlashing()
     176{
     177    RELEASE_LOG(ProcessSwapping, "%p - SuspendedPageProxy::closeWithoutFlashing() shouldDelayClosingUntilEnteringAcceleratedCompositingMode? %d", this, m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode == ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::Yes);
     178    if (m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode == ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::Yes) {
     179        m_shouldCloseWhenEnteringAcceleratedCompositingMode = true;
     180        return;
     181    }
     182    close();
    174183}
    175184
     
    192201    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
    193202
    194     if (m_suspensionState == SuspensionState::FailedToSuspend && !m_shouldDelayClosingOnFailure)
     203    if (m_suspensionState == SuspensionState::FailedToSuspend && m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode == ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No)
    195204        close();
    196205
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.h

    r244144 r245198  
    3838class WebProcessProxy;
    3939
     40enum class ShouldDelayClosingUntilEnteringAcceleratedCompositingMode : bool { No, Yes };
     41
    4042class SuspendedPageProxy final: public IPC::MessageReceiver, public CanMakeWeakPtr<SuspendedPageProxy> {
    4143    WTF_MAKE_FAST_ALLOCATED;
    4244public:
    43     SuspendedPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, uint64_t mainFrameID);
     45    SuspendedPageProxy(WebPageProxy&, Ref<WebProcessProxy>&&, uint64_t mainFrameID, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode);
    4446    ~SuspendedPageProxy();
    4547
     
    5254    void waitUntilReadyToUnsuspend(CompletionHandler<void(SuspendedPageProxy*)>&&);
    5355    void unsuspend();
    54     void close();
    5556
    5657    void pageEnteredAcceleratedCompositingMode();
     58    void closeWithoutFlashing();
    5759
    5860#if !LOG_DISABLED
     
    6567    void suspensionTimedOut();
    6668
     69    void close();
     70
    6771    // IPC::MessageReceiver
    6872    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) final;
     
    7377    uint64_t m_mainFrameID;
    7478    bool m_isClosed { false };
    75     bool m_shouldDelayClosingOnFailure { false };
     79    ShouldDelayClosingUntilEnteringAcceleratedCompositingMode m_shouldDelayClosingUntilEnteringAcceleratedCompositingMode { ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No };
     80    bool m_shouldCloseWhenEnteringAcceleratedCompositingMode { false };
    7681
    7782    SuspensionState m_suspensionState { SuspensionState::Suspending };
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r245185 r245198  
    743743}
    744744
    745 bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient)
     745bool WebPageProxy::suspendCurrentPageIfPossible(API::Navigation& navigation, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient processSwapRequestedByClient, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode shouldDelayClosingUntilEnteringAcceleratedCompositingMode)
    746746{
    747747    m_lastSuspendedPage = nullptr;
     
    749749    if (!mainFrameID)
    750750        return false;
    751 
    752     // 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.
    753     if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes) {
    754         RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Not suspending current page for process pid %i because the swap was requested by the client", m_process->processIdentifier());
    755         return false;
    756     }
    757751
    758752    if (!hasCommittedAnyProvisionalLoads()) {
     
    782776
    783777    RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "suspendCurrentPageIfPossible: Suspending current page for process pid %i", m_process->processIdentifier());
    784     auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *mainFrameID);
     778    auto suspendedPage = std::make_unique<SuspendedPageProxy>(*this, m_process.copyRef(), *mainFrameID, shouldDelayClosingUntilEnteringAcceleratedCompositingMode);
    785779
    786780    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);
     781
     782    // If the client forced a swap then it may not be web-compatible to keep the previous page because other windows may have an opener link to it. We thus close it as soon as we
     783    // can do so without flashing.
     784    if (processSwapRequestedByClient == ProcessSwapRequestedByClient::Yes)
     785        suspendedPage->closeWithoutFlashing();
    787786
    788787    if (fromItem && m_preferences->usesPageCache())
     
    28852884    ASSERT(m_process.ptr() != &m_provisionalPage->process());
    28862885
     2886    auto shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::No;
     2887#if PLATFORM(MAC)
     2888    // On macOS, when not using UI-side compositing, we need to make sure we do not close the page in the previous process until we've
     2889    // entered accelerated compositing for the new page or we will flash on navigation.
     2890    if (drawingArea()->type() == DrawingAreaTypeTiledCoreAnimation)
     2891        shouldDelayClosingUntilEnteringAcceleratedCompositingMode = ShouldDelayClosingUntilEnteringAcceleratedCompositingMode::Yes;
     2892#endif
     2893
    28872894    processDidTerminate(ProcessTerminationReason::NavigationSwap);
    28882895
    28892896    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
    28902897    auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
    2891     bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient()) : false;
     2898    bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient(), shouldDelayClosingUntilEnteringAcceleratedCompositingMode) : false;
    28922899    m_process->removeWebPage(*this, m_websiteDataStore.ptr() == &m_provisionalPage->process().websiteDataStore() ? WebProcessProxy::EndsUsingDataStore::No : WebProcessProxy::EndsUsingDataStore::Yes);
    28932900
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r245079 r245198  
    15551555    void updateHiddenPageThrottlingAutoIncreases();
    15561556
    1557     bool suspendCurrentPageIfPossible(API::Navigation&, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient);
     1557    bool suspendCurrentPageIfPossible(API::Navigation&, Optional<uint64_t> mainFrameID, ProcessSwapRequestedByClient, ShouldDelayClosingUntilEnteringAcceleratedCompositingMode);
    15581558
    15591559    enum class ResetStateReason {
Note: See TracChangeset for help on using the changeset viewer.