Home | History | Annotate | Download | only in src
      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