Finish encoding/decoding support for DisplayList::SetState
[WebKit-https.git] / Source / WebCore / workers / service / context / ServiceWorkerThreadProxy.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 "ServiceWorkerThreadProxy.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "CacheStorageProvider.h"
32 #include "EventNames.h"
33 #include "FetchLoader.h"
34 #include "Frame.h"
35 #include "FrameLoader.h"
36 #include "LoaderStrategy.h"
37 #include "PlatformStrategies.h"
38 #include "ServiceWorkerClientIdentifier.h"
39 #include "Settings.h"
40 #include "WorkerGlobalScope.h"
41 #include <wtf/MainThread.h>
42 #include <wtf/RunLoop.h>
43
44 namespace WebCore {
45
46 URL static inline topOriginURL(const SecurityOrigin& origin)
47 {
48     URL url;
49     url.setProtocol(origin.protocol());
50     url.setHost(origin.host());
51     if (origin.port())
52         url.setPort(*origin.port());
53     return url;
54 }
55
56 static inline UniqueRef<Page> createPageForServiceWorker(PageConfiguration&& configuration, const ServiceWorkerContextData& data, SecurityOrigin::StorageBlockingPolicy storageBlockingPolicy)
57 {
58     auto page = makeUniqueRef<Page>(WTFMove(configuration));
59
60     auto& mainFrame = page->mainFrame();
61     mainFrame.loader().initForSynthesizedDocument({ });
62     auto document = Document::createNonRenderedPlaceholder(mainFrame, data.scriptURL);
63     document->createDOMWindow();
64
65     document->mutableSettings().setStorageBlockingPolicy(storageBlockingPolicy);
66     document->storageBlockingStateDidChange();
67
68     auto origin = data.registration.key.topOrigin().securityOrigin();
69     origin->setStorageBlockingPolicy(storageBlockingPolicy);
70
71     document->setSiteForCookies(topOriginURL(origin));
72     document->setFirstPartyForCookies(topOriginURL(origin));
73     document->setDomainForCachePartition(origin->domainForCachePartition());
74
75     if (auto policy = parseReferrerPolicy(data.referrerPolicy, ReferrerPolicySource::HTTPHeader))
76         document->setReferrerPolicy(*policy);
77
78     mainFrame.setDocument(WTFMove(document));
79     return page;
80 }
81
82 static inline IDBClient::IDBConnectionProxy* idbConnectionProxy(Document& document)
83 {
84 #if ENABLE(INDEXED_DATABASE)
85     return document.idbConnectionProxy();
86 #else
87     return nullptr;
88 #endif
89 }
90
91 static HashSet<ServiceWorkerThreadProxy*>& allServiceWorkerThreadProxies()
92 {
93     static NeverDestroyed<HashSet<ServiceWorkerThreadProxy*>> set;
94     return set;
95 }
96
97 ServiceWorkerThreadProxy::ServiceWorkerThreadProxy(PageConfiguration&& pageConfiguration, const ServiceWorkerContextData& data, String&& userAgent, CacheStorageProvider& cacheStorageProvider, SecurityOrigin::StorageBlockingPolicy storageBlockingPolicy)
98     : m_page(createPageForServiceWorker(WTFMove(pageConfiguration), data, storageBlockingPolicy))
99     , m_document(*m_page->mainFrame().document())
100     , m_serviceWorkerThread(ServiceWorkerThread::create(data, WTFMove(userAgent), *this, *this, idbConnectionProxy(m_document), m_document->socketProvider()))
101     , m_cacheStorageProvider(cacheStorageProvider)
102     , m_inspectorProxy(*this)
103 {
104     static bool addedListener;
105     if (!addedListener) {
106         platformStrategies()->loaderStrategy()->addOnlineStateChangeListener(&networkStateChanged);
107         addedListener = true;
108     }
109
110     ASSERT(!allServiceWorkerThreadProxies().contains(this));
111     allServiceWorkerThreadProxies().add(this);
112
113 #if ENABLE(REMOTE_INSPECTOR)
114     m_remoteDebuggable = makeUnique<ServiceWorkerDebuggable>(*this, data);
115     m_remoteDebuggable->setRemoteDebuggingAllowed(true);
116     m_remoteDebuggable->init();
117 #endif
118 }
119
120 ServiceWorkerThreadProxy::~ServiceWorkerThreadProxy()
121 {
122     ASSERT(allServiceWorkerThreadProxies().contains(this));
123     allServiceWorkerThreadProxies().remove(this);
124 }
125
126 bool ServiceWorkerThreadProxy::postTaskForModeToWorkerGlobalScope(ScriptExecutionContext::Task&& task, const String& mode)
127 {
128     if (m_isTerminatingOrTerminated)
129         return false;
130
131     m_serviceWorkerThread->runLoop().postTaskForMode(WTFMove(task), mode);
132     return true;
133 }
134
135 void ServiceWorkerThreadProxy::postTaskToLoader(ScriptExecutionContext::Task&& task)
136 {
137     callOnMainThread([task = WTFMove(task), this, protectedThis = makeRef(*this)] () mutable {
138         task.performTask(m_document.get());
139     });
140 }
141
142 void ServiceWorkerThreadProxy::postMessageToDebugger(const String& message)
143 {
144     RunLoop::main().dispatch([this, protectedThis = makeRef(*this), message = message.isolatedCopy()] {
145         // FIXME: Handle terminated case.
146         m_inspectorProxy.sendMessageFromWorkerToFrontend(message);
147     });
148 }
149
150 void ServiceWorkerThreadProxy::setResourceCachingDisabledByWebInspector(bool disabled)
151 {
152     postTaskToLoader([this, protectedThis = makeRef(*this), disabled] (ScriptExecutionContext&) {
153         ASSERT(isMainThread());
154         m_page->setResourceCachingDisabledByWebInspector(disabled);
155     });   
156 }
157
158 Ref<CacheStorageConnection> ServiceWorkerThreadProxy::createCacheStorageConnection()
159 {
160     ASSERT(isMainThread());
161     if (!m_cacheStorageConnection)
162         m_cacheStorageConnection = m_cacheStorageProvider.createCacheStorageConnection();
163     return *m_cacheStorageConnection;
164 }
165
166 std::unique_ptr<FetchLoader> ServiceWorkerThreadProxy::createBlobLoader(FetchLoaderClient& client, const URL& blobURL)
167 {
168     auto loader = makeUnique<FetchLoader>(client, nullptr);
169     loader->startLoadingBlobURL(m_document, blobURL);
170     if (!loader->isStarted())
171         return nullptr;
172     return loader;
173 }
174
175 void ServiceWorkerThreadProxy::networkStateChanged(bool isOnLine)
176 {
177     for (auto* proxy : allServiceWorkerThreadProxies())
178         proxy->notifyNetworkStateChange(isOnLine);
179 }
180
181 void ServiceWorkerThreadProxy::notifyNetworkStateChange(bool isOnline)
182 {
183     if (m_isTerminatingOrTerminated)
184         return;
185
186     postTaskForModeToWorkerGlobalScope([isOnline] (ScriptExecutionContext& context) {
187         auto& globalScope = downcast<WorkerGlobalScope>(context);
188         globalScope.setIsOnline(isOnline);
189         globalScope.dispatchEvent(Event::create(isOnline ? eventNames().onlineEvent : eventNames().offlineEvent, Event::CanBubble::No, Event::IsCancelable::No));
190     }, WorkerRunLoop::defaultMode());
191 }
192
193 void ServiceWorkerThreadProxy::startFetch(SWServerConnectionIdentifier connectionIdentifier, FetchIdentifier fetchIdentifier, Ref<ServiceWorkerFetch::Client>&& client, Optional<ServiceWorkerClientIdentifier>&& clientId, ResourceRequest&& request, String&& referrer, FetchOptions&& options)
194 {
195     auto key = std::make_pair(connectionIdentifier, fetchIdentifier);
196
197     ASSERT(!m_ongoingFetchTasks.contains(key));
198     m_ongoingFetchTasks.add(key, client.copyRef());
199     thread().postFetchTask(WTFMove(client), WTFMove(clientId), WTFMove(request), WTFMove(referrer), WTFMove(options));
200 }
201
202 void ServiceWorkerThreadProxy::cancelFetch(SWServerConnectionIdentifier connectionIdentifier, FetchIdentifier fetchIdentifier)
203 {
204     auto client = m_ongoingFetchTasks.take(std::make_pair(connectionIdentifier, fetchIdentifier));
205     if (!client)
206         return;
207
208     postTaskForModeToWorkerGlobalScope([client = WTFMove(client.value())] (ScriptExecutionContext&) {
209         client->cancel();
210     }, WorkerRunLoop::defaultMode());
211 }
212
213 void ServiceWorkerThreadProxy::continueDidReceiveFetchResponse(SWServerConnectionIdentifier connectionIdentifier, FetchIdentifier fetchIdentifier)
214 {
215     auto client = m_ongoingFetchTasks.get(std::make_pair(connectionIdentifier, fetchIdentifier));
216     if (!client)
217         return;
218
219     postTaskForModeToWorkerGlobalScope([client = makeRef(*client)] (ScriptExecutionContext&) {
220         client->continueDidReceiveResponse();
221     }, WorkerRunLoop::defaultMode());
222 }
223
224 void ServiceWorkerThreadProxy::removeFetch(SWServerConnectionIdentifier connectionIdentifier, FetchIdentifier fetchIdentifier)
225 {
226     m_ongoingFetchTasks.remove(std::make_pair(connectionIdentifier, fetchIdentifier));
227 }
228
229 } // namespace WebCore
230
231 #endif // ENABLE(SERVICE_WORKER)