Index: WebCore/websockets/WebSocket.cpp |
diff --git a/WebCore/websockets/WebSocket.cpp b/WebCore/websockets/WebSocket.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..a6628be4bf188b961a7272b883616c653dfe11a1 |
--- /dev/null |
+++ b/WebCore/websockets/WebSocket.cpp |
@@ -0,0 +1,232 @@ |
+/* |
+ * 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" |
+ |
+#if ENABLE(WEB_SOCKETS) |
+ |
+#include "WebSocket.h" |
+ |
+#include "CString.h" |
+#include "DOMWindow.h" |
+#include "Event.h" |
+#include "EventException.h" |
+#include "EventListener.h" |
+#include "EventNames.h" |
+#include "Logging.h" |
+#include "MessageEvent.h" |
+#include "ScriptExecutionContext.h" |
+#include "SecurityOrigin.h" |
+#include "WebSocketChannel.h" |
+#include "WebSocketRequest.h" |
+#include <wtf/StdLibExtras.h> |
+ |
+namespace { |
+ |
+bool IsValidProtocolString(const WebCore::String& protocol) |
+{ |
+ const UChar* characters = protocol.characters(); |
+ for (size_t i = 0; i < protocol.length(); i++) { |
+ if (characters[i] < 0x21 || characters[i] > 0x7E) |
+ return false; |
+ } |
+ return true; |
+} |
+ |
+} // anonymous namespace |
+ |
+namespace WebCore { |
+ |
+WebSocket::WebSocket(ScriptExecutionContext* context) |
+ : ActiveDOMObject(context, this) |
+ , m_state(CONNECTING) |
+{ |
+} |
+ |
+WebSocket::~WebSocket() |
+{ |
+ close(); |
+} |
+ |
+void WebSocket::connect(const KURL& url, ExceptionCode& ec) |
+{ |
+ connect(url, "", ec); |
+} |
+ |
+void WebSocket::connect(const KURL& url, const String& protocol, ExceptionCode& ec) |
+{ |
+ LOG(Network, "WebSocket %p connect to %s protocol=%s", this, url.string().utf8().data(), protocol.utf8().data()); |
+ m_url = url; |
+ m_protocol = protocol; |
+ |
+ if (!m_url.protocolIs("ws") && !m_url.protocolIs("wss")) { |
+ LOG_ERROR("Error: wrong url for WebSocket %s", url.string().utf8().data()); |
+ m_state = CLOSED; |
+ ec = SYNTAX_ERR; |
+ return; |
+ } |
+ if (!protocol.isEmpty() && !IsValidProtocolString(protocol)) { |
+ LOG_ERROR("Error: wrong protocol for WebSocket %s", protocol.utf8().data()); |
+ m_state = CLOSED; |
+ ec = SYNTAX_ERR; |
+ return; |
+ } |
+ // TODO(ukai): if m_url.port() is blocking port, raise SECURITY_ERR. |
+ |
+ WebSocketRequest request(m_url, m_protocol, scriptExecutionContext()->securityOrigin()->toString()); |
+ m_channel = WebSocketChannel::create(scriptExecutionContext(), this, request); |
+ m_channel->connect(); |
+} |
+ |
+bool WebSocket::send(const String& message, ExceptionCode& ec) |
+{ |
+ LOG(Network, "WebSocket %p send %s", this, message.utf8().data()); |
+ if (m_state == CONNECTING) { |
+ ec = INVALID_STATE_ERR; |
+ return false; |
+ } |
+ // No exception is raised if the connection was once established but has subsequently been closed. |
+ if (m_state == CLOSED) |
+ return false; |
+ // FIXME: check message is valid |
+ return m_channel->send(message); |
+} |
+ |
+void WebSocket::close() |
+{ |
+ LOG(Network, "WebSocket %p close", this); |
+ if (m_state == CLOSED) |
+ return; |
+ m_state = CLOSED; |
+ m_channel->close(); |
+} |
+ |
+const KURL& WebSocket::url() const |
+{ |
+ return m_url; |
+} |
+ |
+WebSocket::State WebSocket::readyState() const |
+{ |
+ return m_state; |
+} |
+ |
+unsigned long WebSocket::bufferedAmount() const |
+{ |
+ if (m_state == OPEN) |
+ return m_channel->bufferedAmount(); |
+ return 0; |
+} |
+ |
+ScriptExecutionContext* WebSocket::scriptExecutionContext() const |
+{ |
+ return ActiveDOMObject::scriptExecutionContext(); |
+} |
+ |
+void WebSocket::addEventListener(const AtomicString& eventType, PassRefPtr<EventListener> listener, bool useCapture) |
+{ |
+ // FIXME: implement this. |
+} |
+ |
+void WebSocket::removeEventListener(const AtomicString& eventType, EventListener* listener, bool useCapture) |
+{ |
+ // FIXME: implement this. |
+} |
+ |
+bool WebSocket::dispatchEvent(PassRefPtr<Event> event, ExceptionCode& ec) |
+{ |
+ // FIXME: implement this. |
+ return false; |
+} |
+ |
+void WebSocket::didConnect() |
+{ |
+ LOG(Network, "WebSocket %p didConnect", this); |
+ if (m_state != CONNECTING) { |
+ didClose(); |
+ return; |
+ } |
+ m_state = OPEN; |
+ dispatchOpenEvent(); |
+} |
+ |
+void WebSocket::didReceiveMessage(const String& msg) |
+{ |
+ LOG(Network, "WebSocket %p didReceiveMessage %s", this, msg.utf8().data()); |
+ if (m_state != OPEN) |
+ return; |
+ dispatchMessageEvent(msg); |
+} |
+ |
+void WebSocket::didClose() |
+{ |
+ LOG(Network, "WebSocket %p didClose", this); |
+ m_state = CLOSED; |
+ dispatchCloseEvent(); |
+} |
+ |
+void WebSocket::dispatchOpenEvent() |
+{ |
+ RefPtr<Event> evt = Event::create(eventNames().openEvent, false, false); |
+ if (m_onopen) { |
+ evt->setTarget(this); |
+ evt->setCurrentTarget(this); |
+ m_onopen->handleEvent(evt.get(), false); |
+ } |
+ // FIXME: need dispatchEvent? |
+} |
+ |
+void WebSocket::dispatchMessageEvent(const String& msg) |
+{ |
+ RefPtr<MessageEvent> evt = MessageEvent::create(); |
+ // FIXME: origin, lastEventId, source, messagePort. |
+ evt->initMessageEvent(eventNames().messageEvent, false, false, msg, "", "", NULL, NULL); |
+ if (m_onmessage) { |
+ evt->setTarget(this); |
+ evt->setCurrentTarget(this); |
+ m_onmessage->handleEvent(evt.get(), false); |
+ } |
+ // FIXME: need dispatchEvent? |
+} |
+ |
+void WebSocket::dispatchCloseEvent() |
+{ |
+ RefPtr<Event> evt = Event::create(eventNames().closeEvent, false, false); |
+ if (m_onclose) { |
+ evt->setTarget(this); |
+ evt->setCurrentTarget(this); |
+ m_onclose->handleEvent(evt.get(), false); |
+ } |
+ // FIXME: need dispatchEvent? |
+} |
+ |
+} // namespace WebCore |
+ |
+#endif |