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

Changeset 239993 in webkit


Ignore:
Timestamp:
Jan 15, 2019, 11:01:43 AM (8 years ago)
Author:
Chris Dumez
Message:

Regression(PSON) View becomes blank after click a cross-site download link
​https://bugs.webkit.org/show_bug.cgi?id=193361
<rdar://problem/47099573>

Reviewed by Geoff Garen.

Source/WebCore:

  • loader/FrameLoader.cpp:

(WebCore::FrameLoader::commitProvisionalLoad):
When restoring from PageCache, make sure we notify the client that the load was committed
*before* we tell it that the navigation is complete. This would confuse the ProvisionalPageProxy
logic in the UIProcess.

Source/WebKit:

The issue tracked by rdar://problem/47099573 is that a provisional load may get
canceled (or converted into a download) *after* we've decided to process-swap.
In such cases, the view should keep displaying the current site and it should
still be interactive. However, with the previous PSON model, the view (pageProxy)
would have already swapped to the new process and would end up displaying the
initially empty document.

To address the issue, this patch introduces the concept of a provisional load
in the UIProcess, handled by a ProvisionalPageProxy which has its own privisional
process. The WebPageProxy owns the ProvisionalPageProxy but we do not commit the
provisional page until after the load was committed in the new process. This means
that the view / WebPageProxy keeps using the old process and displays the current
content until a load has committed in the provisional page. If no load commits
in the provisional process (e.g. because the load is cancelled or converted into
a download), then we merely destroy the ProvisionalPageProxy and terminate its
process, without impacting the WebPageProxy.

  • Shared/WebPageCreationParameters.cpp:

(WebKit::WebPageCreationParameters::encode const):
(WebKit::WebPageCreationParameters::decode):

  • Shared/WebPageCreationParameters.h:

Rename isSwapFromSuspended to isProcessSwap for clarity as we always want to
delay attaching the drawing area in case of a process-swap, no matter what
now that the previous process is kept alive until the provisional load is
committed in the new process.

  • Shared/WebPolicyAction.h:

Drop Suspend policy action. At decidePolicyForNavigationAction time, in case of
process-swap, we now tell the previous process to simply ignore the load, while
we create a ProvisionalPageProxy to do the new load in a new process.
Suspension of the previous page in the old process, happens later, when a load
is actually committed in the new process.

  • Sources.txt:

Add new ProvisionalPageProxy file.

  • UIProcess/API/Cocoa/WKWebView.mm:

(-[WKWebView _killWebContentProcessAndResetState]):
When calling _killWebContentProcessAndResetState on a WKWebView, kill both the current
process and the provisional one, to maintain previous behavior in our API tests.

  • UIProcess/PageClient.h:

Tiny build fix.

  • UIProcess/ProvisionalPageProxy.cpp: Added.

(WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
(WebKit::ProvisionalPageProxy::takeDrawingArea):
(WebKit::ProvisionalPageProxy::cancel):
(WebKit::ProvisionalPageProxy::initializeWebPage):
(WebKit::ProvisionalPageProxy::loadDataWithNavigation):
(WebKit::ProvisionalPageProxy::loadRequestWithNavigation):
(WebKit::ProvisionalPageProxy::goToBackForwardItem):
(WebKit::ProvisionalPageProxy::didCreateMainFrame):
(WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
(WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
(WebKit::ProvisionalPageProxy::didReceiveMessage):
(WebKit::ProvisionalPageProxy::didReceiveSyncMessage):

  • UIProcess/ProvisionalPageProxy.h: Added.

(WebKit::ProvisionalPageProxy::page):
(WebKit::ProvisionalPageProxy::mainFrame const):
(WebKit::ProvisionalPageProxy::process):
(WebKit::ProvisionalPageProxy::processSwapRequestedByClient const):
(WebKit::ProvisionalPageProxy::navigationID const):
Add new ProvisionalPageProxy class to wrap the provisional load in the new process
after a swap. The provisional page is owned by the WebPageProxy and we only commit
the provisional page when the load is committed. Until then, the WebPageProxy keeps
using the old process and displaying the current content.

  • UIProcess/SuspendedPageProxy.cpp:

(WebKit::SuspendedPageProxy::~SuspendedPageProxy):
(WebKit::SuspendedPageProxy::unsuspend):
(WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
Unregister the SuspendedPageProxy as an IPC message receiver a little bit earlier
when we're going to unsuspend it. This avoids conflicting with the ProvisionalPageProxy
which tries to register itself as an IPC message receiver for the same pageID when
a process-swap occurs and we're switching to a suspended page.

  • UIProcess/WebFrameProxy.cpp:

(WebKit::WebFrameProxy::isMainFrame const):
WebFrameProxy::isMainFrame() relies on checking that the frame is the WebPageProxy's m_mainFrame.
Now that the WebPageProxy can have a ProvisionalPageProxy, also check if it is the ProvisionalPageProxy's
m_mainFrame to maintain previous behavior.

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::swapToWebProcess):
swapToWebProcess() no longer takes care of unsuspending the SuspendedPage because we now call swapToWebProcess()
later, when a load is actually committed in the provisional page / process. swapToWebProcess() now also needs
to initialize some data members such as the drawing area and the main frame as it is transferring them over from
the ProvisionalPageProxy which started the provisional load.

(WebKit::WebPageProxy::finishAttachingToWebProcess):
We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
committed in the provisional process.

(WebKit::WebPageProxy::initializeWebPage):

  • We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been committed in the provisional process.
  • Factor some code out to WebPageProxy::setDrawingArea() so that it can be shared with swapToWebProcess().

(WebKit::WebPageProxy::loadRequestWithNavigation):
Only call setPendingAPIRequestURL() in loadRequestWithNavigation() only if ShouldTreatAsContinuingLoad is not
Yes. This avoids hitting some assertions as this was already called during the first API call if needed.

(WebKit::WebPageProxy::receivedNavigationPolicyDecision):
In case of process swap, tell the previous process to ignore the load instead of suspending it right away.
Suspension now happens later, only if we end up committing the provisional load in the new process.
Also discard the SuspendedPage if it failed to suspend (we only reuse its process in this case). This used
to happen a bit later but it is clearer if we do this as early as possible I think.

(WebKit::WebPageProxy::commitProvisionalPage):
When the load is committed in the new process, we call WebPageProxy::commitProvisionalPage(). It takes care of:

  • Actually swapping the WebPageProxy to the new process by calling processDidTerminate() / swapToWebProcess().
  • Suspending the current page.
  • Letting the client know the load is comitted
  • Destroy the ProvisionalPageProxy.

This work used to happen earlier in continueNavigationInNewProcess().

(WebKit::WebPageProxy::continueNavigationInNewProcess):
Moved some of the logic to commitProvisionalPage(). We now merely start the load in a new ProvisionalPageProxy,
without actually having the WebPageProxy switch to the new process yet.

(WebKit::WebPageProxy::didCreateMainFrame):
(WebKit::WebPageProxy::didCreateWindow):
Drop some code that is no longer needed, now that the ProvisionalPageProxy takes care of this.

(WebKit::WebPageProxy::didDestroyNavigation):
On process-swap, when telling the previous process to ignore the load and starting the new load in a new
ProvisionalPageProxy, the previous WebPage attempts to destroy the navigation. In this case, we ignore
the call since the navigation is merely taken over by the ProvisionalPageProxy.

(WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
Moved some PSON logic to the ProvisionalPageProxy instead.

(WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
When didFailProvisionalLoadForFrame() is called for a ProvisionalPageProxy, destroy it.

(WebKit::WebPageProxy::decidePolicyForNavigationActionAsync):
(WebKit::WebPageProxy::decidePolicyForResponse):
Capture the process in the lambda, to make sure we send the policy decision to the same process that
asked for it, so as to not get confused by process swaps.

(WebKit::WebPageProxy::resetState):
Drop some code that is no longer needed.

(WebKit::WebPageProxy::creationParameters):
Move the hasRegisteredServiceWorkers flag initialization from the call site to here now that we have
more than one call site. This was just some bad factoring.

(WebKit::WebPageProxy::PageProcessOverride::PageProcessOverride):
(WebKit::WebPageProxy::PageProcessOverride::~PageProcessOverride):

  • UIProcess/WebPageProxy.h:

(WebKit::WebPageProxy::temporarilyOverrideProcess):
Add utility class to temporarily override the WebPageProxy's m_process with the provisional one when
the ProvisionalPageProxy interacts with the WebPageProxy.

  • UIProcess/WebProcessProxy.cpp:

(WebKit::WebProcessProxy::hasProvisionalPageWithID const):
(WebKit::WebProcessProxy::updateBackForwardItem):
Before updating a BackForwardListItem, we normally make sure the process has a WebPageProxy with the
item's pageID. We have to tweak the logic because there may now be no WebPageProxy with this pageID
associated with this process yet, because it is still a ProvisionalPageProxy.

(WebKit::WebProcessProxy::canTerminateChildProcess):
Do not terminate the WebProcess if there are ProvisionalPageProxy objects using it.

  • UIProcess/WebProcessProxy.h:

(WebKit::WebProcessProxy::addProvisionalPageProxy):
(WebKit::WebProcessProxy::removeProvisionalPageProxy):

  • WebKit.xcodeproj/project.pbxproj:
  • WebProcess/WebPage/WebFrame.cpp:

(WebKit::toPolicyAction):
(WebKit::WebFrame::didReceivePolicyDecision):
Stop dealing with WebPolicyAction::Suspend as it no longer exists.

  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::reinitializeWebPage):
(WebKit::WebPage::didReceivePolicyDecision):

(WebKit::WebPage::setIsSuspended):
Suspend the Page when setIsSuspended(true) is called, now that there is no longer a WebPolicyAction::Suspend.
setIsSuspended(true) IPC is sent when we actually commit the provisional page.

  • WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:

(WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:

(-[PSONNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):

LayoutTests:

Skip test testing the cross-process DOMWindow API as I broke it with this patch.
The feature is far from ready and off by default anyway. I will add support back
in a follow-up.

  • platform/wk2/TestExpectations:
Location:
trunk
Files:
2 added
24 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r239991 r239993  
     12019-01-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Regression(PSON) View becomes blank after click a cross-site download link
     4        https://bugs.webkit.org/show_bug.cgi?id=193361
     5        <rdar://problem/47099573>
     6
     7        Reviewed by Geoff Garen.
     8
     9        Skip test testing the cross-process DOMWindow API as I broke it with this patch.
     10        The feature is far from ready and off by default anyway. I will add support back
     11        in a follow-up.
     12
     13        * platform/wk2/TestExpectations:
     14
    1152019-01-15  Zalan Bujtas  <zalan@apple.com>
    216
  • trunk/LayoutTests/platform/wk2/TestExpectations

    r239337 r239993  
    734734http/tests/resourceLoadStatistics/cap-cache-max-age-for-prevalent-resource.html [ Skip ]
    735735
    736 # Process swapping is only implemented on WebKit2.
    737 http/tests/navigation/process-swap-window-open.html [ Pass ]
     736# This feature is currently disabled by default and unfinished <rdar://problem/38925077>.
     737http/tests/navigation/process-swap-window-open.html [ Skip ]
    738738
    739739# Cross-Origin-Resource-Policy response header is only implemented in WebKit2.
  • trunk/Source/WebCore/ChangeLog

    r239991 r239993  
     12019-01-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Regression(PSON) View becomes blank after click a cross-site download link
     4        https://bugs.webkit.org/show_bug.cgi?id=193361
     5        <rdar://problem/47099573>
     6
     7        Reviewed by Geoff Garen.
     8
     9        * loader/FrameLoader.cpp:
     10        (WebCore::FrameLoader::commitProvisionalLoad):
     11        When restoring from PageCache, make sure we notify the client that the load was committed
     12        *before* we tell it that the navigation is complete. This would confuse the ProvisionalPageProxy
     13        logic in the UIProcess.
     14
    1152019-01-15  Zalan Bujtas  <zalan@apple.com>
    216
  • trunk/Source/WebCore/loader/FrameLoader.cpp

    r239726 r239993  
    20332033        Optional<HasInsecureContent> hasInsecureContent = cachedPage->cachedMainFrame()->hasInsecureContent();
    20342034
     2035        dispatchDidCommitLoad(hasInsecureContent);
     2036
    20352037        // FIXME: This API should be turned around so that we ground CachedPage into the Page.
    20362038        cachedPage->restore(*m_frame.page());
    2037 
    2038         dispatchDidCommitLoad(hasInsecureContent);
    20392039
    20402040#if PLATFORM(IOS_FAMILY)
  • trunk/Source/WebKit/ChangeLog

    r239988 r239993  
     12019-01-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Regression(PSON) View becomes blank after click a cross-site download link
     4        https://bugs.webkit.org/show_bug.cgi?id=193361
     5        <rdar://problem/47099573>
     6
     7        Reviewed by Geoff Garen.
     8
     9        The issue tracked by rdar://problem/47099573 is that a provisional load may get
     10        canceled (or converted into a download) *after* we've decided to process-swap.
     11        In such cases, the view should keep displaying the current site and it should
     12        still be interactive. However, with the previous PSON model, the view (pageProxy)
     13        would have already swapped to the new process and would end up displaying the
     14        initially empty document.
     15
     16        To address the issue, this patch introduces the concept of a provisional load
     17        in the UIProcess, handled by a ProvisionalPageProxy which has its own privisional
     18        process. The WebPageProxy owns the ProvisionalPageProxy but we do not commit the
     19        provisional page until after the load was committed in the new process. This means
     20        that the view / WebPageProxy keeps using the old process and displays the current
     21        content until a load has committed in the provisional page. If no load commits
     22        in the provisional process (e.g. because the load is cancelled or converted into
     23        a download), then we merely destroy the ProvisionalPageProxy and terminate its
     24        process, without impacting the WebPageProxy.
     25
     26        * Shared/WebPageCreationParameters.cpp:
     27        (WebKit::WebPageCreationParameters::encode const):
     28        (WebKit::WebPageCreationParameters::decode):
     29        * Shared/WebPageCreationParameters.h:
     30        Rename isSwapFromSuspended to isProcessSwap for clarity as we always want to
     31        delay attaching the drawing area in case of a process-swap, no matter what
     32        now that the previous process is kept alive until the provisional load is
     33        committed in the new process.
     34
     35        * Shared/WebPolicyAction.h:
     36        Drop Suspend policy action. At decidePolicyForNavigationAction time, in case of
     37        process-swap, we now tell the previous process to simply ignore the load, while
     38        we create a ProvisionalPageProxy to do the new load in a new process.
     39        Suspension of the previous page in the old process, happens later, when a load
     40        is actually committed in the new process.
     41
     42        * Sources.txt:
     43        Add new ProvisionalPageProxy file.
     44
     45        * UIProcess/API/Cocoa/WKWebView.mm:
     46        (-[WKWebView _killWebContentProcessAndResetState]):
     47        When calling _killWebContentProcessAndResetState on a WKWebView, kill both the current
     48        process and the provisional one, to maintain previous behavior in our API tests.
     49
     50        * UIProcess/PageClient.h:
     51        Tiny build fix.
     52
     53        * UIProcess/ProvisionalPageProxy.cpp: Added.
     54        (WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
     55        (WebKit::ProvisionalPageProxy::~ProvisionalPageProxy):
     56        (WebKit::ProvisionalPageProxy::takeDrawingArea):
     57        (WebKit::ProvisionalPageProxy::cancel):
     58        (WebKit::ProvisionalPageProxy::initializeWebPage):
     59        (WebKit::ProvisionalPageProxy::loadDataWithNavigation):
     60        (WebKit::ProvisionalPageProxy::loadRequestWithNavigation):
     61        (WebKit::ProvisionalPageProxy::goToBackForwardItem):
     62        (WebKit::ProvisionalPageProxy::didCreateMainFrame):
     63        (WebKit::ProvisionalPageProxy::didStartProvisionalLoadForFrame):
     64        (WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
     65        (WebKit::ProvisionalPageProxy::didCommitLoadForFrame):
     66        (WebKit::ProvisionalPageProxy::didReceiveMessage):
     67        (WebKit::ProvisionalPageProxy::didReceiveSyncMessage):
     68        * UIProcess/ProvisionalPageProxy.h: Added.
     69        (WebKit::ProvisionalPageProxy::page):
     70        (WebKit::ProvisionalPageProxy::mainFrame const):
     71        (WebKit::ProvisionalPageProxy::process):
     72        (WebKit::ProvisionalPageProxy::processSwapRequestedByClient const):
     73        (WebKit::ProvisionalPageProxy::navigationID const):
     74        Add new ProvisionalPageProxy class to wrap the provisional load in the new process
     75        after a swap. The provisional page is owned by the WebPageProxy and we only commit
     76        the provisional page when the load is committed. Until then, the WebPageProxy keeps
     77        using the old process and displaying the current content.
     78
     79        * UIProcess/SuspendedPageProxy.cpp:
     80        (WebKit::SuspendedPageProxy::~SuspendedPageProxy):
     81        (WebKit::SuspendedPageProxy::unsuspend):
     82        (WebKit::SuspendedPageProxy::didProcessRequestToSuspend):
     83        Unregister the SuspendedPageProxy as an IPC message receiver a little bit earlier
     84        when we're going to unsuspend it. This avoids conflicting with the ProvisionalPageProxy
     85        which tries to register itself as an IPC message receiver for the same pageID when
     86        a process-swap occurs and we're switching to a suspended page.
     87
     88        * UIProcess/WebFrameProxy.cpp:
     89        (WebKit::WebFrameProxy::isMainFrame const):
     90        WebFrameProxy::isMainFrame() relies on checking that the frame is the WebPageProxy's m_mainFrame.
     91        Now that the WebPageProxy can have a ProvisionalPageProxy, also check if it is the ProvisionalPageProxy's
     92        m_mainFrame to maintain previous behavior.
     93
     94        * UIProcess/WebPageProxy.cpp:
     95        (WebKit::WebPageProxy::swapToWebProcess):
     96        swapToWebProcess() no longer takes care of unsuspending the SuspendedPage because we now call swapToWebProcess()
     97        later, when a load is actually committed in the provisional page / process. swapToWebProcess() now also needs
     98        to initialize some data members such as the drawing area and the main frame as it is transferring them over from
     99        the ProvisionalPageProxy which started the provisional load.
     100
     101        (WebKit::WebPageProxy::finishAttachingToWebProcess):
     102        We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
     103        committed in the provisional process.
     104
     105        (WebKit::WebPageProxy::initializeWebPage):
     106        - We no longer need IsSwapFromSuspended parameter as this is called later now, after a load has actually been
     107          committed in the provisional process.
     108        - Factor some code out to WebPageProxy::setDrawingArea() so that it can be shared with swapToWebProcess().
     109
     110        (WebKit::WebPageProxy::loadRequestWithNavigation):
     111        Only call setPendingAPIRequestURL() in loadRequestWithNavigation() only if ShouldTreatAsContinuingLoad is not
     112        Yes. This avoids hitting some assertions as this was already called during the first API call if needed.
     113
     114        (WebKit::WebPageProxy::receivedNavigationPolicyDecision):
     115        In case of process swap, tell the previous process to ignore the load instead of suspending it right away.
     116        Suspension now happens later, only if we end up committing the provisional load in the new process.
     117        Also discard the SuspendedPage if it failed to suspend (we only reuse its process in this case). This used
     118        to happen a bit later but it is clearer if we do this as early as possible I think.
     119
     120        (WebKit::WebPageProxy::commitProvisionalPage):
     121        When the load is committed in the new process, we call WebPageProxy::commitProvisionalPage(). It takes care of:
     122        - Actually swapping the WebPageProxy to the new process by calling processDidTerminate() / swapToWebProcess().
     123        - Suspending the current page.
     124        - Letting the client know the load is comitted
     125        - Destroy the ProvisionalPageProxy.
     126        This work used to happen earlier in continueNavigationInNewProcess().
     127
     128        (WebKit::WebPageProxy::continueNavigationInNewProcess):
     129        Moved some of the logic to commitProvisionalPage(). We now merely start the load in a new ProvisionalPageProxy,
     130        without actually having the WebPageProxy switch to the new process yet.
     131
     132        (WebKit::WebPageProxy::didCreateMainFrame):
     133        (WebKit::WebPageProxy::didCreateWindow):
     134        Drop some code that is no longer needed, now that the ProvisionalPageProxy takes care of this.
     135
     136        (WebKit::WebPageProxy::didDestroyNavigation):
     137        On process-swap, when telling the previous process to ignore the load and starting the new load in a new
     138        ProvisionalPageProxy, the previous WebPage attempts to destroy the navigation. In this case, we ignore
     139        the call since the navigation is merely taken over by the ProvisionalPageProxy.
     140
     141        (WebKit::WebPageProxy::didStartProvisionalLoadForFrame):
     142        Moved some PSON logic to the ProvisionalPageProxy instead.
     143
     144        (WebKit::WebPageProxy::didFailProvisionalLoadForFrame):
     145        When didFailProvisionalLoadForFrame() is called for a ProvisionalPageProxy, destroy it.
     146
     147        (WebKit::WebPageProxy::decidePolicyForNavigationActionAsync):
     148        (WebKit::WebPageProxy::decidePolicyForResponse):
     149        Capture the process in the lambda, to make sure we send the policy decision to the same process that
     150        asked for it, so as to not get confused by process swaps.
     151
     152        (WebKit::WebPageProxy::resetState):
     153        Drop some code that is no longer needed.
     154
     155        (WebKit::WebPageProxy::creationParameters):
     156        Move the hasRegisteredServiceWorkers flag initialization from the call site to here now that we have
     157        more than one call site. This was just some bad factoring.
     158
     159        (WebKit::WebPageProxy::PageProcessOverride::PageProcessOverride):
     160        (WebKit::WebPageProxy::PageProcessOverride::~PageProcessOverride):
     161        * UIProcess/WebPageProxy.h:
     162        (WebKit::WebPageProxy::temporarilyOverrideProcess):
     163        Add utility class to temporarily override the WebPageProxy's m_process with the provisional one when
     164        the ProvisionalPageProxy interacts with the WebPageProxy.
     165
     166        * UIProcess/WebProcessProxy.cpp:
     167        (WebKit::WebProcessProxy::hasProvisionalPageWithID const):
     168        (WebKit::WebProcessProxy::updateBackForwardItem):
     169        Before updating a BackForwardListItem, we normally make sure the process has a WebPageProxy with the
     170        item's pageID. We have to tweak the logic because there may now be no WebPageProxy with this pageID
     171        associated with this process yet, because it is still a ProvisionalPageProxy.
     172
     173        (WebKit::WebProcessProxy::canTerminateChildProcess):
     174        Do not terminate the WebProcess if there are ProvisionalPageProxy objects using it.
     175
     176        * UIProcess/WebProcessProxy.h:
     177        (WebKit::WebProcessProxy::addProvisionalPageProxy):
     178        (WebKit::WebProcessProxy::removeProvisionalPageProxy):
     179
     180        * WebKit.xcodeproj/project.pbxproj:
     181
     182        * WebProcess/WebPage/WebFrame.cpp:
     183        (WebKit::toPolicyAction):
     184        (WebKit::WebFrame::didReceivePolicyDecision):
     185        Stop dealing with WebPolicyAction::Suspend as it no longer exists.
     186
     187        * WebProcess/WebPage/WebPage.cpp:
     188        (WebKit::WebPage::reinitializeWebPage):
     189        (WebKit::WebPage::didReceivePolicyDecision):
     190
     191        (WebKit::WebPage::setIsSuspended):
     192        Suspend the Page when setIsSuspended(true) is called, now that there is no longer a WebPolicyAction::Suspend.
     193        setIsSuspended(true) IPC is sent when we actually commit the provisional page.
     194
     195        * WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm:
     196        (WebKit::TiledCoreAnimationDrawingArea::TiledCoreAnimationDrawingArea):
     197
    11982019-01-15  Brian Burg  <bburg@apple.com>
    2199
  • trunk/Source/WebKit/Shared/WebPageCreationParameters.cpp

    r239777 r239993  
    7474    encoder << mimeTypesWithCustomContentProviders;
    7575    encoder << controlledByAutomation;
    76     encoder << isSwapFromSuspended;
     76    encoder << isProcessSwap;
    7777
    7878#if PLATFORM(MAC)
    … …  
    228228    if (!decoder.decode(parameters.controlledByAutomation))
    229229        return WTF::nullopt;
    230     if (!decoder.decode(parameters.isSwapFromSuspended))
     230    if (!decoder.decode(parameters.isProcessSwap))
    231231        return WTF::nullopt;
    232232
  • trunk/Source/WebKit/Shared/WebPageCreationParameters.h

    r239777 r239993  
    130130
    131131    bool controlledByAutomation;
    132     bool isSwapFromSuspended { false };
     132    bool isProcessSwap { false };
    133133
    134134#if PLATFORM(MAC)
  • trunk/Source/WebKit/Shared/WebPolicyAction.h

    r239219 r239993  
    3030namespace WebKit {
    3131
     32// FIXME: Remove this type and use WebCore::PolicyAction instead.
    3233enum class WebPolicyAction : uint8_t {
    3334    Use,
    3435    Download,
    35     Ignore,
    36     Suspend
     36    Ignore
    3737};
    3838
    … …  
    4646        WebKit::WebPolicyAction::Use,
    4747        WebKit::WebPolicyAction::Download,
    48         WebKit::WebPolicyAction::Ignore,
    49         WebKit::WebPolicyAction::Suspend
     48        WebKit::WebPolicyAction::Ignore
    5049    >;
    5150};
  • trunk/Source/WebKit/Sources.txt

    r239815 r239993  
    231231UIProcess/ProcessAssertion.cpp
    232232UIProcess/ProcessThrottler.cpp
     233UIProcess/ProvisionalPageProxy.cpp
    233234UIProcess/RemoteWebInspectorProxy.cpp
    234235UIProcess/ResponsivenessTimer.cpp
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebView.mm

    r239931 r239993  
    4545#import "ObjCObjectGraph.h"
    4646#import "PageClient.h"
     47#import "ProvisionalPageProxy.h"
    4748#import "RemoteLayerTreeScrollingPerformanceData.h"
    4849#import "RemoteLayerTreeTransaction.h"
    … …  
    47014702    Ref<WebKit::WebProcessProxy> protectedProcessProxy(_page->process());
    47024703    protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
     4704
     4705    if (auto* provisionalPageProxy = _page->provisionalPageProxy()) {
     4706        Ref<WebKit::WebProcessProxy> protectedProcessProxy(provisionalPageProxy->process());
     4707        protectedProcessProxy->requestTermination(WebKit::ProcessTerminationReason::RequestedByClient);
     4708    }
    47034709}
    47044710
  • trunk/Source/WebKit/UIProcess/PageClient.h

    r239843 r239993  
    4949OBJC_CLASS CALayer;
    5050OBJC_CLASS NSFileWrapper;
     51OBJC_CLASS NSMenu;
    5152OBJC_CLASS NSSet;
    5253OBJC_CLASS WKDrawingView;
  • trunk/Source/WebKit/UIProcess/SuspendedPageProxy.cpp

    r239437 r239993  
    101101    // on the WebProcess side.
    102102    m_process->send(Messages::WebPage::Close(), m_page.pageID());
    103     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
     103
     104    if (m_suspensionState == SuspensionState::Suspending)
     105        m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
    104106
    105107    // We call maybeShutDown() asynchronously since the SuspendedPage is currently being removed from the WebProcessPool
    … …  
    135137
    136138    m_suspensionState = SuspensionState::Resumed;
    137     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
    138139    m_process->send(Messages::WebPage::SetIsSuspended(false), m_page.pageID());
    139140}
    … …  
    151152    m_suspensionToken = nullptr;
    152153#endif
     154
     155    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_page.pageID());
    153156
    154157    if (m_readyToUnsuspendHandler)
  • trunk/Source/WebKit/UIProcess/WebFrameProxy.cpp

    r239219 r239993  
    2828
    2929#include "APINavigation.h"
     30#include "ProvisionalPageProxy.h"
    3031#include "WebCertificateInfo.h"
    3132#include "WebFramePolicyListenerProxy.h"
    … …  
    7576        return false;
    7677
    77     return this == m_page->mainFrame();
     78    return this == m_page->mainFrame() || (m_page->provisionalPageProxy() && this == m_page->provisionalPageProxy()->mainFrame());
    7879}
    7980
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r239881 r239993  
    7878#include "PluginProcessManager.h"
    7979#include "PrintInfo.h"
     80#include "ProvisionalPageProxy.h"
    8081#include "SafeBrowsingWarning.h"
    8182#include "ShareSheetCallbackID.h"
    … …  
    546547}
    547548
     549DrawingAreaProxy* WebPageProxy::drawingArea() const
     550{
     551    if (m_provisionalPage && m_process.ptr() == &m_provisionalPage->process() && m_provisionalPage->drawingArea())
     552        return m_provisionalPage->drawingArea();
     553    return m_drawingArea.get();
     554}
     555
    548556void WebPageProxy::changeWebsiteDataStore(WebsiteDataStore& websiteDataStore)
    549557{
    … …  
    769777}
    770778
    771 void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<SuspendedPageProxy>&& destinationSuspendedPage, IsSwapFromSuspended isSwapFromSuspended)
     779void WebPageProxy::swapToWebProcess(Ref<WebProcessProxy>&& process, std::unique_ptr<DrawingAreaProxy>&& drawingArea, RefPtr<WebFrameProxy>&& mainFrame)
    772780{
    773781    ASSERT(!m_isClosed);
    … …  
    775783
    776784    m_process = WTFMove(process);
     785    ASSERT(!m_drawingArea);
     786    setDrawingArea(WTFMove(drawingArea));
     787    ASSERT(!m_mainFrame);
     788    m_mainFrame = WTFMove(mainFrame);
    777789    m_isValid = true;
    778 
    779     // If we are reattaching to a SuspendedPage, then the WebProcess' WebPage already exists and
    780     // WebPageProxy::didCreateMainFrame() will not be called to initialize m_mainFrame. In such
    781     // case, we need to initialize m_mainFrame to reflect the fact the the WebProcess' WebPage
    782     // already exists and already has a main frame.
    783     if (destinationSuspendedPage) {
    784         if (!destinationSuspendedPage->failedToSuspend()) {
    785             ASSERT(!m_mainFrame);
    786             ASSERT(&destinationSuspendedPage->process() == m_process.ptr());
    787             destinationSuspendedPage->unsuspend();
    788             m_mainFrame = WebFrameProxy::create(*this, destinationSuspendedPage->mainFrameID());
    789             m_process->frameCreated(destinationSuspendedPage->mainFrameID(), *m_mainFrame);
    790         } else {
    791             // We failed to suspend the page so destroy it now and merely reuse its WebContent process.
    792             destinationSuspendedPage = nullptr;
    793         }
    794     }
    795790
    796791    m_process->addExistingWebPage(*this, m_pageID, WebProcessProxy::BeginsUsingDataStore::No);
    797792    m_process->addMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID, *this);
    798793
    799     finishAttachingToWebProcess(isSwapFromSuspended);
    800 }
    801 
    802 void WebPageProxy::finishAttachingToWebProcess(IsSwapFromSuspended isSwapFromSuspended)
     794    // No need to initialize the WebPage since it was created when we created the ProvisionalPageProxy.
     795    finishAttachingToWebProcess(ShouldInitializeWebPage::No);
     796}
     797
     798void WebPageProxy::finishAttachingToWebProcess(ShouldInitializeWebPage shouldInitializePage)
    803799{
    804800    ASSERT(m_process->state() != ChildProcessProxy::State::Terminated);
    … …  
    836832#endif
    837833
    838     initializeWebPage(isSwapFromSuspended);
     834    if (shouldInitializePage == ShouldInitializeWebPage::Yes)
     835        initializeWebPage();
    839836
    840837    m_inspector->updateForNewPageProcess(this);
    … …  
    901898}
    902899
    903 void WebPageProxy::initializeWebPage(IsSwapFromSuspended isSwapFromSuspended)
    904 {
    905     ASSERT(isValid());
    906 
    907     m_drawingArea = pageClient().createDrawingAreaProxy();
    908     ASSERT(m_drawingArea);
     900void WebPageProxy::setDrawingArea(std::unique_ptr<DrawingAreaProxy>&& drawingArea)
     901{
     902    m_drawingArea = WTFMove(drawingArea);
     903    if (!m_drawingArea)
     904        return;
    909905
    910906#if ENABLE(ASYNC_SCROLLING) && PLATFORM(COCOA)
    … …  
    917913    }
    918914#endif
    919 
    920     auto parameters = creationParameters();
    921     parameters.isSwapFromSuspended = isSwapFromSuspended == IsSwapFromSuspended::Yes;
    922 
    923 #if ENABLE(SERVICE_WORKER)
    924     parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
    925 #endif
    926 
    927     process().send(Messages::WebProcess::CreateWebPage(m_pageID, parameters), 0);
     915}
     916
     917void WebPageProxy::initializeWebPage()
     918{
     919    ASSERT(isValid());
     920
     921    setDrawingArea(pageClient().createDrawingAreaProxy());
     922    ASSERT(m_drawingArea);
     923
     924    process().send(Messages::WebProcess::CreateWebPage(m_pageID, creationParameters()), 0);
    928925
    929926    m_needsToFinishInitializingWebPageAfterProcessLaunch = true;
    … …  
    10771074
    10781075    auto url = request.url();
    1079     m_pageLoadState.setPendingAPIRequestURL(transaction, url);
     1076    if (shouldTreatAsContinuingLoad != ShouldTreatAsContinuingLoad::Yes)
     1077        m_pageLoadState.setPendingAPIRequestURL(transaction, url);
    10801078
    10811079    if (!isValid())
    … …  
    12951293
    12961294    m_process->send(Messages::WebPage::StopLoading(), m_pageID);
     1295    if (m_provisionalPage) {
     1296        m_provisionalPage->cancel();
     1297        m_provisionalPage = nullptr;
     1298    }
    12971299    m_process->responsivenessTimer().start();
    12981300}
    … …  
    26992701
    27002702        if (processForNavigation.ptr() != &process()) {
    2701             policyAction = isPageOpenedByDOMShowingInitialEmptyDocument() ? WebPolicyAction::Ignore : WebPolicyAction::Suspend;
     2703            policyAction = WebPolicyAction::Ignore;
    27022704            RELEASE_LOG_IF_ALLOWED(ProcessSwapping, "decidePolicyForNavigationAction, swapping process %i with process %i for navigation, reason: %{public}s", processIdentifier(), processForNavigation->processIdentifier(), reason.utf8().data());
    27032705            LOG(ProcessSwapping, "(ProcessSwapping) Switching from process %i to new process (%i) for navigation %" PRIu64 " '%s'", processIdentifier(), processForNavigation->processIdentifier(), navigation->navigationID(), navigation->loggingString());
    … …  
    27082710        receivedPolicyDecision(policyAction, navigation.ptr(), shouldProcessSwap ? WTF::nullopt : WTFMove(data), WTFMove(sender));
    27092711
    2710         if (shouldProcessSwap)
    2711             continueNavigationInNewProcess(navigation, destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr, WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
     2712        if (!shouldProcessSwap)
     2713            return;
     2714
     2715        auto suspendedPage = destinationSuspendedPage ? process().processPool().takeSuspendedPage(*destinationSuspendedPage) : nullptr;
     2716        if (suspendedPage && suspendedPage->failedToSuspend())
     2717            suspendedPage = nullptr;
     2718
     2719        continueNavigationInNewProcess(navigation, WTFMove(suspendedPage), WTFMove(processForNavigation), processSwapRequestedByClient, WTFMove(data));
    27122720    });
    27132721}
    … …  
    27452753}
    27462754
    2747 void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& process, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
     2755void WebPageProxy::commitProvisionalPage(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)
     2756{
     2757    ASSERT(m_provisionalPage);
     2758    RELEASE_LOG_IF_ALLOWED(Loading, "commitProvisionalPage: previousPID = %i, newPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_provisionalPage->process().processIdentifier(), m_pageID);
     2759
     2760    Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
     2761
     2762    ASSERT(m_process.ptr() != &m_provisionalPage->process());
     2763
     2764    processDidTerminate(ProcessTerminationReason::NavigationSwap);
     2765
     2766    m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
     2767    auto* navigation = navigationState().navigation(m_provisionalPage->navigationID());
     2768    bool didSuspendPreviousPage = navigation ? suspendCurrentPageIfPossible(*navigation, mainFrameIDInPreviousProcess, m_provisionalPage->processSwapRequestedByClient()) : false;
     2769    m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
     2770
     2771    // There is no way we'll be able to return to the page in the previous page so close it.
     2772    if (!didSuspendPreviousPage)
     2773        m_process->send(Messages::WebPage::Close(), pageID());
     2774
     2775    swapToWebProcess(m_provisionalPage->process(), m_provisionalPage->takeDrawingArea(), m_provisionalPage->mainFrame());
     2776
     2777    didCommitLoadForFrame(frameID, navigationID, mimeType, frameHasCustomContentProvider, frameLoadType, certificateInfo, containsPluginDocument, forcedHasInsecureContent, userData);
     2778
     2779    m_provisionalPage = nullptr;
     2780}
     2781
     2782void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPageProxy, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, Optional<WebsitePoliciesData>&& websitePolicies)
    27482783{
    27492784    RELEASE_LOG_IF_ALLOWED(Loading, "continueNavigationInNewProcess: webPID = %i, pageID = %" PRIu64, m_process->processIdentifier(), m_pageID);
    27502785    LOG(Loading, "Continuing navigation %" PRIu64 " '%s' in a new web process", navigation.navigationID(), navigation.loggingString());
    27512786
    2752     Ref<WebProcessProxy> previousProcess = m_process.copyRef();
    2753     Optional<uint64_t> mainFrameIDInPreviousProcess = m_mainFrame ? makeOptional(m_mainFrame->frameID()) : WTF::nullopt;
    2754     auto mainFrameURL = m_mainFrame ? m_mainFrame->url() : URL();
    2755 
    2756     ASSERT(m_process.ptr() != process.ptr());
    2757 
    2758     processDidTerminate(ProcessTerminationReason::NavigationSwap);
    2759 
    2760     m_process->removeMessageReceiver(Messages::WebPageProxy::messageReceiverName(), m_pageID);
    2761     bool didSuspendPreviousPage = suspendCurrentPageIfPossible(navigation, mainFrameIDInPreviousProcess, processSwapRequestedByClient);
    2762     m_process->removeWebPage(*this, m_pageID, WebProcessProxy::EndsUsingDataStore::No);
    2763 
    2764     swapToWebProcess(WTFMove(process), WTFMove(suspendedPageProxy), didSuspendPreviousPage ? IsSwapFromSuspended::Yes : IsSwapFromSuspended::No);
     2787    if (m_provisionalPage) {
     2788        if (m_provisionalPage->navigationID() != navigation.navigationID())
     2789            m_provisionalPage->cancel();
     2790        m_provisionalPage = nullptr;
     2791    }
     2792
     2793    m_provisionalPage = std::make_unique<ProvisionalPageProxy>(*this, newProcess.copyRef(), WTFMove(suspendedPageProxy), navigation.navigationID(), navigation.currentRequestIsRedirect(), navigation.currentRequest(), processSwapRequestedByClient);
    27652794
    27662795    if (auto* item = navigation.targetItem()) {
    … …  
    27702799        m_pageLoadState.setPendingAPIRequestURL(transaction, item->url());
    27712800
    2772         auto itemStates = m_backForwardList->filteredItemStates([this, targetItem = item](WebBackForwardListItem& item) {
    2773             if (auto* page = item.suspendedPage()) {
    2774                 if (&page->process() == m_process.ptr())
    2775                     return false;
    2776             }
    2777             return &item != targetItem;
    2778         });
    2779         m_process->send(Messages::WebPage::UpdateBackForwardListForReattach(WTFMove(itemStates)), m_pageID);
    2780         m_process->send(Messages::WebPage::GoToBackForwardItem(navigation.navigationID(), item->itemID(), *navigation.backForwardFrameLoadType(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies)), m_pageID);
    2781         m_process->responsivenessTimer().start();
    2782 
     2801        m_provisionalPage->goToBackForwardItem(navigation, *item, WTFMove(websitePolicies));
    27832802        return;
    27842803    }
    … …  
    27872806        // If WebCore is supposed to lock the history for this load, then the new process needs to know about the current history item so it can update
    27882807        // it instead of creating a new one.
    2789         m_process->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
     2808        newProcess->send(Messages::WebPage::SetCurrentHistoryItemForReattach(m_backForwardList->currentItem()->itemState()), m_pageID);
    27902809    }
    27912810
    … …  
    27932812    ASSERT(!navigation.currentRequest().isEmpty());
    27942813    if (auto& substituteData = navigation.substituteData())
    2795         loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
     2814        m_provisionalPage->loadDataWithNavigation(navigation, { substituteData->content.data(), substituteData->content.size() }, substituteData->MIMEType, substituteData->encoding, substituteData->baseURL, substituteData->userData.get(), WTFMove(websitePolicies));
    27962815    else
    2797         loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, ShouldTreatAsContinuingLoad::Yes, WTFMove(websitePolicies));
    2798 
    2799     ASSERT(!m_mainFrame);
    2800     m_mainFrameCreationHandler = [this, weakThis = makeWeakPtr(*this), navigationID = navigation.navigationID(), request =  navigation.currentRequest(), mainFrameURL, isServerRedirect = navigation.currentRequestIsRedirect()]() mutable {
    2801         if (!weakThis)
    2802             return;
    2803 
    2804         ASSERT(m_mainFrame);
    2805         // This navigation was destroyed so no need to notify of redirect.
    2806         if (!navigationState().navigation(navigationID))
    2807             return;
    2808 
    2809         // Restore the main frame's committed URL as some clients may rely on it until the next load is committed.
    2810         m_mainFrame->frameLoadState().setURL(mainFrameURL);
    2811 
    2812         // Normally, notification of a server redirect comes from the WebContent process.
    2813         // If we are process swapping in response to a server redirect then that notification will not come from the new WebContent process.
    2814         // In this case we have the UIProcess synthesize the redirect notification at the appropriate time.
    2815         if (isServerRedirect) {
    2816             m_mainFrame->frameLoadState().didStartProvisionalLoad(request.url());
    2817             didReceiveServerRedirectForProvisionalLoadForFrame(m_mainFrame->frameID(), navigationID, WTFMove(request), { });
    2818         }
    2819     };
    2820 
    2821     if (!m_process->processPool().configuration().processSwapsOnWindowOpenWithOpener() || !isPageOpenedByDOMShowingInitialEmptyDocument() || !mainFrameIDInPreviousProcess) {
    2822         // There is no way we'll be able to return to the page in the previous page so close it.
    2823         if (!didSuspendPreviousPage)
    2824             previousProcess->send(Messages::WebPage::Close(), m_pageID);
    2825         return;
    2826     }
    2827 
    2828     m_mainFrameWindowCreationHandler = [this, previousProcess = WTFMove(previousProcess), mainFrameIDInPreviousProcess = *mainFrameIDInPreviousProcess](const GlobalWindowIdentifier& windowIdentifier) {
    2829         ASSERT(m_mainFrame);
    2830         GlobalFrameIdentifier navigatedFrameIdentifierInNewProcess { pageID(), m_mainFrame->frameID() };
    2831         previousProcess->send(Messages::WebPage::FrameBecameRemote(mainFrameIDInPreviousProcess, navigatedFrameIdentifierInNewProcess, windowIdentifier), pageID());
    2832     };
     2816        m_provisionalPage->loadRequestWithNavigation(navigation, ResourceRequest { navigation.currentRequest() }, WebCore::ShouldOpenExternalURLsPolicy::ShouldAllowExternalSchemes, nullptr, WTFMove(websitePolicies));
    28332817}
    28342818
    … …  
    36953679    // Add the frame to the process wide map.
    36963680    m_process->frameCreated(frameID, *m_mainFrame);
    3697 
    3698     if (m_mainFrameCreationHandler) {
    3699         m_mainFrameCreationHandler();
    3700         m_mainFrameCreationHandler = nullptr;
    3701     }
    37023681}
    37033682
    … …  
    37243703void WebPageProxy::didCreateWindow(uint64_t frameID, GlobalWindowIdentifier&& windowIdentifier)
    37253704{
    3726     if (m_mainFrame && m_mainFrame->frameID() == frameID) {
    3727         if (auto mainFrameWindowCreationHandler = WTFMove(m_mainFrameWindowCreationHandler))
    3728             mainFrameWindowCreationHandler(windowIdentifier);
    3729     }
    37303705}
    37313706
    … …  
    37793754{
    37803755    PageClientProtector protector(pageClient());
     3756
     3757    // On process-swap, the previous process tries to destroy the navigation but the provisional process is actually taking over the navigation.
     3758    if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID)
     3759        return;
    37813760
    37823761    // FIXME: Message check the navigationID.
    … …  
    37963775    if (frame->isMainFrame() && navigationID)
    37973776        navigation = navigationState().navigation(navigationID);
    3798 
    3799     // If this seemingly new load is actually continuing a server redirect for a previous navigation in a new process,
    3800     // then we ignore this notification.
    3801     if (navigation && navigation->currentRequestIsRedirect()) {
    3802         auto navigationProcessIdentifier = navigation->currentRequestProcessIdentifier();
    3803         if (navigationProcessIdentifier && *navigationProcessIdentifier != m_process->coreProcessIdentifier())
    3804             return;
    3805     }
    38063777
    38073778    LOG(Loading, "WebPageProxy %" PRIu64 " in process pid %i didStartProvisionalLoadForFrame to frameID %" PRIu64 ", navigationID %" PRIu64 ", url %s", m_pageID, m_process->processIdentifier(), frameID, navigationID, url.string().utf8().data());
    … …  
    39113882
    39123883    PageClientProtector protector(pageClient());
     3884
     3885    if (m_provisionalPage && m_provisionalPage->navigationID() == navigationID && &m_provisionalPage->process() != m_process.ptr()) {
     3886        // The load did not fail, it is merely happening in a new provisional process.
     3887        return;
     3888    }
    39133889
    39143890    WebFrameProxy* frame = m_process->webFrame(frameID);
    … …  
    39503926
    39513927    m_failingProvisionalLoadURL = { };
     3928
     3929    // If the provisional page's load fails then we destroy the provisional page.
     3930    if (m_provisionalPage && m_provisionalPage->mainFrame() == frame)
     3931        m_provisionalPage = nullptr;
    39523932}
    39533933
    … …  
    43414321    MESSAGE_CHECK(frame);
    43424322
    4343     decidePolicyForNavigationAction(*frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, PolicyDecisionSender::create([this, protectedThis = makeRef(*this), frameID, listenerID] (auto... args) {
    4344         m_process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
     4323    decidePolicyForNavigationAction(*frame, WTFMove(frameSecurityOrigin), navigationID, WTFMove(navigationActionData), WTFMove(frameInfoData), originatingPageID, originalRequest, WTFMove(request), WTFMove(requestBody), WTFMove(redirectResponse), userData, PolicyDecisionSender::create([this, protectedThis = makeRef(*this), frameID, listenerID, process = m_process.copyRef()] (auto... args) {
     4324        process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
    43454325    }));
    43464326}
    … …  
    45764556
    45774557    RefPtr<API::Navigation> navigation = navigationID ? m_navigationState->navigation(navigationID) : nullptr;
    4578     auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation)] (WebPolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
     4558    auto listener = makeRef(frame->setUpPolicyListenerProxy([this, protectedThis = makeRef(*this), frameID, listenerID, navigation = WTFMove(navigation), process = m_process.copyRef()] (WebPolicyAction policyAction, API::WebsitePolicies*, ProcessSwapRequestedByClient processSwapRequestedByClient, RefPtr<SafeBrowsingWarning>&& safeBrowsingWarning) mutable {
    45794559        // FIXME: Assert the API::WebsitePolicies* is nullptr here once clients of WKFramePolicyListenerUseWithPolicies go away.
    45804560        RELEASE_ASSERT(processSwapRequestedByClient == ProcessSwapRequestedByClient::No);
    45814561        ASSERT_UNUSED(safeBrowsingWarning, !safeBrowsingWarning);
    4582         receivedPolicyDecision(policyAction, navigation.get(), WTF::nullopt, PolicyDecisionSender::create([this, protectedThis = WTFMove(protectedThis), frameID, listenerID] (auto... args) {
    4583             m_process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
     4562        receivedPolicyDecision(policyAction, navigation.get(), WTF::nullopt, PolicyDecisionSender::create([this, protectedThis = WTFMove(protectedThis), frameID, listenerID, process = WTFMove(process)] (auto... args) {
     4563            process->send(Messages::WebPage::DidReceivePolicyDecision(frameID, listenerID, args...), m_pageID);
    45844564        }));
    45854565    }, ShouldExpectSafeBrowsingResult::No));
    … …  
    64016381}
    64026382
     6383void WebPageProxy::provisionalProcessDidTerminate()
     6384{
     6385    ASSERT(m_provisionalPage);
     6386    m_provisionalPage->cancel();
     6387    m_provisionalPage = nullptr;
     6388}
     6389
    64036390static bool shouldReloadAfterProcessTermination(ProcessTerminationReason reason)
    64046391{
    … …  
    64886475{
    64896476    m_mainFrame = nullptr;
    6490     m_mainFrameCreationHandler = nullptr;
    6491     m_mainFrameWindowCreationHandler = nullptr;
    64926477
    64936478#if PLATFORM(COCOA)
    … …  
    67806765#endif
    67816766
     6767#if ENABLE(SERVICE_WORKER)
     6768    parameters.hasRegisteredServiceWorkers = process().processPool().mayHaveRegisteredServiceWorkers(m_websiteDataStore);
     6769#endif
     6770
    67826771    parameters.needsFontAttributes = m_needsFontAttributes;
    67836772
    … …  
    85418530}
    85428531
     8532WebPageProxy::PageProcessOverride::PageProcessOverride(WebPageProxy& page, WebProcessProxy& newProcess)
     8533    : m_page(&page)
     8534    , m_previousProcess(page.process())
     8535{
     8536    page.m_process = newProcess;
     8537}
     8538
     8539WebPageProxy::PageProcessOverride::PageProcessOverride(PageProcessOverride&&) = default;
     8540
     8541WebPageProxy::PageProcessOverride::~PageProcessOverride()
     8542{
     8543    if (m_page)
     8544        m_page->m_process = WTFMove(m_previousProcess);
     8545}
     8546
    85438547#if ENABLE(DATA_DETECTION)
    85448548
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r239881 r239993  
    226226class NativeWebWheelEvent;
    227227class PageClient;
     228class ProvisionalPageProxy;
    228229class RemoteLayerTreeHost;
    229230class RemoteLayerTreeScrollingPerformanceData;
    … …  
    357358    WebFrameProxy* frameSetLargestFrame() const { return m_frameSetLargestFrame.get(); }
    358359
    359     DrawingAreaProxy* drawingArea() const { return m_drawingArea.get(); }
     360    DrawingAreaProxy* drawingArea() const;
    360361
    361362    WebNavigationState& navigationState() { return *m_navigationState.get(); }
    … …  
    380381    bool addsVisitedLinks() const { return m_addsVisitedLinks; }
    381382    void setAddsVisitedLinks(bool addsVisitedLinks) { m_addsVisitedLinks = addsVisitedLinks; }
     383    VisitedLinkStore& visitedLinkStore() { return m_visitedLinkStore; }
    382384
    383385    void exitFullscreenImmediately();
    … …  
    459461    void setIconLoadingClient(std::unique_ptr<API::IconLoadingClient>&&);
    460462
    461     enum class IsSwapFromSuspended { No, Yes };
    462     void initializeWebPage(IsSwapFromSuspended = IsSwapFromSuspended::No);
     463    void initializeWebPage();
     464    void setDrawingArea(std::unique_ptr<DrawingAreaProxy>&&);
    463465
    464466    WeakPtr<SecKeyProxyStore> secKeyProxyStore(const WebCore::AuthenticationChallenge&);
    … …  
    9981000    void processDidBecomeResponsive();
    9991001    void processDidTerminate(ProcessTerminationReason);
     1002    void provisionalProcessDidTerminate();
    10001003    void dispatchProcessDidTerminate(ProcessTerminationReason);
    10011004    void willChangeProcessIsResponsive();
    … …  
    10251028    WebProcessProxy& process() { return m_process; }
    10261029    ProcessID processIdentifier() const;
     1030
     1031    class PageProcessOverride {
     1032    public:
     1033        PageProcessOverride(WebPageProxy&, WebProcessProxy& newProcess);
     1034        PageProcessOverride(PageProcessOverride&&);
     1035        ~PageProcessOverride();
     1036
     1037    private:
     1038        RefPtr<WebPageProxy> m_page;
     1039        Ref<WebProcessProxy> m_previousProcess;
     1040    };
     1041
     1042    PageProcessOverride temporarilyOverrideProcess(WebProcessProxy& newProcess) { return PageProcessOverride(*this, newProcess); }
    10271043
    10281044    WebPreferences& preferences() { return m_preferences; }
    … …  
    14161432#endif
    14171433
     1434    ProvisionalPageProxy* provisionalPageProxy() const { return m_provisionalPage.get(); }
     1435    void commitProvisionalPage(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
     1436
     1437    void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
     1438    void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
     1439    void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);
     1440
     1441    void loadDataWithNavigation(API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
     1442    void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
     1443
     1444    // IPC::MessageReceiver
     1445    // Implemented in generated WebPageProxyMessageReceiver.cpp
     1446    void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
     1447    void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
     1448
    14181449private:
    14191450    WebPageProxy(PageClient&, WebProcessProxy&, uint64_t pageID, Ref<API::PageConfiguration>&&);
    … …  
    14401471    void setUserAgent(String&&);
    14411472
    1442     // IPC::MessageReceiver
    1443     // Implemented in generated WebPageProxyMessageReceiver.cpp
    1444     void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
    1445     void didReceiveSyncMessage(IPC::Connection&, IPC::Decoder&, std::unique_ptr<IPC::Encoder>&) override;
    1446 
    1447 
    14481473    // IPC::MessageSender
    14491474    bool sendMessage(std::unique_ptr<IPC::Encoder>, OptionSet<IPC::SendOption>) override;
    … …  
    14671492    void didCreateWindow(uint64_t frameID, WebCore::GlobalWindowIdentifier&&);
    14681493
    1469     void didStartProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, URL&&, URL&& unreachableURL, const UserData&);
    1470     void didReceiveServerRedirectForProvisionalLoadForFrame(uint64_t frameID, uint64_t navigationID, WebCore::ResourceRequest&&, const UserData&);
    14711494    void willPerformClientRedirectForFrame(uint64_t frameID, const String& url, double delay, WebCore::LockBackForwardList);
    14721495    void didCancelClientRedirectForFrame(uint64_t frameID);
    14731496    void didChangeProvisionalURLForFrame(uint64_t frameID, uint64_t navigationID, URL&&);
    1474     void didFailProvisionalLoadForFrame(uint64_t frameID, const WebCore::SecurityOriginData& frameSecurityOrigin, uint64_t navigationID, const String& provisionalURL, const WebCore::ResourceError&, const UserData&);
    14751497    void didCommitLoadForFrame(uint64_t frameID, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, uint32_t frameLoadType, const WebCore::CertificateInfo&, bool containsPluginDocument, Optional<WebCore::HasInsecureContent> forcedHasInsecureContent, const UserData&);
    14761498    void didFinishDocumentLoadForFrame(uint64_t frameID, uint64_t navigationID, const UserData&);
    … …  
    15761598
    15771599    void reattachToWebProcess();
    1578     void swapToWebProcess(Ref<WebProcessProxy>&&, std::unique_ptr<SuspendedPageProxy>&&, IsSwapFromSuspended);
     1600    void swapToWebProcess(Ref<WebProcessProxy>&&, std::unique_ptr<DrawingAreaProxy>&&, RefPtr<WebFrameProxy>&& mainFrame);
    15791601    void didFailToSuspendAfterProcessSwap();
    15801602    void didSuspendAfterProcessSwap();
    15811603
    1582     void finishAttachingToWebProcess(IsSwapFromSuspended = IsSwapFromSuspended::No);
     1604    enum class ShouldInitializeWebPage { No, Yes };
     1605    void finishAttachingToWebProcess(ShouldInitializeWebPage = ShouldInitializeWebPage::Yes);
    15831606
    15841607    RefPtr<API::Navigation> reattachToWebProcessForReload();
    15851608    RefPtr<API::Navigation> reattachToWebProcessWithItem(WebBackForwardListItem&);
    1586 
    1587     void loadDataWithNavigation(API::Navigation&, const IPC::DataReference&, const String& MIMEType, const String& encoding, const String& baseURL, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
    1588     void loadRequestWithNavigation(API::Navigation&, WebCore::ResourceRequest&&, WebCore::ShouldOpenExternalURLsPolicy, API::Object* userData, WebCore::ShouldTreatAsContinuingLoad, Optional<WebsitePoliciesData>&& = WTF::nullopt);
    15891609
    15901610    void requestNotificationPermission(uint64_t notificationID, const String& originString);
    … …  
    19531973
    19541974    RefPtr<WebFrameProxy> m_mainFrame;
    1955     Function<void()> m_mainFrameCreationHandler;
    1956     Function<void(const WebCore::GlobalWindowIdentifier&)> m_mainFrameWindowCreationHandler;
    19571975
    19581976    RefPtr<WebFrameProxy> m_focusedFrame;
    … …  
    23252343    bool m_mayHaveUniversalFileReadSandboxExtension { false };
    23262344
     2345    std::unique_ptr<ProvisionalPageProxy> m_provisionalPage;
     2346
    23272347#if HAVE(PENCILKIT)
    23282348    std::unique_ptr<EditableImageController> m_editableImageController;
  • trunk/Source/WebKit/UIProcess/WebProcessProxy.cpp

    r239427 r239993  
    3535#include "PluginInfoStore.h"
    3636#include "PluginProcessManager.h"
     37#include "ProvisionalPageProxy.h"
    3738#include "TextChecker.h"
    3839#include "TextCheckerState.h"
    … …  
    585586#endif
    586587
     588bool WebProcessProxy::hasProvisionalPageWithID(uint64_t pageID) const
     589{
     590    for (auto* provisionalPage : m_provisionalPages) {
     591        if (provisionalPage->page().pageID() == pageID)
     592            return true;
     593    }
     594    return false;
     595}
     596
    587597void WebProcessProxy::updateBackForwardItem(const BackForwardListItemState& itemState)
    588598{
    … …  
    592602        // e.g. The old web process is navigating to about:blank for suspension.
    593603        // We ignore these updates.
    594         if (m_pageMap.contains(item->pageID()))
     604        if (m_pageMap.contains(item->pageID()) || hasProvisionalPageWithID(item->pageID()))
    595605            item->setPageState(itemState.pageState);
    596606    }
    … …  
    695705
    696706    auto pages = copyToVectorOf<RefPtr<WebPageProxy>>(m_pageMap.values());
     707    auto provisionalPages = WTF::map(m_provisionalPages, [](auto* provisionalPage) { return makeWeakPtr(provisionalPage); });
    697708
    698709    shutDown();
    … …  
    709720    for (auto& page : pages)
    710721        page->processDidTerminate(ProcessTerminationReason::Crash);
     722
     723    for (auto& provisionalPage : provisionalPages) {
     724        if (provisionalPage)
     725            provisionalPage->processDidTerminate();
     726    }
    711727}
    712728
    … …  
    780796        page->processDidFinishLaunching();
    781797    }
     798
     799    for (auto* provisionalPage : m_provisionalPages) {
     800        ASSERT(this == &provisionalPage->process());
     801        provisionalPage->processDidFinishLaunching();
     802    }
     803
    782804
    783805    RELEASE_ASSERT(!m_webConnection);
    … …  
    874896bool WebProcessProxy::canTerminateChildProcess()
    875897{
    876     if (!m_pageMap.isEmpty() || m_processPool->hasSuspendedPageFor(*this))
     898    if (!m_pageMap.isEmpty() || m_processPool->hasSuspendedPageFor(*this) || !m_provisionalPages.isEmpty())
    877899        return false;
    878900
  • trunk/Source/WebKit/UIProcess/WebProcessProxy.h

    r239427 r239993  
    7171class ObjCObjectGraph;
    7272class PageClient;
     73class ProvisionalPageProxy;
    7374class UserMediaCaptureManagerProxy;
    7475class VisitedLinkStore;
    … …  
    125126    void removeWebPage(WebPageProxy&, uint64_t pageID, EndsUsingDataStore);
    126127
     128    void addProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(!m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.add(&provisionalPage); }
     129    void removeProvisionalPageProxy(ProvisionalPageProxy& provisionalPage) { ASSERT(m_provisionalPages.contains(&provisionalPage)); m_provisionalPages.remove(&provisionalPage); }
     130
    127131    typename WebPageProxyMap::ValuesConstIteratorRange pages() const { return m_pageMap.values(); }
    128132    unsigned pageCount() const { return m_pageMap.size(); }
    … …  
    331335    void logDiagnosticMessageForResourceLimitTermination(const String& limitKey);
    332336
     337    bool hasProvisionalPageWithID(uint64_t pageID) const;
     338
    333339    enum class IsWeak { No, Yes };
    334340    template<typename T> class WeakOrStrongPtr {
    … …  
    374380    WebPageProxyMap m_pageMap;
    375381    WebFrameProxyMap m_frameMap;
     382    HashSet<ProvisionalPageProxy*> m_provisionalPages;
    376383    UserInitiatedActionMap m_userInitiatedActionMap;
    377384
  • trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj

    r239841 r239993  
    30713071                466BC0391FA266C9002FA9C1 /* WebSWContextManagerConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebSWContextManagerConnection.h; sourceTree = "<group>"; };
    30723072                466BC03A1FA266C9002FA9C1 /* WebSWContextManagerConnection.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebSWContextManagerConnection.messages.in; sourceTree = "<group>"; };
     3073                4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProvisionalPageProxy.h; sourceTree = "<group>"; };
     3074                4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProvisionalPageProxy.cpp; sourceTree = "<group>"; };
    30733075                46A2B6061E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BackgroundProcessResponsivenessTimer.cpp; sourceTree = "<group>"; };
    30743076                46A2B6071E5675A200C3DEDA /* BackgroundProcessResponsivenessTimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BackgroundProcessResponsivenessTimer.h; sourceTree = "<group>"; };
    … …  
    73137315                                86E67A21190F411800004AB7 /* ProcessThrottler.h */,
    73147316                                83048AE51ACA45DC0082C832 /* ProcessThrottlerClient.h */,
     7317                                4683569B21E81CC7006E27A3 /* ProvisionalPageProxy.cpp */,
     7318                                4683569A21E81CC7006E27A3 /* ProvisionalPageProxy.h */,
    73157319                                A55BA81B1BA25B1E007CD33D /* RemoteWebInspectorProxy.cpp */,
    73167320                                A55BA8191BA25B1E007CD33D /* RemoteWebInspectorProxy.h */,
  • trunk/Source/WebKit/WebProcess/WebPage/WebFrame.cpp

    r239535 r239993  
    264264    case WebPolicyAction::Download:
    265265        return WebCore::PolicyAction::Download;
    266     case WebPolicyAction::Suspend:
    267         break;
    268266    }
    269267    ASSERT_NOT_REACHED();
    … …  
    273271void WebFrame::didReceivePolicyDecision(uint64_t listenerID, WebPolicyAction action, uint64_t navigationID, DownloadID downloadID, Optional<WebsitePoliciesData>&& websitePolicies)
    274272{
    275     if (!m_coreFrame || !m_policyListenerID || listenerID != m_policyListenerID || !m_policyFunction) {
    276         if (action == WebPolicyAction::Suspend)
    277             page()->send(Messages::WebPageProxy::DidFailToSuspendAfterProcessSwap());
     273    if (!m_coreFrame || !m_policyListenerID || listenerID != m_policyListenerID || !m_policyFunction)
    278274        return;
    279     }
    280275
    281276    FramePolicyFunction function = WTFMove(m_policyFunction);
    … …  
    293288    }
    294289
    295     bool shouldSuspend = false;
    296     if (action == WebPolicyAction::Suspend) {
    297         shouldSuspend = true;
    298         action = WebPolicyAction::Ignore;
    299     }
    300 
    301290    function(toPolicyAction(action));
    302 
    303     if (shouldSuspend)
    304         page()->suspendForProcessSwap();
    305291}
    306292
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r239881 r239993  
    402402    , m_cpuLimit(parameters.cpuLimit)
    403403#if PLATFORM(MAC)
    404     , m_shouldAttachDrawingAreaOnPageTransition(parameters.isSwapFromSuspended)
     404    , m_shouldAttachDrawingAreaOnPageTransition(parameters.isProcessSwap)
    405405#endif
    406406{
    … …  
    472472    m_drawingArea->setShouldScaleViewToFitDocument(parameters.shouldScaleViewToFitDocument);
    473473
    474     if (parameters.isSwapFromSuspended)
    475         freezeLayerTree(LayerTreeFreezeReason::SwapFromSuspended);
     474    if (parameters.isProcessSwap)
     475        freezeLayerTree(LayerTreeFreezeReason::ProcessSwap);
    476476
    477477#if ENABLE(ASYNC_SCROLLING)
    … …  
    697697        m_drawingArea->setPaintingEnabled(true);
    698698#if PLATFORM(MAC)
    699         m_shouldAttachDrawingAreaOnPageTransition = parameters.isSwapFromSuspended;
     699        m_shouldAttachDrawingAreaOnPageTransition = parameters.isProcessSwap;
    700700#endif
    701701        unfreezeLayerTree(LayerTreeFreezeReason::PageSuspended);
    … …  
    30543054    if (!frame)
    30553055        return;
    3056     if (policyAction == WebPolicyAction::Suspend) {
    3057         ASSERT(frame == m_mainFrame);
    3058         setIsSuspended(true);
    3059 
    3060         WebProcess::singleton().sendPrewarmInformation(mainWebFrame()->url());
    3061     }
    30623056    frame->didReceivePolicyDecision(listenerID, policyAction, navigationID, downloadID, WTFMove(websitePolicies));
    30633057}
    … …  
    31013095    bool isInitialEmptyDocument = !m_mainFrame;
    31023096    if (!isInitialEmptyDocument)
    3103         unfreezeLayerTree(LayerTreeFreezeReason::SwapFromSuspended);
     3097        unfreezeLayerTree(LayerTreeFreezeReason::ProcessSwap);
    31043098
    31053099#if PLATFORM(MAC)
    … …  
    63136307        // Unfrozen on drawing area reset.
    63146308        freezeLayerTree(LayerTreeFreezeReason::PageSuspended);
     6309
     6310        WebProcess::singleton().sendPrewarmInformation(mainWebFrame()->url());
     6311
     6312        suspendForProcessSwap();
    63156313    } else
    63166314        m_shouldResetDrawingAreaAfterSuspend = true;
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r239777 r239993  
    697697        PageSuspended           = 1 << 3,
    698698        Printing                = 1 << 4,
    699         SwapFromSuspended       = 1 << 5,
     699        ProcessSwap             = 1 << 5,
    700700    };
    701701    void freezeLayerTree(LayerTreeFreezeReason);
  • trunk/Source/WebKit/WebProcess/WebPage/mac/TiledCoreAnimationDrawingArea.mm

    r239777 r239993  
    9898    setColorSpace(parameters.colorSpace);
    9999
    100     if (!parameters.isSwapFromSuspended)
     100    if (!parameters.isProcessSwap)
    101101        attach();
    102102}
  • trunk/Tools/ChangeLog

    r239991 r239993  
     12019-01-15  Chris Dumez  <cdumez@apple.com>
     2
     3        Regression(PSON) View becomes blank after click a cross-site download link
     4        https://bugs.webkit.org/show_bug.cgi?id=193361
     5        <rdar://problem/47099573>
     6
     7        Reviewed by Geoff Garen.
     8
     9        Add API test coverage.
     10
     11        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     12        (-[PSONNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
     13
    1142019-01-15  Zalan Bujtas  <zalan@apple.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r239726 r239993  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2019 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
    … …  
    7373static bool willPerformClientRedirect;
    7474static bool didPerformClientRedirect;
     75static bool shouldConvertToDownload;
    7576static RetainPtr<NSURL> clientRedirectSourceURL;
    7677static RetainPtr<NSURL> clientRedirectDestinationURL;
    … …  
    127128        decisionHandler(WKNavigationActionPolicyAllow);
    128129    didRepondToPolicyDecisionCall = true;
     130}
     131
     132- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     133{
     134    decisionHandler(shouldConvertToDownload ? _WKNavigationResponsePolicyBecomeDownload : WKNavigationResponsePolicyAllow);
    129135}
    130136
    … …  
    14061412    EXPECT_FALSE(serverRedirected);
    14071413    EXPECT_EQ(3, numberOfDecidePolicyCalls);
    1408     EXPECT_EQ(2u, seenPIDs.size());
     1414    EXPECT_EQ(3u, seenPIDs.size());
    14091415}
    14101416
    … …  
    14661472
    14671473    EXPECT_WK_STREQ(@"pson://www.webkit.org/main1.html", [[webView URL] absoluteString]);
     1474}
     1475
     1476static const char* linkToWebKitBytes = R"PSONRESOURCE(
     1477<body>
     1478  <a id="testLink" href="pson://www.webkit.org/main.html">Link</a>
     1479</body>
     1480)PSONRESOURCE";
     1481
     1482TEST(ProcessSwap, PolicyCancelAfterServerRedirect)
     1483{
     1484    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
     1485    processPoolConfiguration.get().processSwapsOnNavigation = YES;
     1486    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     1487
     1488    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     1489    [webViewConfiguration setProcessPool:processPool.get()];
     1490    auto handler = adoptNS([[PSONScheme alloc] init]);
     1491    [handler addMappingFromURLString:@"pson://www.google.com/main.html" toData:linkToWebKitBytes];
     1492    [handler addRedirectFromURLString:@"pson://www.webkit.org/main.html" toURLString:@"pson://www.apple.com/ignore.html"];
     1493    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
     1494
     1495    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     1496    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     1497    [webView setNavigationDelegate:navigationDelegate.get()];
     1498
     1499    navigationDelegate->decidePolicyForNavigationAction = ^(WKNavigationAction *action, void (^decisionHandler)(WKNavigationActionPolicy)) {
     1500        if ([action.request.URL.absoluteString hasSuffix:@"ignore.html"]) {
     1501            decisionHandler(WKNavigationActionPolicyCancel);
     1502            return;
     1503        }
     1504        decisionHandler(WKNavigationActionPolicyAllow);
     1505    };
     1506
     1507    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
     1508    [webView loadRequest:request];
     1509
     1510    TestWebKitAPI::Util::run(&done);
     1511    done = false;
     1512    auto pidAfterFirstLoad = [webView _webProcessIdentifier];
     1513
     1514    EXPECT_EQ(1, numberOfDecidePolicyCalls);
     1515
     1516    [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
     1517
     1518    TestWebKitAPI::Util::run(&failed);
     1519    failed = false;
     1520    done = false;
     1521
     1522    EXPECT_EQ(3, numberOfDecidePolicyCalls);
     1523
     1524    // We should still be on google.com.
     1525    EXPECT_EQ(pidAfterFirstLoad, [webView _webProcessIdentifier]);
     1526    EXPECT_WK_STREQ(@"pson://www.google.com/main.html", [[webView URL] absoluteString]);
     1527
     1528    [webView evaluateJavaScript:@"testLink.innerText" completionHandler: [&] (id innerText, NSError *error) {
     1529        EXPECT_WK_STREQ(@"Link", innerText);
     1530        done = true;
     1531    }];
     1532    TestWebKitAPI::Util::run(&done);
     1533    done = false;
     1534}
     1535
     1536TEST(ProcessSwap, CrossSiteDownload)
     1537{
     1538    auto processPoolConfiguration = adoptNS([[_WKProcessPoolConfiguration alloc] init]);
     1539    processPoolConfiguration.get().processSwapsOnNavigation = YES;
     1540    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     1541
     1542    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     1543    [webViewConfiguration setProcessPool:processPool.get()];
     1544    auto handler = adoptNS([[PSONScheme alloc] init]);
     1545    [handler addMappingFromURLString:@"pson://www.google.com/main.html" toData:linkToWebKitBytes];
     1546    [handler addMappingFromURLString:@"pson://www.webkit.org/main.html" toData:"Hello"];
     1547    [webViewConfiguration setURLSchemeHandler:handler.get() forURLScheme:@"pson"];
     1548
     1549    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     1550    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     1551    [webView setNavigationDelegate:navigationDelegate.get()];
     1552
     1553    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"pson://www.google.com/main.html"]];
     1554    [webView loadRequest:request];
     1555
     1556    TestWebKitAPI::Util::run(&done);
     1557    done = false;
     1558    auto pidAfterFirstLoad = [webView _webProcessIdentifier];
     1559
     1560    shouldConvertToDownload = true;
     1561    [webView evaluateJavaScript:@"testLink.click()" completionHandler:nil];
     1562
     1563    TestWebKitAPI::Util::run(&failed);
     1564    failed = false;
     1565    shouldConvertToDownload = false;
     1566
     1567    // We should still be on google.com.
     1568    EXPECT_EQ(pidAfterFirstLoad, [webView _webProcessIdentifier]);
     1569    EXPECT_WK_STREQ(@"pson://www.google.com/main.html", [[webView URL] absoluteString]);
     1570
     1571    [webView evaluateJavaScript:@"testLink.innerText" completionHandler: [&] (id innerText, NSError *error) {
     1572        EXPECT_WK_STREQ(@"Link", innerText);
     1573        done = true;
     1574    }];
     1575    TestWebKitAPI::Util::run(&done);
     1576    done = false;
    14681577}
    14691578
    … …  
    22332342    EXPECT_EQ(7u, [receivedMessages count]);
    22342343    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow NOT persisted", receivedMessages.get()[0]);
    2235     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[1]);
    2236     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[2]);
    2237     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[3]);
    2238     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[4]);
    2239     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[5]);
    2240     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[6]);
     2344    if ([receivedMessages.get()[1] hasPrefix:@"pson://www.webkit.org/main.html"]) {
     2345        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[1]);
     2346        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[2]);
     2347    } else {
     2348        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow NOT persisted", receivedMessages.get()[1]);
     2349        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[2]);
     2350    }
     2351    if ([receivedMessages.get()[3] hasPrefix:@"pson://www.apple.com/main.html"]) {
     2352        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[3]);
     2353        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[4]);
     2354    } else {
     2355        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pageshow persisted", receivedMessages.get()[3]);
     2356        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pagehide persisted", receivedMessages.get()[4]);
     2357    }
     2358    if ([receivedMessages.get()[5] hasPrefix:@"pson://www.webkit.org/main.html"]) {
     2359        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[5]);
     2360        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[6]);
     2361    } else {
     2362        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - pageshow persisted", receivedMessages.get()[5]);
     2363        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - pagehide persisted", receivedMessages.get()[6]);
     2364    }
    22412365}
    22422366
    … …  
    23082432    EXPECT_EQ(7u, [receivedMessages count]);
    23092433    EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[0]);
    2310     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[1]);
    2311     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[2]);
    2312     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[3]);
    2313     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[4]);
    2314     EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[5]);
    2315     EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[6]);
     2434    if ([receivedMessages.get()[1] hasPrefix:@"pson://www.webkit.org/main.html"]) {
     2435        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[1]);
     2436        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[2]);
     2437    } else {
     2438        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[1]);
     2439        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[2]);
     2440    }
     2441    if ([receivedMessages.get()[3] hasPrefix:@"pson://www.apple.com/main.html"]) {
     2442        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[3]);
     2443        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[4]);
     2444    } else {
     2445        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - load", receivedMessages.get()[3]);
     2446        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - unload", receivedMessages.get()[4]);
     2447    }
     2448    if ([receivedMessages.get()[5] hasPrefix:@"pson://www.webkit.org/main.html"]) {
     2449        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[5]);
     2450        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[6]);
     2451    } else {
     2452        EXPECT_WK_STREQ(@"pson://www.apple.com/main.html - load", receivedMessages.get()[5]);
     2453        EXPECT_WK_STREQ(@"pson://www.webkit.org/main.html - unload", receivedMessages.get()[6]);
     2454    }
    23162455}
    23172456
Note: See TracChangeset for help on using the changeset viewer.