Changeset 229477 in webkit


Ignore:
Timestamp:
Mar 9, 2018 12:47:11 PM (6 years ago)
Author:
youenn@apple.com
Message:

ServiceWorkerClientFetch should send data to its resource loader once the didReceiveResponse completion handler is called
https://bugs.webkit.org/show_bug.cgi?id=183110

Reviewed by Chris Dumez.

Buffering data/finish event/fail event until the response completion handler is called.

  • WebProcess/Storage/ServiceWorkerClientFetch.cpp:

(WebKit::ServiceWorkerClientFetch::didReceiveResponse):
(WebKit::ServiceWorkerClientFetch::didReceiveData):
(WebKit::ServiceWorkerClientFetch::didFinish):
(WebKit::ServiceWorkerClientFetch::didFail):
(WebKit::ServiceWorkerClientFetch::didNotHandle):
(WebKit::ServiceWorkerClientFetch::cancel):
(WebKit::ServiceWorkerClientFetch::continueLoadingAfterCheckingResponse):

  • WebProcess/Storage/ServiceWorkerClientFetch.h:
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r229475 r229477  
     12018-03-09  Youenn Fablet  <youenn@apple.com>
     2
     3        ServiceWorkerClientFetch should send data to its resource loader once the didReceiveResponse completion handler is called
     4        https://bugs.webkit.org/show_bug.cgi?id=183110
     5
     6        Reviewed by Chris Dumez.
     7
     8        Buffering data/finish event/fail event until the response completion handler is called.
     9
     10        * WebProcess/Storage/ServiceWorkerClientFetch.cpp:
     11        (WebKit::ServiceWorkerClientFetch::didReceiveResponse):
     12        (WebKit::ServiceWorkerClientFetch::didReceiveData):
     13        (WebKit::ServiceWorkerClientFetch::didFinish):
     14        (WebKit::ServiceWorkerClientFetch::didFail):
     15        (WebKit::ServiceWorkerClientFetch::didNotHandle):
     16        (WebKit::ServiceWorkerClientFetch::cancel):
     17        (WebKit::ServiceWorkerClientFetch::continueLoadingAfterCheckingResponse):
     18        * WebProcess/Storage/ServiceWorkerClientFetch.h:
     19
    1202018-03-09  Jer Noble  <jer.noble@apple.com>
    221
  • trunk/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp

    r228852 r229477  
    107107        if (auto error = validateResponse(response)) {
    108108            m_loader->didFail(error.value());
     109            ASSERT(!m_loader);
    109110            if (auto callback = WTFMove(m_callback))
    110111                callback(Result::Succeeded);
     
    142143            response.setURL(m_loader->request().url());
    143144
     145        m_isCheckingResponse = true;
    144146        m_loader->didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis)] {
     147            m_isCheckingResponse = false;
     148            continueLoadingAfterCheckingResponse();
    145149            if (auto callback = WTFMove(m_callback))
    146150                callback(Result::Succeeded);
     
    149153}
    150154
    151 void ServiceWorkerClientFetch::didReceiveData(const IPC::DataReference& data, int64_t encodedDataLength)
    152 {
    153     callOnMainThread([this, protectedThis = makeRef(*this), data = data.vector(), encodedDataLength] {
    154         if (!m_loader)
    155             return;
    156 
    157         m_loader->didReceiveData(reinterpret_cast<const char*>(data.data()), data.size(), encodedDataLength, DataPayloadBytes);
     155void ServiceWorkerClientFetch::didReceiveData(const IPC::DataReference& dataReference, int64_t encodedDataLength)
     156{
     157    auto* data = reinterpret_cast<const char*>(dataReference.data());
     158    if (!m_buffer) {
     159        m_buffer = SharedBuffer::create(data, dataReference.size());
     160        m_encodedDataLength = encodedDataLength;
     161    } else {
     162        m_buffer->append(data, dataReference.size());
     163        m_encodedDataLength += encodedDataLength;
     164    }
     165
     166    if (m_isCheckingResponse)
     167        return;
     168
     169    callOnMainThread([this, protectedThis = makeRef(*this)] {
     170        if (!m_loader)
     171            return;
     172
     173        m_loader->didReceiveBuffer(m_buffer.releaseNonNull(), m_encodedDataLength, DataPayloadBytes);
     174        m_encodedDataLength = 0;
    158175    });
    159176}
     
    166183void ServiceWorkerClientFetch::didFinish()
    167184{
     185    m_didFinish = true;
     186
     187    if (m_isCheckingResponse)
     188        return;
     189
    168190    callOnMainThread([this, protectedThis = makeRef(*this)] {
    169191        if (!m_loader)
     
    193215void ServiceWorkerClientFetch::didFail()
    194216{
     217    m_didFail = true;
     218
     219    if (m_isCheckingResponse)
     220        return;
     221
    195222    callOnMainThread([this, protectedThis = makeRef(*this)] {
    196223        if (!m_loader)
     
    208235void ServiceWorkerClientFetch::didNotHandle()
    209236{
     237    ASSERT(!m_isCheckingResponse);
     238
    210239    callOnMainThread([this, protectedThis = makeRef(*this)] {
    211240        if (!m_loader)
     
    224253        callback(Result::Cancelled);
    225254    m_loader = nullptr;
     255    m_buffer = nullptr;
     256}
     257
     258void ServiceWorkerClientFetch::continueLoadingAfterCheckingResponse()
     259{
     260    ASSERT(!m_isCheckingResponse);
     261    if (!m_loader)
     262        return;
     263
     264    if (m_encodedDataLength) {
     265        callOnMainThread([this, protectedThis = makeRef(*this)] {
     266            if (!m_loader || !m_encodedDataLength)
     267                return;
     268            m_loader->didReceiveBuffer(m_buffer.releaseNonNull(), m_encodedDataLength, DataPayloadBytes);
     269            m_encodedDataLength = 0;
     270        });
     271    }
     272
     273    if (m_didFail) {
     274        didFail();
     275        return;
     276    }
     277
     278    if (m_didFinish)
     279        didFinish();
    226280}
    227281
  • trunk/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h

    r228198 r229477  
    6767    void didNotHandle();
    6868
     69    void continueLoadingAfterCheckingResponse();
     70
    6971    WebServiceWorkerProvider& m_serviceWorkerProvider;
    7072    RefPtr<WebCore::ResourceLoader> m_loader;
     
    7577    RedirectionStatus m_redirectionStatus { RedirectionStatus::None };
    7678    bool m_shouldClearReferrerOnHTTPSToHTTPRedirect { true };
     79    RefPtr<WebCore::SharedBuffer> m_buffer;
     80    int64_t m_encodedDataLength { 0 };
     81    bool m_isCheckingResponse { false };
     82    bool m_didFinish { false };
     83    bool m_didFail { false };
    7784};
    7885
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm

    r229150 r229477  
    154154@end
    155155
     156static bool shouldAccept = true;
     157static bool navigationComplete = false;
     158static bool navigationFailed = false;
     159
     160@interface TestSWAsyncNavigationDelegate : NSObject <WKNavigationDelegate, WKUIDelegate>
     161@end
     162
     163@implementation TestSWAsyncNavigationDelegate
     164
     165- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation
     166{
     167    navigationComplete = true;
     168}
     169
     170- (void)webView:(WKWebView *)webView didFailNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error
     171{
     172    navigationFailed = true;
     173    navigationComplete = true;
     174}
     175
     176- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(null_unspecified WKNavigation *)navigation withError:(NSError *)error
     177{
     178    navigationFailed = true;
     179    navigationComplete = true;
     180}
     181
     182- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
     183{
     184    decisionHandler(WKNavigationActionPolicyAllow);
     185}
     186
     187- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler
     188{
     189    int64_t deferredWaitTime = 100 * NSEC_PER_MSEC;
     190    dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, deferredWaitTime);
     191    dispatch_after(when, dispatch_get_main_queue(), ^{
     192        decisionHandler(shouldAccept ? WKNavigationResponsePolicyAllow : WKNavigationResponsePolicyCancel);
     193    });
     194}
     195@end
     196
     197
    156198static const char* mainBytes = R"SWRESOURCE(
    157199<script>
     
    619661}
    620662
     663TEST(ServiceWorkers, WaitForPolicyDelegate)
     664{
     665    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
     666
     667    // Start with a clean slate data store
     668    [[WKWebsiteDataStore defaultDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
     669        done = true;
     670    }];
     671    TestWebKitAPI::Util::run(&done);
     672    done = false;
     673
     674    RetainPtr<WKWebViewConfiguration> configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     675
     676    RetainPtr<SWMessageHandlerWithExpectedMessage> messageHandler = adoptNS([[SWMessageHandlerWithExpectedMessage alloc] init]);
     677    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
     678
     679    RetainPtr<SWSchemes> handler = adoptNS([[SWSchemes alloc] init]);
     680    handler->resources.set("sw://host/main.html", ResourceInfo { @"text/html", mainForFirstLoadInterceptTestBytes });
     681    handler->resources.set("sw://host/sw.js", ResourceInfo { @"application/javascript", scriptInterceptingFirstLoadBytes });
     682    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"SW"];
     683
     684    RetainPtr<WKWebView> webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     685    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
     686
     687    // Register a service worker and activate it.
     688    expectedMessage = "Service Worker activated";
     689    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
     690    [webView loadRequest:request];
     691
     692    TestWebKitAPI::Util::run(&done);
     693
     694    webView = nullptr;
     695    configuration = nullptr;
     696    messageHandler = nullptr;
     697    handler = nullptr;
     698
     699    done = false;
     700
     701    configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     702    messageHandler = adoptNS([[SWMessageHandlerWithExpectedMessage alloc] init]);
     703    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
     704
     705    handler = adoptNS([[SWSchemes alloc] init]);
     706    handler->resources.set("sw://host/main.html", ResourceInfo { @"text/html", mainForFirstLoadInterceptTestBytes });
     707    handler->resources.set("sw://host/sw.js", ResourceInfo { @"application/javascript", scriptInterceptingFirstLoadBytes });
     708    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"SW"];
     709
     710    webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     711    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
     712
     713    // Verify service worker is intercepting load.
     714    expectedMessage = "Intercepted by worker";
     715    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
     716    [webView loadRequest:request];
     717
     718    TestWebKitAPI::Util::run(&done);
     719    done = false;
     720
     721    webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     722    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
     723    auto delegate = adoptNS([[TestSWAsyncNavigationDelegate alloc] init]);
     724    [webView setNavigationDelegate:delegate.get()];
     725    [webView setUIDelegate:delegate.get()];
     726
     727    shouldAccept = true;
     728    navigationFailed = false;
     729    navigationComplete = false;
     730
     731    // Verify service worker load goes well when policy delegate is ok.
     732    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
     733    [webView loadRequest:request];
     734    TestWebKitAPI::Util::run(&navigationComplete);
     735
     736    EXPECT_FALSE(navigationFailed);
     737
     738    webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
     739    [webView.get().configuration.processPool _registerURLSchemeServiceWorkersCanHandle:@"sw"];
     740    [webView setNavigationDelegate:delegate.get()];
     741    [webView setUIDelegate:delegate.get()];
     742
     743    shouldAccept = false;
     744    navigationFailed = false;
     745    navigationComplete = false;
     746
     747    // Verify service worker load fails well when policy delegate is not ok.
     748    request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"sw://host/main.html"]];
     749    [webView loadRequest:request];
     750    TestWebKitAPI::Util::run(&navigationComplete);
     751
     752    EXPECT_TRUE(navigationFailed);
     753}
    621754#if WK_HAVE_C_SPI
    622755
Note: See TracChangeset for help on using the changeset viewer.