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 259