Make it possible for apps that use both WK1 and WK2 to use MessagePorts.
[WebKit-https.git] / Source / WebCore / dom / messageports / MessagePortChannelRegistry.cpp
1 /*
2  * Copyright (C) 2018 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 "MessagePortChannelRegistry.h"
28
29 #include <wtf/MainThread.h>
30
31 namespace WebCore {
32
33 MessagePortChannelRegistry::MessagePortChannelRegistry(MessagePortChannelProvider& provider)
34     : m_provider(provider)
35 {
36 }
37
38 MessagePortChannelRegistry::~MessagePortChannelRegistry()
39 {
40     ASSERT(m_openChannels.isEmpty());
41 }
42
43 void MessagePortChannelRegistry::didCreateMessagePortChannel(const MessagePortIdentifier& port1, const MessagePortIdentifier& port2)
44 {
45     LOG(MessagePorts, "Registry: Creating MessagePortChannel %p linking %s and %s", this, port1.logString().utf8().data(), port2.logString().utf8().data());
46     ASSERT(isMainThread());
47
48     MessagePortChannel::create(*this, port1, port2);
49 }
50
51 void MessagePortChannelRegistry::messagePortChannelCreated(MessagePortChannel& channel)
52 {
53     ASSERT(isMainThread());
54
55     auto result = m_openChannels.ensure(channel.port1(), [channel = &channel] {
56         return channel;
57     });
58     ASSERT(result.isNewEntry);
59
60     result = m_openChannels.ensure(channel.port2(), [channel = &channel] {
61         return channel;
62     });
63     ASSERT(result.isNewEntry);
64 }
65
66 void MessagePortChannelRegistry::messagePortChannelDestroyed(MessagePortChannel& channel)
67 {
68     ASSERT(isMainThread());
69
70     ASSERT(m_openChannels.get(channel.port1()) == &channel);
71     ASSERT(m_openChannels.get(channel.port2()) == &channel);
72
73     m_openChannels.remove(channel.port1());
74     m_openChannels.remove(channel.port2());
75
76     LOG(MessagePorts, "Registry: After removing channel %s there are %u channels left in the registry:", channel.logString().utf8().data(), m_openChannels.size());
77 }
78
79 void MessagePortChannelRegistry::didEntangleLocalToRemote(const MessagePortIdentifier& local, const MessagePortIdentifier& remote, ProcessIdentifier process)
80 {
81     ASSERT(isMainThread());
82
83     // The channel might be gone if the remote side was closed.
84     auto* channel = m_openChannels.get(local);
85     if (!channel)
86         return;
87
88     ASSERT_UNUSED(remote, channel->includesPort(remote));
89
90     channel->entanglePortWithProcess(local, process);
91 }
92
93 void MessagePortChannelRegistry::didDisentangleMessagePort(const MessagePortIdentifier& port)
94 {
95     ASSERT(isMainThread());
96
97     // The channel might be gone if the remote side was closed.
98     auto* channel = m_openChannels.get(port);
99     if (!channel)
100         return;
101
102     channel->disentanglePort(port);
103 }
104
105 void MessagePortChannelRegistry::didCloseMessagePort(const MessagePortIdentifier& port)
106 {
107     ASSERT(isMainThread());
108
109     LOG(MessagePorts, "Registry: MessagePort %s closed in registry", port.logString().utf8().data());
110
111     auto* channel = m_openChannels.get(port);
112     if (!channel)
113         return;
114
115 #ifndef NDEBUG
116     if (channel && channel->hasAnyMessagesPendingOrInFlight())
117         LOG(MessagePorts, "Registry: (Note) The channel closed for port %s had messages pending or in flight", port.logString().utf8().data());
118 #endif
119
120     channel->closePort(port);
121
122     // FIXME: When making message ports be multi-process, this should probably push a notification
123     // to the remaining port to tell it this port closed.
124 }
125
126 bool MessagePortChannelRegistry::didPostMessageToRemote(MessageWithMessagePorts&& message, const MessagePortIdentifier& remoteTarget)
127 {
128     ASSERT(isMainThread());
129
130     LOG(MessagePorts, "Registry: Posting message to MessagePort %s in registry", remoteTarget.logString().utf8().data());
131
132     // The channel might be gone if the remote side was closed.
133     auto* channel = m_openChannels.get(remoteTarget);
134     if (!channel) {
135         LOG(MessagePorts, "Registry: Could not find MessagePortChannel for port %s; It was probably closed. Message will be dropped.", remoteTarget.logString().utf8().data());
136         return false;
137     }
138
139     return channel->postMessageToRemote(WTFMove(message), remoteTarget);
140 }
141
142 void MessagePortChannelRegistry::takeAllMessagesForPort(const MessagePortIdentifier& port, Function<void(Vector<MessageWithMessagePorts>&&, Function<void()>&&)>&& callback)
143 {
144     ASSERT(isMainThread());
145
146     LOG(MessagePorts, "Registry: Taking all messages for MessagePort %s", port.logString().utf8().data());
147
148     // The channel might be gone if the remote side was closed.
149     auto* channel = m_openChannels.get(port);
150     if (!channel) {
151         callback({ }, [] { });
152         return;
153     }
154
155     channel->takeAllMessagesForPort(port, WTFMove(callback));
156 }
157
158 void MessagePortChannelRegistry::checkRemotePortForActivity(const MessagePortIdentifier& remoteTarget, CompletionHandler<void(MessagePortChannelProvider::HasActivity)>&& callback)
159 {
160     ASSERT(isMainThread());
161
162     // The channel might be gone if the remote side was closed.
163     auto* channel = m_openChannels.get(remoteTarget);
164     if (!channel) {
165         callback(MessagePortChannelProvider::HasActivity::No);
166         return;
167     }
168
169     channel->checkRemotePortForActivity(remoteTarget, WTFMove(callback));
170 }
171
172 MessagePortChannel* MessagePortChannelRegistry::existingChannelContainingPort(const MessagePortIdentifier& port)
173 {
174     ASSERT(isMainThread());
175
176     return m_openChannels.get(port);
177 }
178
179 } // namespace WebCore