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
28#if ENABLE(SERVICE_WORKER)
29#include "ServiceWorkerClient.h"
30
31#include "MessagePort.h"
32#include "SWContextManager.h"
33#include "ScriptExecutionContext.h"
34#include "SerializedScriptValue.h"
35#include "ServiceWorkerGlobalScope.h"
36#include "ServiceWorkerThread.h"
37#include "ServiceWorkerWindowClient.h"
38
39namespace WebCore {
40
41Ref<ServiceWorkerClient> ServiceWorkerClient::getOrCreate(ServiceWorkerGlobalScope& context, ServiceWorkerClientData&& data)
42{
43 if (auto* client = context.serviceWorkerClient(data.identifier))
44 return *client;
45
46 if (data.type == ServiceWorkerClientType::Window)
47 return ServiceWorkerWindowClient::create(context, WTFMove(data));
48
49 return adoptRef(*new ServiceWorkerClient { context, WTFMove(data) });
50}
51
52ServiceWorkerClient::ServiceWorkerClient(ServiceWorkerGlobalScope& context, ServiceWorkerClientData&& data)
53 : ContextDestructionObserver(&context)
54 , m_data(WTFMove(data))
55{
56 context.addServiceWorkerClient(*this);
57}
58
59ServiceWorkerClient::~ServiceWorkerClient()
60{
61 if (auto* context = scriptExecutionContext())
62 downcast<ServiceWorkerGlobalScope>(*context).removeServiceWorkerClient(*this);
63}
64
65const URL& ServiceWorkerClient::url() const
66{
67 return m_data.url;
68}
69
70auto ServiceWorkerClient::type() const -> Type
71{
72 return m_data.type;
73}
74
75auto ServiceWorkerClient::frameType() const -> FrameType
76{
77 return m_data.frameType;
78}
79
80String ServiceWorkerClient::id() const
81{
82 return identifier().toString();
83}
84
85ExceptionOr<void> ServiceWorkerClient::postMessage(ScriptExecutionContext& context, JSC::JSValue messageValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer)
86{
87 auto* execState = context.execState();
88 ASSERT(execState);
89
90 Vector<RefPtr<MessagePort>> ports;
91 auto messageData = SerializedScriptValue::create(*execState, messageValue, WTFMove(transfer), ports, SerializationContext::WorkerPostMessage);
92 if (messageData.hasException())
93 return messageData.releaseException();
94
95 // Disentangle the port in preparation for sending it to the remote context.
96 auto portsOrException = MessagePort::disentanglePorts(WTFMove(ports));
97 if (portsOrException.hasException())
98 return portsOrException.releaseException();
99
100 MessageWithMessagePorts message = { messageData.releaseReturnValue(), portsOrException.releaseReturnValue() };
101 auto sourceIdentifier = downcast<ServiceWorkerGlobalScope>(context).thread().identifier();
102 callOnMainThread([message = WTFMove(message), destinationIdentifier = identifier(), sourceIdentifier, sourceOrigin = context.origin().isolatedCopy()] () mutable {
103 if (auto* connection = SWContextManager::singleton().connection())
104 connection->postMessageToServiceWorkerClient(destinationIdentifier, WTFMove(message), sourceIdentifier, sourceOrigin);
105 });
106
107 return { };
108}
109
110} // namespace WebCore
111
112#endif // ENABLE(SERVICE_WORKER)
113