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