| Differences between
and this patch
- a/Source/WebKit/ChangeLog +19 lines
Lines 1-3 a/Source/WebKit/ChangeLog_sec1
1
2018-02-28  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 NOBODY (OOPS!).
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
1
2018-02-28  Youenn Fablet  <youenn@apple.com>
20
2018-02-28  Youenn Fablet  <youenn@apple.com>
2
21
3
        Add API test to validate setting of service worker and cache storage directories
22
        Add API test to validate setting of service worker and cache storage directories
- a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp -3 / +57 lines
Lines 106-111 void ServiceWorkerClientFetch::didReceiveResponse(ResourceResponse&& response) a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec1
106
106
107
        if (auto error = validateResponse(response)) {
107
        if (auto error = validateResponse(response)) {
108
            m_loader->didFail(error.value());
108
            m_loader->didFail(error.value());
109
            ASSERT(!m_loader);
109
            if (auto callback = WTFMove(m_callback))
110
            if (auto callback = WTFMove(m_callback))
110
                callback(Result::Succeeded);
111
                callback(Result::Succeeded);
111
            return;
112
            return;
Lines 141-160 void ServiceWorkerClientFetch::didReceiveResponse(ResourceResponse&& response) a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec2
141
        if (response.url().isNull())
142
        if (response.url().isNull())
142
            response.setURL(m_loader->request().url());
143
            response.setURL(m_loader->request().url());
143
144
145
        m_isCheckingResponse = true;
144
        m_loader->didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis)] {
146
        m_loader->didReceiveResponse(response, [this, protectedThis = WTFMove(protectedThis)] {
147
            m_isCheckingResponse = false;
148
            continueLoadingAfterCheckingResponse();
145
            if (auto callback = WTFMove(m_callback))
149
            if (auto callback = WTFMove(m_callback))
146
                callback(Result::Succeeded);
150
                callback(Result::Succeeded);
147
        });
151
        });
148
    });
152
    });
149
}
153
}
150
154
151
void ServiceWorkerClientFetch::didReceiveData(const IPC::DataReference& data, int64_t encodedDataLength)
155
void ServiceWorkerClientFetch::didReceiveData(const IPC::DataReference& dataReference, int64_t encodedDataLength)
152
{
156
{
153
    callOnMainThread([this, protectedThis = makeRef(*this), data = data.vector(), encodedDataLength] {
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)] {
154
        if (!m_loader)
170
        if (!m_loader)
155
            return;
171
            return;
156
172
157
        m_loader->didReceiveData(reinterpret_cast<const char*>(data.data()), data.size(), encodedDataLength, DataPayloadBytes);
173
        m_loader->didReceiveBuffer(m_buffer.releaseNonNull(), m_encodedDataLength, DataPayloadBytes);
174
        m_encodedDataLength = 0;
158
    });
175
    });
159
}
176
}
160
177
Lines 165-170 void ServiceWorkerClientFetch::didReceiveFormData(const IPC::FormDataReference&) a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec3
165
182
166
void ServiceWorkerClientFetch::didFinish()
183
void ServiceWorkerClientFetch::didFinish()
167
{
184
{
185
    m_didFinish = true;
186
187
    if (m_isCheckingResponse)
188
        return;
189
168
    callOnMainThread([this, protectedThis = makeRef(*this)] {
190
    callOnMainThread([this, protectedThis = makeRef(*this)] {
169
        if (!m_loader)
191
        if (!m_loader)
170
            return;
192
            return;
Lines 192-197 void ServiceWorkerClientFetch::didFinish() a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec4
192
214
193
void ServiceWorkerClientFetch::didFail()
215
void ServiceWorkerClientFetch::didFail()
194
{
216
{
217
    m_didFail = true;
218
219
    if (m_isCheckingResponse)
220
        return;
221
195
    callOnMainThread([this, protectedThis = makeRef(*this)] {
222
    callOnMainThread([this, protectedThis = makeRef(*this)] {
196
        if (!m_loader)
223
        if (!m_loader)
197
            return;
224
            return;
Lines 207-212 void ServiceWorkerClientFetch::didFail() a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec5
207
234
208
void ServiceWorkerClientFetch::didNotHandle()
235
void ServiceWorkerClientFetch::didNotHandle()
209
{
236
{
237
    ASSERT(!m_isCheckingResponse);
238
210
    callOnMainThread([this, protectedThis = makeRef(*this)] {
239
    callOnMainThread([this, protectedThis = makeRef(*this)] {
211
        if (!m_loader)
240
        if (!m_loader)
212
            return;
241
            return;
Lines 223-228 void ServiceWorkerClientFetch::cancel() a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.cpp_sec6
223
    if (auto callback = WTFMove(m_callback))
252
    if (auto callback = WTFMove(m_callback))
224
        callback(Result::Cancelled);
253
        callback(Result::Cancelled);
225
    m_loader = nullptr;
254
    m_loader = nullptr;
255
    m_buffer = nullptr;
256
}
257
258
void 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();
226
}
280
}
227
281
228
} // namespace WebKit
282
} // namespace WebKit
- a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h +7 lines
Lines 66-71 private: a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h_sec1
66
    void didFail();
66
    void didFail();
67
    void didNotHandle();
67
    void didNotHandle();
68
68
69
    void continueLoadingAfterCheckingResponse();
70
69
    WebServiceWorkerProvider& m_serviceWorkerProvider;
71
    WebServiceWorkerProvider& m_serviceWorkerProvider;
70
    RefPtr<WebCore::ResourceLoader> m_loader;
72
    RefPtr<WebCore::ResourceLoader> m_loader;
71
    uint64_t m_identifier { 0 };
73
    uint64_t m_identifier { 0 };
Lines 74-79 private: a/Source/WebKit/WebProcess/Storage/ServiceWorkerClientFetch.h_sec2
74
    enum class RedirectionStatus { None, Receiving, Following, Received };
76
    enum class RedirectionStatus { None, Receiving, Following, Received };
75
    RedirectionStatus m_redirectionStatus { RedirectionStatus::None };
77
    RedirectionStatus m_redirectionStatus { RedirectionStatus::None };
76
    bool m_shouldClearReferrerOnHTTPSToHTTPRedirect { true };
78
    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 };
77
};
84
};
78
85
79
} // namespace WebKit
86
} // namespace WebKit
- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm +133 lines
Lines 153-158 static String retrievedString; a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm_sec1
153
153
154
@end
154
@end
155
155
156
static bool shouldAccept = true;
157
static bool navigationComplete = false;
158
static 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
156
static const char* mainBytes = R"SWRESOURCE(
198
static const char* mainBytes = R"SWRESOURCE(
157
<script>
199
<script>
158
200
Lines 618-623 TEST(ServiceWorkers, InterceptFirstLoadAfterRestoreFromDisk) a/Tools/TestWebKitAPI/Tests/WebKitCocoa/ServiceWorkerBasic.mm_sec2
618
    done = false;
660
    done = false;
619
}
661
}
620
662
663
TEST(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
}
621
#if WK_HAVE_C_SPI
754
#if WK_HAVE_C_SPI
622
755
623
void setConfigurationInjectedBundlePath(WKWebViewConfiguration* configuration)
756
void setConfigurationInjectedBundlePath(WKWebViewConfiguration* configuration)

Return to Bug 183110