94d634d612bdc43c95c2f6a3feecc9d07d07380f
[WebKit-https.git] / Source / WebKit / WebProcess / Storage / ServiceWorkerContextManager.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 "ServiceWorkerContextManager.h"
28
29 #if ENABLE(SERVICE_WORKER)
30
31 #include "DataReference.h"
32 #include "Logging.h"
33 #include "StorageProcessMessages.h"
34 #include "WebCacheStorageProvider.h"
35 #include "WebCoreArgumentCoders.h"
36 #include "WebDocumentLoader.h"
37 #include "WebPreferencesKeys.h"
38 #include "WebPreferencesStore.h"
39 #include "WebProcess.h"
40 #include "WebServiceWorkerFetchTaskClient.h"
41 #include "WebSocketProvider.h"
42 #include <WebCore/EditorClient.h>
43 #include <WebCore/EmptyClients.h>
44 #include <WebCore/EmptyFrameLoaderClient.h>
45 #include <WebCore/LibWebRTCProvider.h>
46 #include <WebCore/MessagePortChannel.h>
47 #include <WebCore/PageConfiguration.h>
48 #include <WebCore/RuntimeEnabledFeatures.h>
49 #include <WebCore/SerializedScriptValue.h>
50 #include <pal/SessionID.h>
51
52 #if USE(QUICK_LOOK)
53 #include <WebCore/PreviewLoaderClient.h>
54 #endif
55
56 using namespace PAL;
57 using namespace WebCore;
58
59 namespace WebKit {
60
61 class ServiceWorkerFrameLoaderClient final : public EmptyFrameLoaderClient {
62 public:
63     ServiceWorkerFrameLoaderClient(PAL::SessionID sessionID, uint64_t pageID, uint64_t frameID)
64         : m_sessionID(sessionID)
65         , m_pageID(pageID)
66         , m_frameID(frameID)
67     {
68     }
69
70 private:
71     Ref<DocumentLoader> createDocumentLoader(const ResourceRequest& request, const SubstituteData& substituteData) final
72     {
73         return WebDocumentLoader::create(request, substituteData);
74     }
75
76     PAL::SessionID sessionID() const final { return m_sessionID; }
77     uint64_t pageID() const final { return m_pageID; }
78     uint64_t frameID() const final { return m_frameID; }
79
80     PAL::SessionID m_sessionID;
81     uint64_t m_pageID { 0 };
82     uint64_t m_frameID { 0 };
83 };
84
85 ServiceWorkerContextManager::ServiceWorkerContextManager(Ref<IPC::Connection>&& connection, uint64_t pageID, const WebPreferencesStore& store)
86     : m_connectionToStorageProcess(WTFMove(connection))
87     , m_pageID(pageID)
88 {
89     updatePreferences(store);
90 }
91
92 void ServiceWorkerContextManager::updatePreferences(const WebPreferencesStore& store)
93 {
94     RuntimeEnabledFeatures::sharedFeatures().setCacheAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::cacheAPIEnabledKey()));
95     RuntimeEnabledFeatures::sharedFeatures().setFetchAPIEnabled(store.getBoolValueForKey(WebPreferencesKey::fetchAPIEnabledKey()));
96 }
97
98 void ServiceWorkerContextManager::startServiceWorker(uint64_t serverConnectionIdentifier, const ServiceWorkerContextData& data)
99 {
100     // FIXME: Provide a sensical session ID.
101     auto sessionID = PAL::SessionID::defaultSessionID();
102
103     PageConfiguration pageConfiguration {
104         createEmptyEditorClient(),
105         WebSocketProvider::create(),
106         WebCore::LibWebRTCProvider::create(),
107         WebProcess::singleton().cacheStorageProvider()
108     };
109     fillWithEmptyClients(pageConfiguration);
110     auto frameLoaderClient = std::make_unique<ServiceWorkerFrameLoaderClient>(sessionID, m_pageID, ++m_previousServiceWorkerID);
111     pageConfiguration.loaderClientForMainFrame = frameLoaderClient.release();
112
113     auto serviceWorkerThreadProxy = ServiceWorkerThreadProxy::create(WTFMove(pageConfiguration), serverConnectionIdentifier, data, sessionID, WebProcess::singleton().cacheStorageProvider());
114     auto serviceWorkerIdentifier = serviceWorkerThreadProxy->identifier();
115     auto result = m_workerMap.add(serviceWorkerIdentifier, WTFMove(serviceWorkerThreadProxy));
116     ASSERT_UNUSED(result, result.isNewEntry);
117
118     LOG(ServiceWorker, "Context process PID: %i started worker thread %s\n", getpid(), data.workerID.utf8().data());
119
120     m_connectionToStorageProcess->send(Messages::StorageProcess::ServiceWorkerContextStarted(serverConnectionIdentifier, data.registrationKey, serviceWorkerIdentifier, data.workerID), 0);
121 }
122
123 void ServiceWorkerContextManager::startFetch(uint64_t serverConnectionIdentifier, uint64_t fetchIdentifier, uint64_t serviceWorkerIdentifier, ResourceRequest&& request, FetchOptions&& options)
124 {
125     auto serviceWorkerThreadProxy = serviceWorkerIdentifier ? m_workerMap.get(serviceWorkerIdentifier) : nullptr;
126     if (!serviceWorkerThreadProxy) {
127         m_connectionToStorageProcess->send(Messages::StorageProcess::DidNotHandleFetch(serverConnectionIdentifier, fetchIdentifier), 0);
128         return;
129     }
130
131     auto client = WebServiceWorkerFetchTaskClient::create(m_connectionToStorageProcess.copyRef(), serverConnectionIdentifier, fetchIdentifier);
132     serviceWorkerThreadProxy->thread().postFetchTask(WTFMove(client), WTFMove(request), WTFMove(options));
133 }
134
135 void ServiceWorkerContextManager::postMessageToServiceWorkerGlobalScope(uint64_t serverConnectionIdentifier, uint64_t serviceWorkerIdentifier, const IPC::DataReference& message, const String& sourceOrigin)
136 {
137     auto* serviceWorker = m_workerMap.get(serviceWorkerIdentifier);
138     if (!serviceWorker)
139         return;
140
141     // FIXME: We should pass valid MessagePortChannels.
142     serviceWorker->thread().postMessageToServiceWorkerGlobalScope(SerializedScriptValue::adopt(message.vector()), nullptr, sourceOrigin);
143 }
144
145 } // namespace WebCore
146
147 #endif // ENABLE(SERVICE_WORKER)