Source/WebCore:
[WebKit-https.git] / Source / WebCore / workers / service / context / ServiceWorkerFetch.cpp
1 /*
2  * Copyright (C) 2017 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "ServiceWorkerFetch.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "EventNames.h"
32 #include "FetchEvent.h"
33 #include "FetchRequest.h"
34 #include "FetchResponse.h"
35 #include "ResourceRequest.h"
36 #include "WorkerGlobalScope.h"
37
38 namespace WebCore {
39
40 namespace ServiceWorkerFetch {
41
42 static void processResponse(Ref<Client>&& client, FetchResponse* response)
43 {
44     if (!response) {
45         client->didFail();
46         return;
47     }
48     auto protectedResponse = makeRef(*response);
49
50     client->didReceiveResponse(response->resourceResponse());
51
52     if (response->hasReadableStreamBody()) {
53         // FIXME: We should send the body as chunks.
54         response->consumeBodyFromReadableStream([client = WTFMove(client)] (ExceptionOr<RefPtr<SharedBuffer>>&& result) mutable {
55             if (result.hasException()) {
56                 client->didFail();
57                 return;
58             }
59             client->didReceiveData(result.releaseReturnValue().releaseNonNull());
60             client->didFinish();
61         });
62         return;
63     }
64     if (response->isLoading()) {
65         // FIXME: We should send the body as chunks.
66         response->consumeBodyWhenLoaded([client = WTFMove(client)] (ExceptionOr<RefPtr<SharedBuffer>>&& result) mutable {
67             if (result.hasException()) {
68                 client->didFail();
69                 return;
70             }
71             client->didReceiveData(result.releaseReturnValue().releaseNonNull());
72             client->didFail();
73         });
74         return;
75     }
76
77     auto body = response->consumeBody();
78     WTF::switchOn(body, [] (Ref<FormData>&) {
79         // FIXME: Support FormData response bodies.
80     }, [&] (Ref<SharedBuffer>& buffer) {
81         client->didReceiveData(WTFMove(buffer));
82     }, [] (std::nullptr_t&) {
83     });
84
85     client->didFinish();
86 }
87
88 void dispatchFetchEvent(Ref<Client>&& client, WorkerGlobalScope& globalScope, ResourceRequest&& request, FetchOptions&& options)
89 {
90     ASSERT(globalScope.isServiceWorkerGlobalScope());
91
92     // FIXME: Set request body and referrer.
93     auto requestHeaders = FetchHeaders::create(FetchHeaders::Guard::Immutable, HTTPHeaderMap { request.httpHeaderFields() });
94     auto fetchRequest = FetchRequest::create(globalScope, std::nullopt, WTFMove(requestHeaders),  WTFMove(request), WTFMove(options), { });
95
96     // FIXME: Initialize other FetchEvent::Init fields.
97     FetchEvent::Init init;
98     init.request = WTFMove(fetchRequest);
99     auto event = FetchEvent::create(eventNames().fetchEvent, WTFMove(init), Event::IsTrusted::Yes);
100
101     event->onResponse([client = WTFMove(client)] (FetchResponse* response) mutable {
102         processResponse(WTFMove(client), response);
103     });
104
105     globalScope.dispatchEvent(event);
106 }
107
108 } // namespace ServiceWorkerFetch
109
110 } // namespace WebCore
111
112 #endif // ENABLE(SERVICE_WORKER)