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

Changeset 286505 in webkit


Ignore:
Timestamp:
Dec 3, 2021, 11:39:02 AM (5 years ago)
Author:
Chris Dumez
Message:

Follow-up to r286479 to add API test and address issues found by the test
https://bugs.webkit.org/show_bug.cgi?id=233798

Reviewed by Darin Adler.

Source/WebKit:

Add functionality needed for API testing and fix issues found by the API test.

  • UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
  • UIProcess/API/Cocoa/WKWebViewTesting.mm:

(-[WKWebView _isLayerTreeFrozenForTesting:]):

  • UIProcess/WebPageProxy.cpp:

(WebKit::WebPageProxy::destroyProvisionalPage):
(WebKit::WebPageProxy::isLayerTreeFrozen):

  • UIProcess/WebPageProxy.h:
  • WebProcess/WebPage/WebPage.cpp:

(WebKit::WebPage::isLayerTreeFrozen):

  • WebProcess/WebPage/WebPage.h:
  • WebProcess/WebPage/WebPage.messages.in:

Add new SPI to check if the layer tree is frozen in the WebProcess so that I could
write an API test for this.

  • UIProcess/ProvisionalPageProxy.cpp:

(WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
Make sure m_provisionalLoadURL gets initialized when the ProvisionalPageProxy gets
constructed *after* the provisional load has already started (which is the case
when the process swap is triggered by COOP).

(WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
If the provisional load load fails in the provisional process, and the ProvisionalPageProxy
was constructed on resource response (COOP case), then no longer forward the
didFailProvisionalLoadForFrame() to the WebPageProxy. Instead, we destroy the
ProvisionalPageProxy. This is to avoid duplicate calls to didFailProvisionalLoadForFrame().
In this case, there is still a provisional load ongoing in the committed process and the
ProvisionalPageProxy destructor will take care of stopping that provisional load (due to
r286479), which will cause the committed process to send its own
didFailProvisionalLoadForFrame IPC.

Tools:

Add API test coverage.

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

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r286501 r286505  
     12021-12-03  Chris Dumez  <cdumez@apple.com>
     2
     3        Follow-up to r286479 to add API test and address issues found by the test
     4        https://bugs.webkit.org/show_bug.cgi?id=233798
     5
     6        Reviewed by Darin Adler.
     7
     8        Add functionality needed for API testing and fix issues found by the API test.
     9
     10        * UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h:
     11        * UIProcess/API/Cocoa/WKWebViewTesting.mm:
     12        (-[WKWebView _isLayerTreeFrozenForTesting:]):
     13        * UIProcess/WebPageProxy.cpp:
     14        (WebKit::WebPageProxy::destroyProvisionalPage):
     15        (WebKit::WebPageProxy::isLayerTreeFrozen):
     16        * UIProcess/WebPageProxy.h:
     17        * WebProcess/WebPage/WebPage.cpp:
     18        (WebKit::WebPage::isLayerTreeFrozen):
     19        * WebProcess/WebPage/WebPage.h:
     20        * WebProcess/WebPage/WebPage.messages.in:
     21        Add new SPI to check if the layer tree is frozen in the WebProcess so that I could
     22        write an API test for this.
     23
     24        * UIProcess/ProvisionalPageProxy.cpp:
     25        (WebKit::ProvisionalPageProxy::ProvisionalPageProxy):
     26        Make sure m_provisionalLoadURL gets initialized when the ProvisionalPageProxy gets
     27        constructed *after* the provisional load has already started (which is the case
     28        when the process swap is triggered by COOP).
     29
     30        (WebKit::ProvisionalPageProxy::didFailProvisionalLoadForFrame):
     31        If the provisional load load fails in the provisional process, and the ProvisionalPageProxy
     32        was constructed on resource response (COOP case), then no longer forward the
     33        didFailProvisionalLoadForFrame() to the WebPageProxy. Instead, we destroy the
     34        ProvisionalPageProxy. This is to avoid duplicate calls to didFailProvisionalLoadForFrame().
     35        In this case, there is still a provisional load ongoing in the committed process and the
     36        ProvisionalPageProxy destructor will take care of stopping that provisional load (due to
     37        r286479), which will cause the committed process to send its own
     38        didFailProvisionalLoadForFrame IPC.
     39
    1402021-12-03  Wenson Hsieh  <wenson_hsieh@apple.com>
    241
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewPrivateForTesting.h

    r284786 r286505  
    117117- (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
    118118
     119- (void)_isLayerTreeFrozenForTesting:(void (^)(BOOL frozen))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
     120
    119121@end
    120122
  • trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebViewTesting.mm

    r284786 r286505  
    425425}
    426426
     427- (void)_isLayerTreeFrozenForTesting:(void (^)(BOOL frozen))completionHandler
     428{
     429    _page->isLayerTreeFrozen([completionHandler = makeBlockPtr(completionHandler)](bool isFrozen) {
     430        completionHandler(isFrozen);
     431    });
     432}
     433
    427434- (void)_gpuToWebProcessConnectionCountForTesting:(void(^)(NSUInteger))completionHandler
    428435{
  • trunk/Source/WebKit/UIProcess/ProvisionalPageProxy.cpp

    r286479 r286505  
    6868    , m_processSwapRequestedByClient(processSwapRequestedByClient)
    6969    , m_isProcessSwappingOnNavigationResponse(isProcessSwappingOnNavigationResponse)
     70    , m_provisionalLoadURL(isProcessSwappingOnNavigationResponse ? request.url() : URL())
    7071#if PLATFORM(IOS_FAMILY)
    7172    , m_provisionalLoadActivity(m_process->throttler().foregroundActivity("Provisional Load"_s))
     
    297298    m_provisionalLoadURL = { };
    298299
     300    if (m_isProcessSwappingOnNavigationResponse) {
     301        // If the provisional load fails and we were process-swapping on navigation response, then we simply destroy ourselves.
     302        // In this case, the provisional load is still ongoing in the committed process and the ProvisionalPageProxy destructor
     303        // will stop it and cause the committed process to send its own DidFailProvisionalLoadForFrame IPC.
     304        ASSERT(m_page.provisionalPageProxy() == this);
     305        m_page.destroyProvisionalPage();
     306        return;
     307    }
     308
    299309    // Make sure the Page's main frame's expectedURL gets cleared since we updated it in didStartProvisionalLoad.
    300310    if (auto* pageMainFrame = m_page.mainFrame())
  • trunk/Source/WebKit/UIProcess/WebPageProxy.cpp

    r286479 r286505  
    35883588}
    35893589
     3590void WebPageProxy::destroyProvisionalPage()
     3591{
     3592    m_provisionalPage = nullptr;
     3593}
     3594
    35903595void WebPageProxy::continueNavigationInNewProcess(API::Navigation& navigation, std::unique_ptr<SuspendedPageProxy>&& suspendedPage, Ref<WebProcessProxy>&& newProcess, ProcessSwapRequestedByClient processSwapRequestedByClient, ShouldTreatAsContinuingLoad shouldTreatAsContinuingLoad, RefPtr<API::WebsitePolicies>&& websitePolicies, std::optional<NetworkResourceLoadIdentifier> existingNetworkResourceLoadIdentifierToResume)
    35913596{
     
    1080110806}
    1080210807
     10808void WebPageProxy::isLayerTreeFrozen(CompletionHandler<void(bool)>&& completionHandler)
     10809{
     10810    sendWithAsyncReply(Messages::WebPage::IsLayerTreeFrozen(), WTFMove(completionHandler));
     10811}
     10812
    1080310813void WebPageProxy::requestSpeechRecognitionPermission(WebCore::SpeechRecognitionRequest& request, CompletionHandler<void(std::optional<SpeechRecognitionError>&&)>&& completionHandler)
    1080410814{
  • trunk/Source/WebKit/UIProcess/WebPageProxy.h

    r286346 r286505  
    15031503    std::optional<WebCore::ScrollbarOverlayStyle> overlayScrollbarStyle() const { return m_scrollbarOverlayStyle; }
    15041504
     1505    void isLayerTreeFrozen(CompletionHandler<void(bool)>&&);
     1506
    15051507    // When the state of the window changes such that the WebPage needs immediate update, the UIProcess sends a new
    15061508    // ActivityStateChangeID to the WebProcess through the SetActivityState message. The UIProcess will wait till it
     
    17711773    ProvisionalPageProxy* provisionalPageProxy() const { return m_provisionalPage.get(); }
    17721774    void commitProvisionalPage(WebCore::FrameIdentifier, FrameInfoData&&, WebCore::ResourceRequest&&, uint64_t navigationID, const String& mimeType, bool frameHasCustomContentProvider, WebCore::FrameLoadType, const WebCore::CertificateInfo&, bool usedLegacyTLS, bool containsPluginDocument, std::optional<WebCore::HasInsecureContent> forcedHasInsecureContent, WebCore::MouseEventPolicy, const UserData&);
     1775    void destroyProvisionalPage();
    17731776
    17741777    // Logic shared between the WebPageProxy and the ProvisionalPageProxy.
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp

    r286469 r286505  
    27882788}
    27892789
     2790void WebPage::isLayerTreeFrozen(CompletionHandler<void(bool)>&& completionHandler)
     2791{
     2792    completionHandler(!!m_layerTreeFreezeReasons);
     2793}
     2794
    27902795void WebPage::updateDrawingAreaLayerTreeFreezeState()
    27912796{
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.h

    r286346 r286505  
    860860    void unfreezeLayerTree(LayerTreeFreezeReason);
    861861
     862    void isLayerTreeFrozen(CompletionHandler<void(bool)>&&);
     863
    862864    void markLayersVolatile(CompletionHandler<void(bool)>&& completionHandler = { });
    863865    void cancelMarkLayersVolatile();
  • trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in

    r285949 r286505  
    403403    FreezeLayerTreeDueToSwipeAnimation()
    404404    UnfreezeLayerTreeDueToSwipeAnimation()
     405    IsLayerTreeFrozen() -> (bool isFrozen) Async
    405406
    406407    # Printing.
  • trunk/Tools/ChangeLog

    r286492 r286505  
     12021-12-03  Chris Dumez  <cdumez@apple.com>
     2
     3        Follow-up to r286479 to add API test and address issues found by the test
     4        https://bugs.webkit.org/show_bug.cgi?id=233798
     5
     6        Reviewed by Darin Adler.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm:
     11
    1122021-12-03  Alex Christensen  <achristensen@webkit.org>
    213
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ProcessSwapOnNavigation.mm

    r285877 r286505  
    72657265    // Clear the WebProcess cache while the processes are being checked for responsiveness.
    72667266    [processPool _clearWebProcessCache];
     7267}
     7268
     7269TEST(ProcessSwap, ResponsePolicyDownloadAfterCOOPProcessSwap)
     7270{
     7271    using namespace TestWebKitAPI;
     7272
     7273    HTTPServer server({
     7274        { "/source.html", { "foo" } },
     7275        { "/destination.html", { { { "Content-Type", "text/html" }, { "Cross-Origin-Opener-Policy", "same-origin" } }, "bar" } },
     7276    }, HTTPServer::Protocol::Https);
     7277
     7278    auto processPoolConfiguration = psonProcessPoolConfiguration();
     7279    auto processPool = adoptNS([[WKProcessPool alloc] _initWithConfiguration:processPoolConfiguration.get()]);
     7280
     7281    auto webViewConfiguration = adoptNS([[WKWebViewConfiguration alloc] init]);
     7282    [webViewConfiguration setProcessPool:processPool.get()];
     7283    for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
     7284        if ([feature.key isEqualToString:@"CrossOriginOpenerPolicyEnabled"])
     7285            [[webViewConfiguration preferences] _setEnabled:YES forExperimentalFeature:feature];
     7286        else if ([feature.key isEqualToString:@"CrossOriginEmbedderPolicyEnabled"])
     7287            [[webViewConfiguration preferences] _setEnabled:YES forExperimentalFeature:feature];
     7288    }
     7289
     7290    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:webViewConfiguration.get()]);
     7291    auto navigationDelegate = adoptNS([[PSONNavigationDelegate alloc] init]);
     7292    [webView setNavigationDelegate:navigationDelegate.get()];
     7293
     7294    done = false;
     7295    [webView loadRequest:server.request("/source.html")];
     7296    Util::run(&done);
     7297    done = false;
     7298
     7299    auto pid1 = [webView _webProcessIdentifier];
     7300
     7301    // The next navigation will get converted into a download via decidePolicyForNavigationResponse.
     7302    shouldConvertToDownload = true;
     7303
     7304    done = false;
     7305    failed = false;
     7306    [webView loadRequest:server.request("/destination.html")];
     7307    Util::run(&failed);
     7308    failed = false;
     7309    shouldConvertToDownload = false;
     7310
     7311    auto pid2 = [webView _webProcessIdentifier];
     7312    EXPECT_EQ(pid1, pid2);
     7313
     7314    // The layer tree should no longer be frozen since the navigation didn't happen.
     7315    __block bool isFrozen = true;
     7316    do {
     7317        Util::sleep(0.1);
     7318        done = false;
     7319        [webView _isLayerTreeFrozenForTesting:^(BOOL frozen) {
     7320            isFrozen = frozen;
     7321            done = true;
     7322        }];
     7323        Util::run(&done);
     7324    } while (isFrozen);
    72677325}
    72687326
Note: See TracChangeset for help on using the changeset viewer.