• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2009 Google 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 are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  * copyright notice, this list of conditions and the following disclaimer
12  * in the documentation and/or other materials provided with the
13  * distribution.
14  *     * Neither the name of Google Inc. nor the names of its
15  * contributors may be used to endorse or promote products derived from
16  * this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "config.h"
32 #include "PlatformMessagePortChannel.h"
33 
34 #include "MessagePort.h"
35 #include "ScriptExecutionContext.h"
36 #include "SerializedScriptValue.h"
37 
38 #include "WebKit.h"
39 #include "WebKitClient.h"
40 #include "WebMessagePortChannel.h"
41 #include "WebString.h"
42 
43 using namespace WebKit;
44 
45 namespace WebCore {
46 
create(PassRefPtr<PlatformMessagePortChannel> channel)47 PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel)
48 {
49     return new MessagePortChannel(channel);
50 }
51 
createChannel(PassRefPtr<MessagePort> port1,PassRefPtr<MessagePort> port2)52 void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
53 {
54     PlatformMessagePortChannel::createChannel(port1, port2);
55 }
56 
MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)57 MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)
58     : m_channel(channel)
59 {
60 }
61 
~MessagePortChannel()62 MessagePortChannel::~MessagePortChannel()
63 {
64     // Make sure we close our platform channel when the base is freed, to keep the channel objects from leaking.
65     m_channel->close();
66 }
67 
entangleIfOpen(MessagePort * port)68 bool MessagePortChannel::entangleIfOpen(MessagePort* port)
69 {
70     return m_channel->entangleIfOpen(port);
71 }
72 
disentangle()73 void MessagePortChannel::disentangle()
74 {
75     m_channel->disentangle();
76 }
77 
postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)78 void MessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)
79 {
80     m_channel->postMessageToRemote(message);
81 }
82 
tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData> & result)83 bool MessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result)
84 {
85     return m_channel->tryGetMessageFromRemote(result);
86 }
87 
close()88 void MessagePortChannel::close()
89 {
90     m_channel->close();
91 }
92 
isConnectedTo(MessagePort * port)93 bool MessagePortChannel::isConnectedTo(MessagePort* port)
94 {
95     return m_channel->isConnectedTo(port);
96 }
97 
hasPendingActivity()98 bool MessagePortChannel::hasPendingActivity()
99 {
100     return m_channel->hasPendingActivity();
101 }
102 
locallyEntangledPort(const ScriptExecutionContext * context)103 MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
104 {
105     // This is just an optimization, so return 0 always.
106     return 0;
107 }
108 
109 
create()110 PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create()
111 {
112     return adoptRef(new PlatformMessagePortChannel());
113 }
114 
create(WebMessagePortChannel * channel)115 PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create(
116     WebMessagePortChannel* channel)
117 {
118     return adoptRef(new PlatformMessagePortChannel(channel));
119 }
120 
121 
PlatformMessagePortChannel()122 PlatformMessagePortChannel::PlatformMessagePortChannel()
123     : m_localPort(0)
124 {
125     m_webChannel = webKitClient()->createMessagePortChannel();
126     if (m_webChannel)
127         m_webChannel->setClient(this);
128 }
129 
PlatformMessagePortChannel(WebMessagePortChannel * channel)130 PlatformMessagePortChannel::PlatformMessagePortChannel(WebMessagePortChannel* channel)
131     : m_localPort(0)
132     , m_webChannel(channel)
133 {
134 }
135 
~PlatformMessagePortChannel()136 PlatformMessagePortChannel::~PlatformMessagePortChannel()
137 {
138     if (m_webChannel)
139         m_webChannel->destroy();
140 }
141 
createChannel(PassRefPtr<MessagePort> port1,PassRefPtr<MessagePort> port2)142 void PlatformMessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
143 {
144     // Create proxies for each endpoint.
145     RefPtr<PlatformMessagePortChannel> channel1 = PlatformMessagePortChannel::create();
146     RefPtr<PlatformMessagePortChannel> channel2 = PlatformMessagePortChannel::create();
147 
148     // Entangle the two endpoints.
149     channel1->setEntangledChannel(channel2);
150     channel2->setEntangledChannel(channel1);
151 
152     // Now entangle the proxies with the appropriate local ports.
153     port1->entangle(MessagePortChannel::create(channel2));
154     port2->entangle(MessagePortChannel::create(channel1));
155 }
156 
messageAvailable()157 void PlatformMessagePortChannel::messageAvailable()
158 {
159     MutexLocker lock(m_mutex);
160     if (m_localPort)
161         m_localPort->messageAvailable();
162 }
163 
entangleIfOpen(MessagePort * port)164 bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port)
165 {
166     MutexLocker lock(m_mutex);
167     m_localPort = port;
168     return true;
169 }
170 
disentangle()171 void PlatformMessagePortChannel::disentangle()
172 {
173     MutexLocker lock(m_mutex);
174     m_localPort = 0;
175 }
176 
postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)177 void PlatformMessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)
178 {
179     if (!m_localPort || !m_webChannel)
180         return;
181 
182     WebString messageString = message->message()->toWireString();
183     OwnPtr<WebCore::MessagePortChannelArray> channels = message->channels();
184     WebMessagePortChannelArray* webChannels = 0;
185     if (channels.get() && channels->size()) {
186         webChannels = new WebMessagePortChannelArray(channels->size());
187         for (size_t i = 0; i < channels->size(); ++i) {
188             WebCore::PlatformMessagePortChannel* platformChannel = (*channels)[i]->channel();
189             (*webChannels)[i] = platformChannel->webChannelRelease();
190             (*webChannels)[i]->setClient(0);
191         }
192     }
193     m_webChannel->postMessage(messageString, webChannels);
194 }
195 
tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData> & result)196 bool PlatformMessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result)
197 {
198     if (!m_webChannel)
199         return false;
200 
201     WebString message;
202     WebMessagePortChannelArray webChannels;
203     bool rv = m_webChannel->tryGetMessage(&message, webChannels);
204     if (rv) {
205         OwnPtr<MessagePortChannelArray> channels;
206         if (webChannels.size()) {
207             channels = new MessagePortChannelArray(webChannels.size());
208             for (size_t i = 0; i < webChannels.size(); ++i) {
209                 RefPtr<PlatformMessagePortChannel> platformChannel = create(webChannels[i]);
210                 webChannels[i]->setClient(platformChannel.get());
211                 (*channels)[i] = MessagePortChannel::create(platformChannel);
212             }
213         }
214         RefPtr<SerializedScriptValue> serializedMessage = SerializedScriptValue::createFromWire(message);
215         result = MessagePortChannel::EventData::create(serializedMessage.release(), channels.release());
216     }
217 
218     return rv;
219 }
220 
close()221 void PlatformMessagePortChannel::close()
222 {
223     MutexLocker lock(m_mutex);
224     // Disentangle ourselves from the other end.  We still maintain a reference to m_webChannel,
225     // since previously-existing messages should still be delivered.
226     m_localPort = 0;
227     m_entangledChannel = 0;
228 }
229 
isConnectedTo(MessagePort * port)230 bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port)
231 {
232     MutexLocker lock(m_mutex);
233     return m_entangledChannel && m_entangledChannel->m_localPort == port;
234 }
235 
hasPendingActivity()236 bool PlatformMessagePortChannel::hasPendingActivity()
237 {
238     MutexLocker lock(m_mutex);
239     return m_localPort;
240 }
241 
setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote)242 void PlatformMessagePortChannel::setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote)
243 {
244     if (m_webChannel)
245         m_webChannel->entangle(remote->m_webChannel);
246 
247     MutexLocker lock(m_mutex);
248     m_entangledChannel = remote;
249 }
250 
webChannelRelease()251 WebMessagePortChannel* PlatformMessagePortChannel::webChannelRelease()
252 {
253     WebMessagePortChannel* rv = m_webChannel;
254     m_webChannel = 0;
255     return rv;
256 }
257 
258 } // namespace WebCore
259