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 "WebSWClientConnection.h" |
28 | |
29 | #if ENABLE(SERVICE_WORKER) |
30 | |
31 | #include "DataReference.h" |
32 | #include "FormDataReference.h" |
33 | #include "Logging.h" |
34 | #include "NetworkConnectionToWebProcessMessages.h" |
35 | #include "ServiceWorkerClientFetch.h" |
36 | #include "WebCoreArgumentCoders.h" |
37 | #include "WebProcess.h" |
38 | #include "WebProcessPoolMessages.h" |
39 | #include "WebSWOriginTable.h" |
40 | #include "WebSWServerConnectionMessages.h" |
41 | #include <WebCore/Document.h> |
42 | #include <WebCore/SecurityOrigin.h> |
43 | #include <WebCore/SerializedScriptValue.h> |
44 | #include <WebCore/ServiceWorkerClientData.h> |
45 | #include <WebCore/ServiceWorkerFetchResult.h> |
46 | #include <WebCore/ServiceWorkerJobData.h> |
47 | #include <WebCore/ServiceWorkerRegistrationData.h> |
48 | #include <WebCore/ServiceWorkerRegistrationKey.h> |
49 | |
50 | namespace WebKit { |
51 | using namespace PAL; |
52 | using namespace WebCore; |
53 | |
54 | WebSWClientConnection::WebSWClientConnection(IPC::Connection& connection, SessionID sessionID) |
55 | : m_sessionID(sessionID) |
56 | , m_connection(connection) |
57 | , m_swOriginTable(makeUniqueRef<WebSWOriginTable>()) |
58 | { |
59 | ASSERT(sessionID.isValid()); |
60 | bool result = sendSync(Messages::NetworkConnectionToWebProcess::EstablishSWServerConnection(sessionID), Messages::NetworkConnectionToWebProcess::EstablishSWServerConnection::Reply(m_identifier)); |
61 | |
62 | ASSERT_UNUSED(result, result); |
63 | updateThrottleState(); |
64 | } |
65 | |
66 | WebSWClientConnection::~WebSWClientConnection() |
67 | { |
68 | } |
69 | |
70 | void WebSWClientConnection::scheduleJobInServer(const ServiceWorkerJobData& jobData) |
71 | { |
72 | send(Messages::WebSWServerConnection::ScheduleJobInServer(jobData)); |
73 | } |
74 | |
75 | void WebSWClientConnection::finishFetchingScriptInServer(const ServiceWorkerFetchResult& result) |
76 | { |
77 | send(Messages::WebSWServerConnection::FinishFetchingScriptInServer(result)); |
78 | } |
79 | |
80 | void WebSWClientConnection::addServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier identifier) |
81 | { |
82 | send(Messages::WebSWServerConnection::AddServiceWorkerRegistrationInServer(identifier)); |
83 | } |
84 | |
85 | void WebSWClientConnection::removeServiceWorkerRegistrationInServer(ServiceWorkerRegistrationIdentifier identifier) |
86 | { |
87 | send(Messages::WebSWServerConnection::RemoveServiceWorkerRegistrationInServer(identifier)); |
88 | } |
89 | |
90 | void WebSWClientConnection::postMessageToServiceWorker(ServiceWorkerIdentifier destinationIdentifier, MessageWithMessagePorts&& message, const ServiceWorkerOrClientIdentifier& sourceIdentifier) |
91 | { |
92 | // FIXME: Temporarily pipe the SW postMessage messages via the UIProcess since this is where the MessagePort registry lives |
93 | // and this avoids races. |
94 | WebProcess::singleton().send(Messages::WebProcessPool::PostMessageToServiceWorker(destinationIdentifier, WTFMove(message), sourceIdentifier, serverConnectionIdentifier()), 0); |
95 | } |
96 | |
97 | void WebSWClientConnection::registerServiceWorkerClient(const SecurityOrigin& topOrigin, const WebCore::ServiceWorkerClientData& data, const Optional<WebCore::ServiceWorkerRegistrationIdentifier>& controllingServiceWorkerRegistrationIdentifier, const String& userAgent) |
98 | { |
99 | send(Messages::WebSWServerConnection::RegisterServiceWorkerClient { topOrigin.data(), data, controllingServiceWorkerRegistrationIdentifier, userAgent }); |
100 | } |
101 | |
102 | void WebSWClientConnection::unregisterServiceWorkerClient(DocumentIdentifier contextIdentifier) |
103 | { |
104 | send(Messages::WebSWServerConnection::UnregisterServiceWorkerClient { ServiceWorkerClientIdentifier { serverConnectionIdentifier(), contextIdentifier } }); |
105 | } |
106 | |
107 | void WebSWClientConnection::didResolveRegistrationPromise(const ServiceWorkerRegistrationKey& key) |
108 | { |
109 | send(Messages::WebSWServerConnection::DidResolveRegistrationPromise(key)); |
110 | } |
111 | |
112 | bool WebSWClientConnection::mayHaveServiceWorkerRegisteredForOrigin(const SecurityOriginData& origin) const |
113 | { |
114 | if (!m_swOriginTable->isImported()) |
115 | return true; |
116 | |
117 | return m_swOriginTable->contains(origin); |
118 | } |
119 | |
120 | void WebSWClientConnection::setSWOriginTableSharedMemory(const SharedMemory::Handle& handle) |
121 | { |
122 | m_swOriginTable->setSharedMemory(handle); |
123 | } |
124 | |
125 | void WebSWClientConnection::setSWOriginTableIsImported() |
126 | { |
127 | m_swOriginTable->setIsImported(); |
128 | while (!m_tasksPendingOriginImport.isEmpty()) |
129 | m_tasksPendingOriginImport.takeFirst()(); |
130 | } |
131 | |
132 | void WebSWClientConnection::didMatchRegistration(uint64_t matchingRequest, Optional<ServiceWorkerRegistrationData>&& result) |
133 | { |
134 | ASSERT(isMainThread()); |
135 | |
136 | if (auto completionHandler = m_ongoingMatchRegistrationTasks.take(matchingRequest)) |
137 | completionHandler(WTFMove(result)); |
138 | } |
139 | |
140 | void WebSWClientConnection::didGetRegistrations(uint64_t matchingRequest, Vector<ServiceWorkerRegistrationData>&& registrations) |
141 | { |
142 | ASSERT(isMainThread()); |
143 | |
144 | if (auto completionHandler = m_ongoingGetRegistrationsTasks.take(matchingRequest)) |
145 | completionHandler(WTFMove(registrations)); |
146 | } |
147 | |
148 | void WebSWClientConnection::matchRegistration(SecurityOriginData&& topOrigin, const URL& clientURL, RegistrationCallback&& callback) |
149 | { |
150 | ASSERT(isMainThread()); |
151 | |
152 | if (!mayHaveServiceWorkerRegisteredForOrigin(topOrigin)) { |
153 | callback(WTF::nullopt); |
154 | return; |
155 | } |
156 | |
157 | runOrDelayTaskForImport([this, callback = WTFMove(callback), topOrigin = WTFMove(topOrigin), clientURL]() mutable { |
158 | uint64_t callbackID = ++m_previousCallbackIdentifier; |
159 | m_ongoingMatchRegistrationTasks.add(callbackID, WTFMove(callback)); |
160 | send(Messages::WebSWServerConnection::MatchRegistration(callbackID, topOrigin, clientURL)); |
161 | }); |
162 | } |
163 | |
164 | void WebSWClientConnection::runOrDelayTaskForImport(WTF::Function<void()>&& task) |
165 | { |
166 | if (m_swOriginTable->isImported()) |
167 | task(); |
168 | else |
169 | m_tasksPendingOriginImport.append(WTFMove(task)); |
170 | } |
171 | |
172 | void WebSWClientConnection::whenRegistrationReady(const SecurityOrigin& topOrigin, const URL& clientURL, WhenRegistrationReadyCallback&& callback) |
173 | { |
174 | uint64_t callbackID = ++m_previousCallbackIdentifier; |
175 | m_ongoingRegistrationReadyTasks.add(callbackID, WTFMove(callback)); |
176 | send(Messages::WebSWServerConnection::WhenRegistrationReady(callbackID, topOrigin.data(), clientURL)); |
177 | } |
178 | |
179 | void WebSWClientConnection::registrationReady(uint64_t callbackID, WebCore::ServiceWorkerRegistrationData&& registrationData) |
180 | { |
181 | ASSERT(registrationData.activeWorker); |
182 | if (auto callback = m_ongoingRegistrationReadyTasks.take(callbackID)) |
183 | callback(WTFMove(registrationData)); |
184 | } |
185 | |
186 | void WebSWClientConnection::getRegistrations(SecurityOriginData&& topOrigin, const URL& clientURL, GetRegistrationsCallback&& callback) |
187 | { |
188 | ASSERT(isMainThread()); |
189 | |
190 | if (!mayHaveServiceWorkerRegisteredForOrigin(topOrigin)) { |
191 | callback({ }); |
192 | return; |
193 | } |
194 | |
195 | runOrDelayTaskForImport([this, callback = WTFMove(callback), topOrigin = WTFMove(topOrigin), clientURL]() mutable { |
196 | uint64_t callbackID = ++m_previousCallbackIdentifier; |
197 | m_ongoingGetRegistrationsTasks.add(callbackID, WTFMove(callback)); |
198 | send(Messages::WebSWServerConnection::GetRegistrations(callbackID, topOrigin, clientURL)); |
199 | }); |
200 | } |
201 | |
202 | void WebSWClientConnection::startFetch(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier, const ResourceRequest& request, const FetchOptions& options, const String& referrer) |
203 | { |
204 | send(Messages::WebSWServerConnection::StartFetch { serviceWorkerRegistrationIdentifier, fetchIdentifier, request, options, IPC::FormDataReference { request.httpBody() }, referrer }); |
205 | } |
206 | |
207 | void WebSWClientConnection::cancelFetch(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier) |
208 | { |
209 | send(Messages::WebSWServerConnection::CancelFetch { serviceWorkerRegistrationIdentifier, fetchIdentifier }); |
210 | } |
211 | |
212 | void WebSWClientConnection::continueDidReceiveFetchResponse(FetchIdentifier fetchIdentifier, ServiceWorkerRegistrationIdentifier serviceWorkerRegistrationIdentifier) |
213 | { |
214 | send(Messages::WebSWServerConnection::ContinueDidReceiveFetchResponse { serviceWorkerRegistrationIdentifier, fetchIdentifier }); |
215 | } |
216 | |
217 | void WebSWClientConnection::connectionToServerLost() |
218 | { |
219 | auto registrationTasks = WTFMove(m_ongoingMatchRegistrationTasks); |
220 | for (auto& callback : registrationTasks.values()) |
221 | callback(WTF::nullopt); |
222 | |
223 | auto getRegistrationTasks = WTFMove(m_ongoingGetRegistrationsTasks); |
224 | for (auto& callback : getRegistrationTasks.values()) |
225 | callback({ }); |
226 | |
227 | clearPendingJobs(); |
228 | } |
229 | |
230 | void WebSWClientConnection::syncTerminateWorker(ServiceWorkerIdentifier identifier) |
231 | { |
232 | sendSync(Messages::WebSWServerConnection::SyncTerminateWorkerFromClient(identifier), Messages::WebSWServerConnection::SyncTerminateWorkerFromClient::Reply()); |
233 | } |
234 | |
235 | void WebSWClientConnection::updateThrottleState() |
236 | { |
237 | m_isThrottleable = WebProcess::singleton().areAllPagesThrottleable(); |
238 | send(Messages::WebSWServerConnection::SetThrottleState { m_isThrottleable }); |
239 | } |
240 | |
241 | } // namespace WebKit |
242 | |
243 | #endif // ENABLE(SERVICE_WORKER) |
244 | |