WebKit/chromium/src/PlatformMessagePortChannel.cpp
changeset 0 4f2f89ce4247
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/WebKit/chromium/src/PlatformMessagePortChannel.cpp	Fri Sep 17 09:02:29 2010 +0300
@@ -0,0 +1,258 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "PlatformMessagePortChannel.h"
+
+#include "MessagePort.h"
+#include "ScriptExecutionContext.h"
+#include "SerializedScriptValue.h"
+
+#include "WebKit.h"
+#include "WebKitClient.h"
+#include "WebMessagePortChannel.h"
+#include "WebString.h"
+
+using namespace WebKit;
+
+namespace WebCore {
+
+PassOwnPtr<MessagePortChannel> MessagePortChannel::create(PassRefPtr<PlatformMessagePortChannel> channel)
+{
+    return new MessagePortChannel(channel);
+}
+
+void MessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
+{
+    PlatformMessagePortChannel::createChannel(port1, port2);
+}
+
+MessagePortChannel::MessagePortChannel(PassRefPtr<PlatformMessagePortChannel> channel)
+    : m_channel(channel)
+{
+}
+
+MessagePortChannel::~MessagePortChannel()
+{
+    // Make sure we close our platform channel when the base is freed, to keep the channel objects from leaking.
+    m_channel->close();
+}
+
+bool MessagePortChannel::entangleIfOpen(MessagePort* port)
+{
+    return m_channel->entangleIfOpen(port);
+}
+
+void MessagePortChannel::disentangle()
+{
+    m_channel->disentangle();
+}
+
+void MessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)
+{
+    m_channel->postMessageToRemote(message);
+}
+
+bool MessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result)
+{
+    return m_channel->tryGetMessageFromRemote(result);
+}
+
+void MessagePortChannel::close()
+{
+    m_channel->close();
+}
+
+bool MessagePortChannel::isConnectedTo(MessagePort* port)
+{
+    return m_channel->isConnectedTo(port);
+}
+
+bool MessagePortChannel::hasPendingActivity()
+{
+    return m_channel->hasPendingActivity();
+}
+
+MessagePort* MessagePortChannel::locallyEntangledPort(const ScriptExecutionContext* context)
+{
+    // This is just an optimization, so return 0 always.
+    return 0;
+}
+
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create()
+{
+    return adoptRef(new PlatformMessagePortChannel());
+}
+
+PassRefPtr<PlatformMessagePortChannel> PlatformMessagePortChannel::create(
+    WebMessagePortChannel* channel)
+{
+    return adoptRef(new PlatformMessagePortChannel(channel));
+}
+
+
+PlatformMessagePortChannel::PlatformMessagePortChannel()
+    : m_localPort(0)
+{
+    m_webChannel = webKitClient()->createMessagePortChannel();
+    if (m_webChannel)
+        m_webChannel->setClient(this);
+}
+
+PlatformMessagePortChannel::PlatformMessagePortChannel(WebMessagePortChannel* channel)
+    : m_localPort(0)
+    , m_webChannel(channel)
+{
+}
+
+PlatformMessagePortChannel::~PlatformMessagePortChannel()
+{
+    if (m_webChannel)
+        m_webChannel->destroy();
+}
+
+void PlatformMessagePortChannel::createChannel(PassRefPtr<MessagePort> port1, PassRefPtr<MessagePort> port2)
+{
+    // Create proxies for each endpoint.
+    RefPtr<PlatformMessagePortChannel> channel1 = PlatformMessagePortChannel::create();
+    RefPtr<PlatformMessagePortChannel> channel2 = PlatformMessagePortChannel::create();
+
+    // Entangle the two endpoints.
+    channel1->setEntangledChannel(channel2);
+    channel2->setEntangledChannel(channel1);
+
+    // Now entangle the proxies with the appropriate local ports.
+    port1->entangle(MessagePortChannel::create(channel2));
+    port2->entangle(MessagePortChannel::create(channel1));
+}
+
+void PlatformMessagePortChannel::messageAvailable()
+{
+    MutexLocker lock(m_mutex);
+    if (m_localPort)
+        m_localPort->messageAvailable();
+}
+
+bool PlatformMessagePortChannel::entangleIfOpen(MessagePort* port)
+{
+    MutexLocker lock(m_mutex);
+    m_localPort = port;
+    return true;
+}
+
+void PlatformMessagePortChannel::disentangle()
+{
+    MutexLocker lock(m_mutex);
+    m_localPort = 0;
+}
+
+void PlatformMessagePortChannel::postMessageToRemote(PassOwnPtr<MessagePortChannel::EventData> message)
+{
+    if (!m_localPort || !m_webChannel)
+        return;
+
+    WebString messageString = message->message()->toWireString();
+    OwnPtr<WebCore::MessagePortChannelArray> channels = message->channels();
+    WebMessagePortChannelArray* webChannels = 0;
+    if (channels.get() && channels->size()) {
+        webChannels = new WebMessagePortChannelArray(channels->size());
+        for (size_t i = 0; i < channels->size(); ++i) {
+            WebCore::PlatformMessagePortChannel* platformChannel = (*channels)[i]->channel();
+            (*webChannels)[i] = platformChannel->webChannelRelease();
+            (*webChannels)[i]->setClient(0);
+        }
+    }
+    m_webChannel->postMessage(messageString, webChannels);
+}
+
+bool PlatformMessagePortChannel::tryGetMessageFromRemote(OwnPtr<MessagePortChannel::EventData>& result)
+{
+    if (!m_webChannel)
+        return false;
+
+    WebString message;
+    WebMessagePortChannelArray webChannels;
+    bool rv = m_webChannel->tryGetMessage(&message, webChannels);
+    if (rv) {
+        OwnPtr<MessagePortChannelArray> channels;
+        if (webChannels.size()) {
+            channels = new MessagePortChannelArray(webChannels.size());
+            for (size_t i = 0; i < webChannels.size(); ++i) {
+                RefPtr<PlatformMessagePortChannel> platformChannel = create(webChannels[i]);
+                webChannels[i]->setClient(platformChannel.get());
+                (*channels)[i] = MessagePortChannel::create(platformChannel);
+            }
+        }
+        RefPtr<SerializedScriptValue> serializedMessage = SerializedScriptValue::createFromWire(message);
+        result = MessagePortChannel::EventData::create(serializedMessage.release(), channels.release());
+    }
+
+    return rv;
+}
+
+void PlatformMessagePortChannel::close()
+{
+    MutexLocker lock(m_mutex);
+    // Disentangle ourselves from the other end.  We still maintain a reference to m_webChannel,
+    // since previously-existing messages should still be delivered.
+    m_localPort = 0;
+    m_entangledChannel = 0;
+}
+
+bool PlatformMessagePortChannel::isConnectedTo(MessagePort* port)
+{
+    MutexLocker lock(m_mutex);
+    return m_entangledChannel && m_entangledChannel->m_localPort == port;
+}
+
+bool PlatformMessagePortChannel::hasPendingActivity()
+{
+    MutexLocker lock(m_mutex);
+    return m_localPort;
+}
+
+void PlatformMessagePortChannel::setEntangledChannel(PassRefPtr<PlatformMessagePortChannel> remote)
+{
+    if (m_webChannel)
+        m_webChannel->entangle(remote->m_webChannel);
+
+    MutexLocker lock(m_mutex);
+    m_entangledChannel = remote;
+}
+
+WebMessagePortChannel* PlatformMessagePortChannel::webChannelRelease()
+{
+    WebMessagePortChannel* rv = m_webChannel;
+    m_webChannel = 0;
+    return rv;
+}
+
+} // namespace WebCore