Changeset 229666 in webkit


Ignore:
Timestamp:
Mar 16, 2018 9:11:54 AM (6 years ago)
Author:
Chris Dumez
Message:

URLSchemeHandler.Basic API test fails with async policy delegates
https://bugs.webkit.org/show_bug.cgi?id=183678

Reviewed by Alex Christensen.

Source/WebKit:

The issue is that the client calls _didPerformRedirection / didReceiveResponse / didReceiveData / didFinish
on the URLScheme task one after the one, synchronously. However, redirects and responses can be processed
asynchronously. To address the issue, we now queue operations requested by the client if we're waiting
for an async policy delegate.

  • WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:

(WebKit::WebURLSchemeTaskProxy::didPerformRedirection):
(WebKit::WebURLSchemeTaskProxy::didReceiveResponse):
(WebKit::WebURLSchemeTaskProxy::didReceiveData):
(WebKit::WebURLSchemeTaskProxy::didComplete):
(WebKit::WebURLSchemeTaskProxy::processNextPendingTask):

  • WebProcess/WebPage/WebURLSchemeTaskProxy.h:

(WebKit::WebURLSchemeTaskProxy::queueTask):

Tools:

Add API test coverage.

  • TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:

(-[URLSchemeHandlerAsyncNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]):
(-[URLSchemeHandlerAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
(TEST):

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r229661 r229666  
     12018-03-16  Chris Dumez  <cdumez@apple.com>
     2
     3        URLSchemeHandler.Basic API test fails with async policy delegates
     4        https://bugs.webkit.org/show_bug.cgi?id=183678
     5
     6        Reviewed by Alex Christensen.
     7
     8        The issue is that the client calls _didPerformRedirection / didReceiveResponse / didReceiveData / didFinish
     9        on the URLScheme task one after the one, synchronously. However, redirects and responses can be processed
     10        asynchronously. To address the issue, we now queue operations requested by the client if we're waiting
     11        for an async policy delegate.
     12
     13        * WebProcess/WebPage/WebURLSchemeTaskProxy.cpp:
     14        (WebKit::WebURLSchemeTaskProxy::didPerformRedirection):
     15        (WebKit::WebURLSchemeTaskProxy::didReceiveResponse):
     16        (WebKit::WebURLSchemeTaskProxy::didReceiveData):
     17        (WebKit::WebURLSchemeTaskProxy::didComplete):
     18        (WebKit::WebURLSchemeTaskProxy::processNextPendingTask):
     19        * WebProcess/WebPage/WebURLSchemeTaskProxy.h:
     20        (WebKit::WebURLSchemeTaskProxy::queueTask):
     21
    1222018-03-16  Claudio Saavedra  <csaavedra@igalia.com>
    223
  • trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.cpp

    r229209 r229666  
    7171   
    7272    auto completionHandler = [this, protectedThis = makeRef(*this), originalRequest = request] (ResourceRequest&& request) {
    73         m_waitingForRedirectCompletionHandler = false;
     73        m_waitingForCompletionHandler = false;
    7474        // We do not inform the UIProcess of WebKit's new request with the given suggested request.
    7575        // We do want to know if WebKit would have generated a request that differs from the suggested request, though.
    7676        if (request.url() != originalRequest.url())
    7777            WTFLogAlways("Redirected scheme task would have been sent to a different URL.");
     78
     79        processNextPendingTask();
    7880    };
    7981   
    80     if (m_waitingForRedirectCompletionHandler)
    81         WTFLogAlways("Received redirect during previous redirect processing.");
    82     m_waitingForRedirectCompletionHandler = true;
     82    if (m_waitingForCompletionHandler) {
     83        WTFLogAlways("Received redirect during previous redirect processing, queuing it.");
     84        queueTask([this, protectedThis = makeRef(*this), redirectResponse = WTFMove(redirectResponse), request = WTFMove(request)]() mutable {
     85            didPerformRedirection(WTFMove(redirectResponse), WTFMove(request));
     86        });
     87        return;
     88    }
     89    m_waitingForCompletionHandler = true;
    8390
    8491    m_coreLoader->willSendRequest(WTFMove(request), redirectResponse, WTFMove(completionHandler));
     
    8794void WebURLSchemeTaskProxy::didReceiveResponse(const ResourceResponse& response)
    8895{
    89     if (m_waitingForRedirectCompletionHandler)
    90         WTFLogAlways("Received response during redirect processing.");
     96    if (m_waitingForCompletionHandler) {
     97        WTFLogAlways("Received response during redirect processing, queuing it.");
     98        queueTask([this, protectedThis = makeRef(*this), response] {
     99            didReceiveResponse(response);
     100        });
     101        return;
     102    }
    91103   
    92104    if (!hasLoader())
    93105        return;
    94106
    95     m_coreLoader->didReceiveResponse(response, nullptr);
     107    m_waitingForCompletionHandler = true;
     108    m_coreLoader->didReceiveResponse(response, [this, protectedThis = makeRef(*this)] {
     109        m_waitingForCompletionHandler = false;
     110        processNextPendingTask();
     111    });
    96112}
    97113
     
    101117        return;
    102118
     119    if (m_waitingForCompletionHandler) {
     120        WTFLogAlways("Received data during response processing, queuing it.");
     121        Vector<uint8_t> dataVector;
     122        dataVector.append(data, size);
     123        queueTask([this, protectedThis = makeRef(*this), dataVector = WTFMove(dataVector)] {
     124            didReceiveData(dataVector.size(), dataVector.data());
     125        });
     126        return;
     127    }
     128
    103129    m_coreLoader->didReceiveData(reinterpret_cast<const char*>(data), size, 0, DataPayloadType::DataPayloadBytes);
     130    processNextPendingTask();
    104131}
    105132
     
    108135    if (!hasLoader())
    109136        return;
     137
     138    if (m_waitingForCompletionHandler) {
     139        queueTask([this, protectedThis = makeRef(*this), error] {
     140            didComplete(error);
     141        });
     142        return;
     143    }
    110144
    111145    if (error.isNull())
     
    125159}
    126160
     161void WebURLSchemeTaskProxy::processNextPendingTask()
     162{
     163    if (!m_queuedTasks.isEmpty())
     164        m_queuedTasks.takeFirst()();
     165}
     166
    127167} // namespace WebKit
  • trunk/Source/WebKit/WebProcess/WebPage/WebURLSchemeTaskProxy.h

    r218750 r229666  
    2727
    2828#include <WebCore/ResourceRequest.h>
     29#include <wtf/Deque.h>
    2930#include <wtf/RefCounted.h>
    3031
     
    6263    bool hasLoader();
    6364
     65    void queueTask(Function<void()>&& task) { m_queuedTasks.append(WTFMove(task)); }
     66    void processNextPendingTask();
     67
    6468    WebURLSchemeHandlerProxy& m_urlSchemeHandler;
    6569    RefPtr<WebCore::ResourceLoader> m_coreLoader;
    6670    WebCore::ResourceRequest m_request;
    6771    unsigned long m_identifier;
    68     bool m_waitingForRedirectCompletionHandler { };
     72    bool m_waitingForCompletionHandler { false };
     73    Deque<Function<void()>> m_queuedTasks;
    6974};
    7075
  • trunk/Tools/ChangeLog

    r229664 r229666  
     12018-03-16  Chris Dumez  <cdumez@apple.com>
     2
     3        URLSchemeHandler.Basic API test fails with async policy delegates
     4        https://bugs.webkit.org/show_bug.cgi?id=183678
     5
     6        Reviewed by Alex Christensen.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm:
     11        (-[URLSchemeHandlerAsyncNavigationDelegate webView:decidePolicyForNavigationAction:decisionHandler:]):
     12        (-[URLSchemeHandlerAsyncNavigationDelegate webView:decidePolicyForNavigationResponse:decisionHandler:]):
     13        (TEST):
     14
    1152018-03-16  Zalan Bujtas  <zalan@apple.com>
    216
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WKURLSchemeHandler-1.mm

    r220107 r229666  
    100100@end
    101101
     102@interface URLSchemeHandlerAsyncNavigationDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
     103@end
     104
     105@implementation URLSchemeHandlerAsyncNavigationDelegate
     106
     107- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
     108{
     109    int64_t deferredWaitTime = 100 * NSEC_PER_MSEC;
     110    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, deferredWaitTime);
     111    dispatch_after(when, dispatch_get_main_queue(), ^{
     112        decisionHandler(WKNavigationActionPolicyAllow);
     113    });
     114
     115}
     116
     117- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     118{
     119    int64_t deferredWaitTime = 100 * NSEC_PER_MSEC;
     120    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, deferredWaitTime);
     121    dispatch_after(when, dispatch_get_main_queue(), ^{
     122        decisionHandler(WKNavigationResponsePolicyAllow);
     123    });
     124}
     125@end
     126
     127
    102128static const char mainBytes[] =
    103129"<html>" \
     
    115141
    116142    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     143
     144    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:main"]];
     145    [webView loadRequest:request];
     146
     147    TestWebKitAPI::Util::run(&done);
     148
     149    EXPECT_EQ([handler.get().startedURLs count], 2u);
     150    EXPECT_TRUE([[handler.get().startedURLs objectAtIndex:0] isEqual:[NSURL URLWithString:@"testing:main"]]);
     151    EXPECT_TRUE([[handler.get().startedURLs objectAtIndex:1] isEqual:[NSURL URLWithString:@"testing:image"]]);
     152    EXPECT_EQ([handler.get().stoppedURLs count], 0u);
     153}
     154
     155TEST(URLSchemeHandler, BasicWithAsyncPolicyDelegate)
     156{
     157    done = false;
     158
     159    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     160
     161    RetainPtr<SchemeHandler> handler = adoptNS([[SchemeHandler alloc] initWithData:[NSData dataWithBytesNoCopy:(void*)mainBytes length:sizeof(mainBytes) freeWhenDone:NO] mimeType:@"text/html"]);
     162    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
     163
     164    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     165    auto delegate = adoptNS([[URLSchemeHandlerAsyncNavigationDelegate alloc] init]);
     166    [webView setNavigationDelegate:delegate.get()];
    117167
    118168    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"testing:main"]];
Note: See TracChangeset for help on using the changeset viewer.