|
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 |
|
47 PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel) |
|
48 { |
|
49 return new MessagePortChannel(channel); |
|
50 } |
|
51 |
|
52 void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2) |
|
53 { |
|
54 PlatformMessagePortChannel::createChannel(port1, port2); |
|
55 } |
|
56 |
|
57 MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel) |
|
58 : m_channel(channel) |
|
59 { |
|
60 } |
|
61 |
|
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 |
|
68 bool MessagePortChannel::entangleIfOpen(MessagePort* port) |
|
69 { |
|
70 return m_channel->entangleIfOpen(port); |
|
71 } |
|
72 |
|
73 void MessagePortChannel::disentangle() |
|
74 { |
|
75 m_channel->disentangle(); |
|
76 } |
|
77 |
|
78 void MessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message) |
|
79 { |
|
80 m_channel->postMessageToRemote(message); |
|
81 } |
|
82 |
|
83 bool MessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result) |
|
84 { |
|
85 return m_channel->tryGetMessageFromRemote(result); |
|
86 } |
|
87 |
|
88 void MessagePortChannel::close() |
|
89 { |
|
90 m_channel->close(); |
|
91 } |
|
92 |
|
93 bool MessagePortChannel::isConnectedTo(MessagePort* port) |
|
94 { |
|
95 return m_channel->isConnectedTo(port); |
|
96 } |
|
97 |
|
98 bool MessagePortChannel::hasPendingActivity() |
|
99 { |
|
100 return m_channel->hasPendingActivity(); |
|
101 } |
|
102 |
|
103 MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context) |
|
104 { |
|
105 // This is just an optimization, so return 0 always. |
|
106 return 0; |
|
107 } |
|
108 |
|
109 |
|
110 PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create() |
|
111 { |
|
112 return adoptRef(new PlatformMessagePortChannel()); |
|
113 } |
|
114 |
|
115 PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create( |
|
116 WebMessagePortChannel* channel) |
|
117 { |
|
118 return adoptRef(new PlatformMessagePortChannel(channel)); |
|
119 } |
|
120 |
|
121 |
|
122 PlatformMessagePortChannel::PlatformMessagePortChannel() |
|
123 : m_localPort(0) |
|
124 { |
|
125 m_webChannel = webKitClient()->createMessagePortChannel(); |
|
126 if (m_webChannel) |
|
127 m_webChannel->setClient(this); |
|
128 } |
|
129 |
|
130 PlatformMessagePortChannel::PlatformMessagePortChannel(WebMessagePortChannel* channel) |
|
131 : m_localPort(0) |
|
132 , m_webChannel(channel) |
|
133 { |
|
134 } |
|
135 |
|
136 PlatformMessagePortChannel::~PlatformMessagePortChannel() |
|
137 { |
|
138 if (m_webChannel) |
|
139 m_webChannel->destroy(); |
|
140 } |
|
141 |
|
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 |
|
157 void PlatformMessagePortChannel::messageAvailable() |
|
158 { |
|
159 MutexLocker lock(m_mutex); |
|
160 if (m_localPort) |
|
161 m_localPort->messageAvailable(); |
|
162 } |
|
163 |
|
164 bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port) |
|
165 { |
|
166 MutexLocker lock(m_mutex); |
|
167 m_localPort = port; |
|
168 return true; |
|
169 } |
|
170 |
|
171 void PlatformMessagePortChannel::disentangle() |
|
172 { |
|
173 MutexLocker lock(m_mutex); |
|
174 m_localPort = 0; |
|
175 } |
|
176 |
|
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 |
|
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 |
|
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 |
|
230 bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port) |
|
231 { |
|
232 MutexLocker lock(m_mutex); |
|
233 return m_entangledChannel && m_entangledChannel->m_localPort == port; |
|
234 } |
|
235 |
|
236 bool PlatformMessagePortChannel::hasPendingActivity() |
|
237 { |
|
238 MutexLocker lock(m_mutex); |
|
239 return m_localPort; |
|
240 } |
|
241 |
|
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 |
|
251 WebMessagePortChannel* PlatformMessagePortChannel::webChannelRelease() |
|
252 { |
|
253 WebMessagePortChannel* rv = m_webChannel; |
|
254 m_webChannel = 0; |
|
255 return rv; |
|
256 } |
|
257 |
|
258 } // namespace WebCore |