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 "SWServerToContextConnection.h"
28
29#if ENABLE(SERVICE_WORKER)
30
31#include "SWServer.h"
32#include "SWServerWorker.h"
33#include <wtf/CompletionHandler.h>
34#include <wtf/NeverDestroyed.h>
35
36namespace WebCore {
37
38static SWServerToContextConnectionIdentifier generateServerToContextConnectionIdentifier()
39{
40 return SWServerToContextConnectionIdentifier::generate();
41}
42
43static HashMap<RegistrableDomain, SWServerToContextConnection*>& allConnectionsByRegistrableDomain()
44{
45 static NeverDestroyed<HashMap<RegistrableDomain, SWServerToContextConnection*>> connectionsByOrigin;
46 return connectionsByOrigin;
47}
48
49SWServerToContextConnection::SWServerToContextConnection(const RegistrableDomain& registrableDomain)
50 : m_identifier(generateServerToContextConnectionIdentifier())
51 , m_registrableDomain(registrableDomain)
52{
53 auto result = allConnectionsByRegistrableDomain().add(m_registrableDomain, this);
54 ASSERT_UNUSED(result, result.isNewEntry);
55}
56
57SWServerToContextConnection::~SWServerToContextConnection()
58{
59 auto result = allConnectionsByRegistrableDomain().remove(m_registrableDomain);
60 ASSERT_UNUSED(result, result);
61}
62
63SWServerToContextConnection* SWServerToContextConnection::connectionForRegistrableDomain(const RegistrableDomain& registrableDomain)
64{
65 return allConnectionsByRegistrableDomain().get(registrableDomain);
66}
67
68void SWServerToContextConnection::scriptContextFailedToStart(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, const String& message)
69{
70 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
71 worker->scriptContextFailedToStart(jobDataIdentifier, message);
72}
73
74void SWServerToContextConnection::scriptContextStarted(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
75{
76 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
77 worker->scriptContextStarted(jobDataIdentifier);
78}
79
80void SWServerToContextConnection::didFinishInstall(const Optional<ServiceWorkerJobDataIdentifier>& jobDataIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, bool wasSuccessful)
81{
82 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
83 worker->didFinishInstall(jobDataIdentifier, wasSuccessful);
84}
85
86void SWServerToContextConnection::didFinishActivation(ServiceWorkerIdentifier serviceWorkerIdentifier)
87{
88 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
89 worker->didFinishActivation();
90}
91
92void SWServerToContextConnection::setServiceWorkerHasPendingEvents(ServiceWorkerIdentifier serviceWorkerIdentifier, bool hasPendingEvents)
93{
94 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
95 worker->setHasPendingEvents(hasPendingEvents);
96}
97
98void SWServerToContextConnection::workerTerminated(ServiceWorkerIdentifier serviceWorkerIdentifier)
99{
100 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
101 worker->contextTerminated();
102}
103
104void SWServerToContextConnection::findClientByIdentifier(uint64_t requestIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, ServiceWorkerClientIdentifier clientId)
105{
106 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
107 worker->contextConnection()->findClientByIdentifierCompleted(requestIdentifier, worker->findClientByIdentifier(clientId), false);
108}
109
110void SWServerToContextConnection::matchAll(uint64_t requestIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier, const ServiceWorkerClientQueryOptions& options)
111{
112 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier)) {
113 worker->matchAll(options, [&] (auto&& data) {
114 worker->contextConnection()->matchAllCompleted(requestIdentifier, data);
115 });
116 }
117}
118
119void SWServerToContextConnection::claim(uint64_t requestIdentifier, ServiceWorkerIdentifier serviceWorkerIdentifier)
120{
121 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier)) {
122 worker->claim();
123 worker->contextConnection()->claimCompleted(requestIdentifier);
124 }
125}
126
127void SWServerToContextConnection::skipWaiting(ServiceWorkerIdentifier serviceWorkerIdentifier, uint64_t callbackID)
128{
129 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
130 worker->skipWaiting();
131
132 didFinishSkipWaiting(callbackID);
133}
134
135void SWServerToContextConnection::setScriptResource(ServiceWorkerIdentifier serviceWorkerIdentifier, URL&& scriptURL, String&& script, URL&& responseURL, String&& mimeType)
136{
137 if (auto* worker = SWServerWorker::existingWorkerForIdentifier(serviceWorkerIdentifier))
138 worker->setScriptResource(WTFMove(scriptURL), ServiceWorkerContextData::ImportedScript { WTFMove(script), WTFMove(responseURL), WTFMove(mimeType) });
139}
140
141} // namespace WebCore
142
143#endif // ENABLE(SERVICE_WORKER)
144