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 "WebSWServerToContextConnection.h"
28
29#if ENABLE(SERVICE_WORKER)
30
31#include "FormDataReference.h"
32#include "NetworkProcess.h"
33#include "ServiceWorkerFetchTask.h"
34#include "ServiceWorkerFetchTaskMessages.h"
35#include "WebCoreArgumentCoders.h"
36#include "WebSWContextManagerConnectionMessages.h"
37#include <WebCore/ServiceWorkerContextData.h>
38
39namespace WebKit {
40using namespace WebCore;
41
42WebSWServerToContextConnection::WebSWServerToContextConnection(NetworkProcess& networkProcess, const RegistrableDomain& registrableDomain, Ref<IPC::Connection>&& connection)
43 : SWServerToContextConnection(registrableDomain)
44 , m_ipcConnection(WTFMove(connection))
45 , m_networkProcess(networkProcess)
46{
47}
48
49WebSWServerToContextConnection::~WebSWServerToContextConnection() = default;
50
51IPC::Connection* WebSWServerToContextConnection::messageSenderConnection() const
52{
53 return m_ipcConnection.ptr();
54}
55
56uint64_t WebSWServerToContextConnection::messageSenderDestinationID() const
57{
58 return 0;
59}
60
61void WebSWServerToContextConnection::connectionClosed()
62{
63 auto fetches = WTFMove(m_ongoingFetches);
64 for (auto& fetch : fetches.values())
65 fetch->fail(ResourceError { errorDomainWebKitInternal, 0, { }, "Service Worker context closed"_s });
66}
67
68void WebSWServerToContextConnection::installServiceWorkerContext(const ServiceWorkerContextData& data, PAL::SessionID sessionID, const String& userAgent)
69{
70 send(Messages::WebSWContextManagerConnection::InstallServiceWorker { data, sessionID, userAgent });
71}
72
73void WebSWServerToContextConnection::fireInstallEvent(ServiceWorkerIdentifier serviceWorkerIdentifier)
74{
75 send(Messages::WebSWContextManagerConnection::FireInstallEvent(serviceWorkerIdentifier));
76}
77
78void WebSWServerToContextConnection::fireActivateEvent(ServiceWorkerIdentifier serviceWorkerIdentifier)
79{
80 send(Messages::WebSWContextManagerConnection::FireActivateEvent(serviceWorkerIdentifier));
81}
82
83void WebSWServerToContextConnection::terminateWorker(ServiceWorkerIdentifier serviceWorkerIdentifier)
84{
85 send(Messages::WebSWContextManagerConnection::TerminateWorker(serviceWorkerIdentifier));
86}
87
88void WebSWServerToContextConnection::syncTerminateWorker(ServiceWorkerIdentifier serviceWorkerIdentifier)
89{
90 sendSync(Messages::WebSWContextManagerConnection::SyncTerminateWorker(serviceWorkerIdentifier), Messages::WebSWContextManagerConnection::SyncTerminateWorker::Reply());
91}
92
93void WebSWServerToContextConnection::findClientByIdentifierCompleted(uint64_t requestIdentifier, const Optional<ServiceWorkerClientData>& data, bool hasSecurityError)
94{
95 send(Messages::WebSWContextManagerConnection::FindClientByIdentifierCompleted { requestIdentifier, data, hasSecurityError });
96}
97
98void WebSWServerToContextConnection::matchAllCompleted(uint64_t requestIdentifier, const Vector<ServiceWorkerClientData>& clientsData)
99{
100 send(Messages::WebSWContextManagerConnection::MatchAllCompleted { requestIdentifier, clientsData });
101}
102
103void WebSWServerToContextConnection::claimCompleted(uint64_t requestIdentifier)
104{
105 send(Messages::WebSWContextManagerConnection::ClaimCompleted { requestIdentifier });
106}
107
108void WebSWServerToContextConnection::didFinishSkipWaiting(uint64_t callbackID)
109{
110 send(Messages::WebSWContextManagerConnection::DidFinishSkipWaiting { callbackID });
111}
112
113void WebSWServerToContextConnection::connectionMayNoLongerBeNeeded()
114{
115 m_networkProcess->swContextConnectionMayNoLongerBeNeeded(*this);
116}
117
118void WebSWServerToContextConnection::setThrottleState(bool isThrottleable)
119{
120 m_isThrottleable = isThrottleable;
121 send(Messages::WebSWContextManagerConnection::SetThrottleState { isThrottleable });
122}
123
124void WebSWServerToContextConnection::terminate()
125{
126 send(Messages::WebSWContextManagerConnection::TerminateProcess());
127}
128
129void WebSWServerToContextConnection::startFetch(PAL::SessionID sessionID, Ref<IPC::Connection>&& contentConnection, WebCore::SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, const ResourceRequest& request, const FetchOptions& options, const IPC::FormDataReference& data, const String& referrer)
130{
131 auto fetchIdentifier = FetchIdentifier::generate();
132
133 m_ongoingFetches.add(fetchIdentifier, ServiceWorkerFetchTask::create(sessionID, WTFMove(contentConnection), serverConnectionIdentifier, contentFetchIdentifier));
134
135 ASSERT(!m_ongoingFetchIdentifiers.contains({serverConnectionIdentifier, contentFetchIdentifier}));
136 m_ongoingFetchIdentifiers.add({serverConnectionIdentifier, contentFetchIdentifier}, fetchIdentifier);
137
138 send(Messages::WebSWContextManagerConnection::StartFetch { serverConnectionIdentifier, serviceWorkerIdentifier, fetchIdentifier, request, options, data, referrer });
139}
140
141void WebSWServerToContextConnection::cancelFetch(WebCore::SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
142{
143 auto iterator = m_ongoingFetchIdentifiers.find({ serverConnectionIdentifier, contentFetchIdentifier });
144 if (iterator == m_ongoingFetchIdentifiers.end())
145 return;
146
147 send(Messages::WebSWContextManagerConnection::CancelFetch { serverConnectionIdentifier, serviceWorkerIdentifier, iterator->value });
148
149 m_ongoingFetches.remove(iterator->value);
150 m_ongoingFetchIdentifiers.remove(iterator);
151}
152
153void WebSWServerToContextConnection::continueDidReceiveFetchResponse(WebCore::SWServerConnectionIdentifier serverConnectionIdentifier, FetchIdentifier contentFetchIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
154{
155 auto iterator = m_ongoingFetchIdentifiers.find({ serverConnectionIdentifier, contentFetchIdentifier });
156 if (iterator == m_ongoingFetchIdentifiers.end())
157 return;
158
159 send(Messages::WebSWContextManagerConnection::ContinueDidReceiveFetchResponse { serverConnectionIdentifier, serviceWorkerIdentifier, iterator->value });
160}
161
162void WebSWServerToContextConnection::didReceiveFetchTaskMessage(IPC::Connection& connection, IPC::Decoder& decoder)
163{
164 auto iterator = m_ongoingFetches.find(makeObjectIdentifier<FetchIdentifierType>(decoder.destinationID()));
165 if (iterator == m_ongoingFetches.end())
166 return;
167
168 bool shouldRemove = decoder.messageName() == Messages::ServiceWorkerFetchTask::DidFail::name()
169 || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidNotHandle::name()
170 || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidFinish::name()
171 || decoder.messageName() == Messages::ServiceWorkerFetchTask::DidReceiveRedirectResponse::name();
172
173 iterator->value->didReceiveMessage(connection, decoder);
174
175 if (shouldRemove) {
176 ASSERT(m_ongoingFetchIdentifiers.contains(iterator->value->identifier()));
177 m_ongoingFetchIdentifiers.remove(iterator->value->identifier());
178 m_ongoingFetches.remove(iterator);
179 }
180}
181
182} // namespace WebKit
183
184#endif // ENABLE(SERVICE_WORKER)
185