Replace WTF::move with WTFMove
[WebKit-https.git] / Source / WebCore / dom / default / PlatformMessagePortChannel.cpp
1 /*
2  * Copyright (C) 2009 Google Inc. All rights reserved.
3  * Copyright (C) 2013 Apple Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *     * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *     * Neither the name of Google Inc. nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "config.h"
33 #include "PlatformMessagePortChannel.h"
34
35 #include "MessagePort.h"
36 #include "ScriptExecutionContext.h"
37
38 namespace WebCore {
39
40 PlatformMessagePortChannel::EventData::EventData(PassRefPtr<SerializedScriptValue> message, std::unique_ptr<MessagePortChannelArray> channels)
41     : m_message(message)
42     , m_channels(WTFMove(channels))
43 {
44 }
45
46 void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
47 {
48     RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue1 = PlatformMessagePortChannel::MessagePortQueue::create();
49     RefPtr<PlatformMessagePortChannel::MessagePortQueue> queue2 = PlatformMessagePortChannel::MessagePortQueue::create();
50
51     auto channel1 = std::make_unique<MessagePortChannel>(PlatformMessagePortChannel::create(queue1, queue2));
52     auto channel2 = std::make_unique<MessagePortChannel>(PlatformMessagePortChannel::create(queue2, queue1));
53
54     channel1->m_channel->m_entangledChannel = channel2->m_channel;
55     channel2->m_channel->m_entangledChannel = channel1->m_channel;
56
57     port1->entangle(WTFMove(channel2));
58     port2->entangle(WTFMove(channel1));
59 }
60
61 MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)
62     : m_channel(channel)
63 {
64 }
65
66 MessagePortChannel::~MessagePortChannel()
67 {
68     close();
69 }
70
71 bool MessagePortChannel::entangleIfOpen(MessagePort* port)
72 {
73     // We can't call member functions on our remote pair while holding our mutex or we'll deadlock,
74     // but we need to guard against the remote port getting closed/freed, so create a standalone reference.
75     RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
76     if (!remote)
77         return false;
78     remote->setRemotePort(port);
79     return true;
80 }
81
82 void MessagePortChannel::disentangle()
83 {
84     RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
85     if (remote)
86         remote->setRemotePort(nullptr);
87 }
88
89 void MessagePortChannel::postMessageToRemote(PassRefPtr<SerializedScriptValue> message, std::unique_ptr<MessagePortChannelArray> channels)
90 {
91     LockHolder lock(m_channel->m_mutex);
92     if (!m_channel->m_outgoingQueue)
93         return;
94     bool wasEmpty = m_channel->m_outgoingQueue->appendAndCheckEmpty(std::make_unique<PlatformMessagePortChannel::EventData>(message, WTFMove(channels)));
95     if (wasEmpty && m_channel->m_remotePort)
96         m_channel->m_remotePort->messageAvailable();
97 }
98
99 bool MessagePortChannel::tryGetMessageFromRemote(RefPtr<SerializedScriptValue>& message, std::unique_ptr<MessagePortChannelArray>& channels)
100 {
101     LockHolder lock(m_channel->m_mutex);
102     auto result = m_channel->m_incomingQueue->tryGetMessage();
103     if (!result)
104         return false;
105
106     message = result->message();
107     channels = result->channels();
108
109     return true;
110 }
111
112 void MessagePortChannel::close()
113 {
114     RefPtr<PlatformMessagePortChannel> remote = m_channel->entangledChannel();
115     if (!remote)
116         return;
117     m_channel->closeInternal();
118     remote->closeInternal();
119 }
120
121 bool MessagePortChannel::isConnectedTo(MessagePort* port)
122 {
123     // FIXME: What guarantees that the result remains the same after we release the lock?
124     LockHolder lock(m_channel->m_mutex);
125     return m_channel->m_remotePort == port;
126 }
127
128 bool MessagePortChannel::hasPendingActivity()
129 {
130     // FIXME: What guarantees that the result remains the same after we release the lock?
131     LockHolder lock(m_channel->m_mutex);
132     return !m_channel->m_incomingQueue->isEmpty();
133 }
134
135 MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
136 {
137     LockHolder lock(m_channel->m_mutex);
138     // See if both contexts are run by the same thread (are the same context, or are both documents).
139     if (m_channel->m_remotePort) {
140         // The remote port's ScriptExecutionContext is guaranteed not to change here - MessagePort::contextDestroyed()
141         // will close the port before the context goes away, and close() will block because we are holding the mutex.
142         ScriptExecutionContext* remoteContext = m_channel->m_remotePort->scriptExecutionContext();
143         if (remoteContext == context || (remoteContext && remoteContext->isDocument() && context->isDocument()))
144             return m_channel->m_remotePort;
145     }
146     return 0;
147 }
148
149 Ref<PlatformMessagePortChannel> PlatformMessagePortChannel::create(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing)
150 {
151     return adoptRef(*new PlatformMessagePortChannel(incoming, outgoing));
152 }
153
154 PlatformMessagePortChannel::PlatformMessagePortChannel(PassRefPtr<MessagePortQueue> incoming, PassRefPtr<MessagePortQueue> outgoing)
155     : m_incomingQueue(incoming)
156     , m_outgoingQueue(outgoing)
157 {
158 }
159
160 PlatformMessagePortChannel::~PlatformMessagePortChannel()
161 {
162 }
163
164 void PlatformMessagePortChannel::setRemotePort(MessagePort* port)
165 {
166     LockHolder lock(m_mutex);
167     // Should never set port if it is already set.
168     ASSERT(!port || !m_remotePort);
169     m_remotePort = port;
170 }
171
172 PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::entangledChannel()
173 {
174     // FIXME: What guarantees that the result remains the same after we release the lock?
175     // This lock only guarantees that the returned pointer will not be pointing to released memory,
176     // but not that it will still be pointing to this object's entangled port channel.
177     LockHolder lock(m_mutex);
178     return m_entangledChannel;
179 }
180
181 void PlatformMessagePortChannel::closeInternal()
182 {
183     LockHolder lock(m_mutex);
184     // Disentangle ourselves from the other end. We still maintain a reference to our incoming queue, since previously-existing messages should still be delivered.
185     m_remotePort = nullptr;
186     m_entangledChannel = nullptr;
187     m_outgoingQueue = nullptr;
188 }
189
190 } // namespace WebCore