summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>2011-08-19 10:16:27 (GMT)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>2011-08-19 10:16:27 (GMT)
commitf7b7ff753be8e84253b2413a9125eebfe0315cd2 (patch)
treeadb69e0ef1529175b7707c76a784c7e0f7d95ea2
parente6e56a6f6233f80a95a85603fe5eaa4851406bd3 (diff)
downloadGESWebKit-master.tar.gz
GESWebKit-master.tar.xz
[WebSocket] CloseEvent's code and reason properties support.HEADmaster
https://bugs.webkit.org/show_bug.cgi?id=66362 Patch by Takashi Toyoshima <toyoshim@chromium.org> on 2011-08-19 Reviewed by Kent Tamura. Current WebSocket implementation miss code and reason properties in CloseEvent. This change expose incoming closing frame's code and reason to JavaScript API. Source/WebCore: Tests: http/tests/websocket/tests/hybi/close-code-and-reason.html http/tests/websocket/tests/hybi/workers/close-code-and-reason.html * websockets/CloseEvent.h: (WebCore::CloseEvent::initCloseEvent): (WebCore::CloseEvent::code): (WebCore::CloseEvent::reason): (WebCore::CloseEvent::CloseEvent): * websockets/CloseEvent.idl: Add code and reason properies. * websockets/ThreadableWebSocketChannelClientWrapper.cpp: (WebCore::ThreadableWebSocketChannelClientWrapper::didClose): (WebCore::ThreadableWebSocketChannelClientWrapper::didCloseCallback): * websockets/ThreadableWebSocketChannelClientWrapper.h: * websockets/WebSocket.cpp: (WebCore::WebSocket::didConnect): (WebCore::WebSocket::didClose): * websockets/WebSocket.h: Add implement to handle code and reason. * websockets/WebSocketChannel.cpp: (WebCore::WebSocketChannel::WebSocketChannel): (WebCore::WebSocketChannel::didCloseSocketStream): (WebCore::WebSocketChannel::processFrame): * websockets/WebSocketChannel.h: Add closing frame payload parser. * websockets/WebSocketChannelClient.h: (WebCore::WebSocketChannelClient::didClose): * websockets/WorkerThreadableWebSocketChannel.cpp: (WebCore::workerContextDidClose): (WebCore::WorkerThreadableWebSocketChannel::Peer::didClose): * websockets/WorkerThreadableWebSocketChannel.h: Add implement to handle code and reason. LayoutTests: * http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt: Added. * http/tests/websocket/tests/hybi/close-code-and-reason.html: Added. * http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py: Added. * http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt: Added. * http/tests/websocket/tests/hybi/workers/close-code-and-reason.html: Added. * http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js: Added. (postResult): (ws.onopen): (ws.onmessage): (ws.onclose): git-svn-id: http://svn.webkit.org/repository/webkit/trunk@93393 268f45cc-cd09-0410-ab3c-d52691b4dbfc
-rw-r--r--LayoutTests/ChangeLog22
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt34
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason.html100
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py19
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt35
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason.html40
-rw-r--r--LayoutTests/http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js85
-rw-r--r--Source/WebCore/ChangeLog44
-rw-r--r--Source/WebCore/websockets/CloseEvent.h9
-rw-r--r--Source/WebCore/websockets/CloseEvent.idl6
-rw-r--r--Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp8
-rw-r--r--Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h4
-rw-r--r--Source/WebCore/websockets/WebSocket.cpp6
-rw-r--r--Source/WebCore/websockets/WebSocket.h2
-rw-r--r--Source/WebCore/websockets/WebSocketChannel.cpp14
-rw-r--r--Source/WebCore/websockets/WebSocketChannel.h13
-rw-r--r--Source/WebCore/websockets/WebSocketChannelClient.h4
-rw-r--r--Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp10
-rw-r--r--Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h4
19 files changed, 436 insertions, 23 deletions
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 565a1d0..db8a588 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,25 @@
+2011-08-19 Takashi Toyoshima <toyoshim@chromium.org>
+
+ [WebSocket] CloseEvent's code and reason properties support.
+ https://bugs.webkit.org/show_bug.cgi?id=66362
+
+ Reviewed by Kent Tamura.
+
+ Current WebSocket implementation miss code and reason properties
+ in CloseEvent. This change expose incoming closing frame's code
+ and reason to JavaScript API.
+
+ * http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt: Added.
+ * http/tests/websocket/tests/hybi/close-code-and-reason.html: Added.
+ * http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py: Added.
+ * http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt: Added.
+ * http/tests/websocket/tests/hybi/workers/close-code-and-reason.html: Added.
+ * http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js: Added.
+ (postResult):
+ (ws.onopen):
+ (ws.onmessage):
+ (ws.onclose):
+
2011-08-19 MORITA Hajime <morrita@google.com>
Spell-checking doesn't recognize word boundaries on contests inserted by execCommand('insertHTML')
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt
new file mode 100644
index 0000000..bf24ac2
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason-expected.txt
@@ -0,0 +1,34 @@
+CONSOLE MESSAGE: line 0: WebSocket is closed before the connection is established.
+Test CloseEvent code and reason property.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+ws.onclose() was called.
+PASS closeEvent.wasClean is false
+PASS closeEvent.code is codeAbnormalClosure
+PASS closeEvent.reason is emptyString
+WebSocketTest.onopen() was called with testId = 0.
+WebSocketTest.onclose() was called with testId = 0.
+PASS closeEvent.wasClean is true
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+WebSocketTest.onopen() was called with testId = 1.
+WebSocketTest.onclose() was called with testId = 1.
+PASS closeEvent.wasClean is true
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+WebSocketTest.onopen() was called with testId = 2.
+WebSocketTest.onclose() was called with testId = 2.
+PASS closeEvent.wasClean is true
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+PASS closeEvent.code is expectedCode[testId]
+PASS closeEvent.reason is expectedReason[testId]
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason.html b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason.html
new file mode 100644
index 0000000..d288eb5
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason.html
@@ -0,0 +1,100 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
+<script src="../../../../js-test-resources/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script type="text/javascript">
+description("Test CloseEvent code and reason property.");
+
+window.jsTestIsAsync = true;
+if (window.layoutTestController)
+ layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
+
+var closeEvent;
+var codeNoStatusRcvd = 1005;
+var codeAbnormalClosure = 1006;
+var emptyString = "";
+
+var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/hanging-handshake");
+
+ws.onopen = function(event)
+{
+ testFailed("ws.onopen() was called. (message = \"" + event.data + "\")");
+};
+
+ws.onclose = function(event)
+{
+ debug("ws.onclose() was called.");
+ closeEvent = event;
+ shouldBeFalse("closeEvent.wasClean");
+ shouldBe("closeEvent.code", "codeAbnormalClosure");
+ shouldBe("closeEvent.reason", "emptyString");
+};
+
+ws.close();
+
+var testId = 0;
+var testNum = 3;
+var sendData = [
+ "-", // request close frame without code and reason
+ "--", // request close frame with invalid body which size is 1
+ "65535 good bye", // request close frame with specified code and reason
+];
+var expectedCode = [
+ codeNoStatusRcvd,
+ codeNoStatusRcvd,
+ 65535,
+];
+var expectedReason = [
+ "",
+ "",
+ "good bye",
+];
+
+WebSocketTest = function() {
+ this.ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/close-code-and-reason");
+ this.ws.onopen = this.onopen;
+ this.ws.onmessage = this.onmessage;
+ this.ws.onclose = this.onclose;
+};
+
+WebSocketTest.prototype.onopen = function()
+{
+ debug("WebSocketTest.onopen() was called with testId = " + testId + ".");
+ this.send(sendData[testId]);
+};
+
+WebSocketTest.prototype.onmessage = function(event)
+{
+ testFailed("WebSocketTest.onmessage() was called. (message = \"" + event.data + "\")");
+};
+
+WebSocketTest.prototype.onclose = function(event)
+{
+ closeEvent = event;
+ debug("WebSocketTest.onclose() was called with testId = " + testId + ".");
+ shouldBeTrue("closeEvent.wasClean");
+ shouldBe("closeEvent.code", "expectedCode[testId]");
+ shouldBe("closeEvent.reason", "expectedReason[testId]");
+ closeEvent.code = 0;
+ closeEvent.reason = "readonly";
+ shouldBe("closeEvent.code", "expectedCode[testId]");
+ shouldBe("closeEvent.reason", "expectedReason[testId]");
+ testId++;
+ if (testId < testNum)
+ test = new WebSocketTest();
+ else
+ finishJSTest();
+};
+
+var test = new WebSocketTest();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py
new file mode 100644
index 0000000..15a2d24
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/close-code-and-reason_wsh.py
@@ -0,0 +1,19 @@
+import struct
+
+from mod_pywebsocket import stream
+
+def web_socket_do_extra_handshake(request):
+ pass
+
+def web_socket_transfer_data(request):
+ line = request.ws_stream.receive_message()
+ if line is None:
+ return
+ if line == '-':
+ data = ''
+ elif line == '--':
+ data = 'X'
+ else:
+ code, reason = line.split(' ', 1)
+ data = struct.pack('!H', int(code)) + reason.encode('utf-8')
+ request.connection.write(stream.create_close_frame(data))
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt b/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt
new file mode 100644
index 0000000..2cb0895
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason-expected.txt
@@ -0,0 +1,35 @@
+CONSOLE MESSAGE: line 0: WebSocket is closed before the connection is established.
+Test CloseEvent code and reason property in Worker.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+ws.onclose() was called.
+PASS PASS: worker: event.wasClean is false
+PASS PASS: worker: event.code is codeAbnormalClosure
+PASS PASS: worker: event.reason is emptyString
+WebSocketTest.onopen() was called with testId = 0.
+WebSocketTest.onclose() was called with testId = 0.
+PASS PASS: worker: event.wasClean is true
+PASS PASS: worker: event.code is 1005
+PASS PASS: worker: event.reason is
+PASS PASS: worker: event.code is 1005
+PASS PASS: worker: event.reason is
+WebSocketTest.onopen() was called with testId = 1.
+WebSocketTest.onclose() was called with testId = 1.
+PASS PASS: worker: event.wasClean is true
+PASS PASS: worker: event.code is 1005
+PASS PASS: worker: event.reason is
+PASS PASS: worker: event.code is 1005
+PASS PASS: worker: event.reason is
+WebSocketTest.onopen() was called with testId = 2.
+WebSocketTest.onclose() was called with testId = 2.
+PASS PASS: worker: event.wasClean is true
+PASS PASS: worker: event.code is 65535
+PASS PASS: worker: event.reason is good bye
+PASS PASS: worker: event.code is 65535
+PASS PASS: worker: event.reason is good bye
+DONE
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason.html b/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason.html
new file mode 100644
index 0000000..7ff287c
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/workers/close-code-and-reason.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link rel="stylesheet" href="../../../../../js-test-resources/js-test-style.css">
+<script src="../../../../../js-test-resources/js-test-pre.js"></script>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script type="text/javascript">
+description("Test CloseEvent code and reason property in Worker.");
+
+window.jsTestIsAsync = true;
+if (window.layoutTestController)
+ layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
+
+function startsWith(str, prefix)
+{
+ return str.indexOf(prefix) == 0;
+}
+
+var worker = new Worker("resources/close-code-and-reason.js");
+worker.onmessage = function (event)
+{
+ var message = event.data;
+ if (startsWith(message, "PASS"))
+ testPassed(message);
+ else if (startsWith(message, "FAIL"))
+ testFailed(message)
+ else
+ debug(message);
+ if (message === "DONE")
+ finishJSTest();
+};
+
+var successfullyParsed = true;
+</script>
+<script src="../../../../../js-test-resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js b/LayoutTests/http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js
new file mode 100644
index 0000000..ad9c7d7
--- /dev/null
+++ b/LayoutTests/http/tests/websocket/tests/hybi/workers/resources/close-code-and-reason.js
@@ -0,0 +1,85 @@
+var codeNoStatusRcvd = 1005;
+var codeAbnormalClosure = 1006;
+var emptyString = "";
+
+function postResult(result, actual, expected)
+{
+ var message = result ? "PASS" : "FAIL";
+ message += ": worker: " + actual + " is ";
+ if (!result)
+ message += "not ";
+ message += expected;
+ postMessage(message);
+}
+
+var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/hanging-handshake");
+
+ws.onopen = function(event)
+{
+ testFailed("FAIL: ws.onopen() was called. (message = \"" + event.data + "\")");
+};
+
+ws.onclose = function(event)
+{
+ postMessage("ws.onclose() was called.");
+ postResult(!event.wasClean, "event.wasClean", "false");
+ postResult(event.code == codeAbnormalClosure, "event.code", "codeAbnormalClosure");
+ postResult(event.reason == emptyString, "event.reason", "emptyString");
+};
+
+ws.close();
+
+var testId = 0;
+var testNum = 3;
+var sendData = [
+ "-", // request close frame without code and reason
+ "--", // request close frame with invalid body which size is 1
+ "65535 good bye", // request close frame with specified code and reason
+];
+var expectedCode = [
+ codeNoStatusRcvd,
+ codeNoStatusRcvd,
+ 65535,
+];
+var expectedReason = [
+ "",
+ "",
+ "good bye",
+];
+
+WebSocketTest = function() {
+ this.ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/close-code-and-reason");
+ this.ws.onopen = this.onopen;
+ this.ws.onmessage = this.onmessage;
+ this.ws.onclose = this.onclose;
+};
+
+WebSocketTest.prototype.onopen = function()
+{
+ postMessage("WebSocketTest.onopen() was called with testId = " + testId + ".");
+ this.send(sendData[testId]);
+};
+
+WebSocketTest.prototype.onmessage = function(event)
+{
+ postMessage("FAIL: WebSocketTest.onmessage() was called. (message = \"" + event.data + "\")");
+};
+
+WebSocketTest.prototype.onclose = function(event)
+{
+ postMessage("WebSocketTest.onclose() was called with testId = " + testId + ".");
+ postResult(event.wasClean, "event.wasClean", "true");
+ postResult(event.code == expectedCode[testId], "event.code", expectedCode[testId]);
+ postResult(event.reason == expectedReason[testId], "event.reason", expectedReason[testId]);
+ event.code = 0;
+ event.reason = "readonly";
+ postResult(event.code == expectedCode[testId], "event.code", expectedCode[testId]);
+ postResult(event.reason == expectedReason[testId], "event.reason", expectedReason[testId]);
+ testId++;
+ if (testId < testNum)
+ test = new WebSocketTest();
+ else
+ postMessage("DONE")
+};
+
+var test = new WebSocketTest();
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 3935106..1077f2a 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,47 @@
+2011-08-19 Takashi Toyoshima <toyoshim@chromium.org>
+
+ [WebSocket] CloseEvent's code and reason properties support.
+ https://bugs.webkit.org/show_bug.cgi?id=66362
+
+ Reviewed by Kent Tamura.
+
+ Current WebSocket implementation miss code and reason properties
+ in CloseEvent. This change expose incoming closing frame's code
+ and reason to JavaScript API.
+
+ Tests: http/tests/websocket/tests/hybi/close-code-and-reason.html
+ http/tests/websocket/tests/hybi/workers/close-code-and-reason.html
+
+ * websockets/CloseEvent.h:
+ (WebCore::CloseEvent::initCloseEvent):
+ (WebCore::CloseEvent::code):
+ (WebCore::CloseEvent::reason):
+ (WebCore::CloseEvent::CloseEvent):
+ * websockets/CloseEvent.idl:
+ Add code and reason properies.
+ * websockets/ThreadableWebSocketChannelClientWrapper.cpp:
+ (WebCore::ThreadableWebSocketChannelClientWrapper::didClose):
+ (WebCore::ThreadableWebSocketChannelClientWrapper::didCloseCallback):
+ * websockets/ThreadableWebSocketChannelClientWrapper.h:
+ * websockets/WebSocket.cpp:
+ (WebCore::WebSocket::didConnect):
+ (WebCore::WebSocket::didClose):
+ * websockets/WebSocket.h:
+ Add implement to handle code and reason.
+ * websockets/WebSocketChannel.cpp:
+ (WebCore::WebSocketChannel::WebSocketChannel):
+ (WebCore::WebSocketChannel::didCloseSocketStream):
+ (WebCore::WebSocketChannel::processFrame):
+ * websockets/WebSocketChannel.h:
+ Add closing frame payload parser.
+ * websockets/WebSocketChannelClient.h:
+ (WebCore::WebSocketChannelClient::didClose):
+ * websockets/WorkerThreadableWebSocketChannel.cpp:
+ (WebCore::workerContextDidClose):
+ (WebCore::WorkerThreadableWebSocketChannel::Peer::didClose):
+ * websockets/WorkerThreadableWebSocketChannel.h:
+ Add implement to handle code and reason.
+
2011-08-19 MORITA Hajime <morrita@google.com>
Spell-checking doesn't recognize word boundaries on contests inserted by execCommand('insertHTML')
diff --git a/Source/WebCore/websockets/CloseEvent.h b/Source/WebCore/websockets/CloseEvent.h
index a079003..9bf259c 100644
--- a/Source/WebCore/websockets/CloseEvent.h
+++ b/Source/WebCore/websockets/CloseEvent.h
@@ -45,7 +45,7 @@ public:
return adoptRef(new CloseEvent());
}
- void initCloseEvent(const AtomicString& type, bool canBubble, bool cancelable, bool wasClean)
+ void initCloseEvent(const AtomicString& type, bool canBubble, bool cancelable, bool wasClean, unsigned short code, const String& reason)
{
if (dispatched())
return;
@@ -53,17 +53,24 @@ public:
initEvent(type, canBubble, cancelable);
m_wasClean = wasClean;
+ m_code = code;
+ m_reason = reason;
}
bool wasClean() const { return m_wasClean; }
+ unsigned short code() const { return m_code; }
+ String reason() const { return m_reason; }
private:
CloseEvent()
: Event(eventNames().closeEvent, false, false)
, m_wasClean(false)
+ , m_code(0)
{ }
bool m_wasClean;
+ unsigned short m_code;
+ String m_reason;
};
} // namespace WebCore
diff --git a/Source/WebCore/websockets/CloseEvent.idl b/Source/WebCore/websockets/CloseEvent.idl
index d74ab2d..a2911466 100644
--- a/Source/WebCore/websockets/CloseEvent.idl
+++ b/Source/WebCore/websockets/CloseEvent.idl
@@ -34,10 +34,14 @@ module events {
NoStaticTables
] CloseEvent : Event {
readonly attribute boolean wasClean;
+ readonly attribute unsigned short code;
+ readonly attribute [ConvertingNullStringTo=Undefined] DOMString reason;
void initCloseEvent(in [Optional=CallWithDefaultValue] DOMString typeArg,
in [Optional=CallWithDefaultValue] boolean canBubbleArg,
in [Optional=CallWithDefaultValue] boolean cancelableArg,
- in [Optional=CallWithDefaultValue] boolean wasCleanArg);
+ in [Optional=CallWithDefaultValue] boolean wasCleanArg,
+ in [Optional=CallWithDefaultValue] unsigned short codeArg,
+ in [Optional=CallWithDefaultValue] DOMString reasonArg);
};
}
diff --git a/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp b/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp
index 1a179c9..23f45ad 100644
--- a/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp
+++ b/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.cpp
@@ -139,9 +139,9 @@ void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshake()
processPendingTasks();
}
-void ThreadableWebSocketChannelClientWrapper::didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion)
+void ThreadableWebSocketChannelClientWrapper::didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
- m_pendingTasks.append(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::didCloseCallback, AllowCrossThreadAccess(this), unhandledBufferedAmount, closingHandshakeCompletion));
+ m_pendingTasks.append(createCallbackTask(&ThreadableWebSocketChannelClientWrapper::didCloseCallback, AllowCrossThreadAccess(this), unhandledBufferedAmount, closingHandshakeCompletion, code, reason));
if (!m_suspended)
processPendingTasks();
}
@@ -187,11 +187,11 @@ void ThreadableWebSocketChannelClientWrapper::didStartClosingHandshakeCallback(S
wrapper->m_client->didStartClosingHandshake();
}
-void ThreadableWebSocketChannelClientWrapper::didCloseCallback(ScriptExecutionContext* context, ThreadableWebSocketChannelClientWrapper* wrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion)
+void ThreadableWebSocketChannelClientWrapper::didCloseCallback(ScriptExecutionContext* context, ThreadableWebSocketChannelClientWrapper* wrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
ASSERT_UNUSED(context, !context);
if (wrapper->m_client)
- wrapper->m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion);
+ wrapper->m_client->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason);
}
} // namespace WebCore
diff --git a/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h b/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h
index b54aca0..bcea9d6 100644
--- a/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h
+++ b/Source/WebCore/websockets/ThreadableWebSocketChannelClientWrapper.h
@@ -73,7 +73,7 @@ public:
void didConnect();
void didReceiveMessage(const String& message);
void didStartClosingHandshake();
- void didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus);
+ void didClose(unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
void suspend();
void resume();
@@ -85,7 +85,7 @@ protected:
static void didConnectCallback(ScriptExecutionContext*, ThreadableWebSocketChannelClientWrapper*);
static void didReceiveMessageCallback(ScriptExecutionContext*, ThreadableWebSocketChannelClientWrapper*, const String& message);
static void didStartClosingHandshakeCallback(ScriptExecutionContext*, ThreadableWebSocketChannelClientWrapper*);
- static void didCloseCallback(ScriptExecutionContext*, ThreadableWebSocketChannelClientWrapper*, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus);
+ static void didCloseCallback(ScriptExecutionContext*, ThreadableWebSocketChannelClientWrapper*, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
WebSocketChannelClient* m_client;
bool m_syncMethodDone;
diff --git a/Source/WebCore/websockets/WebSocket.cpp b/Source/WebCore/websockets/WebSocket.cpp
index 1b0133e..f1797f0 100644
--- a/Source/WebCore/websockets/WebSocket.cpp
+++ b/Source/WebCore/websockets/WebSocket.cpp
@@ -378,7 +378,7 @@ void WebSocket::didConnect()
{
LOG(Network, "WebSocket %p didConnect", this);
if (m_state != CONNECTING) {
- didClose(0, ClosingHandshakeIncomplete);
+ didClose(0, ClosingHandshakeIncomplete, WebSocketChannel::CloseEventCodeAbnormalClosure, "");
return;
}
ASSERT(scriptExecutionContext());
@@ -413,7 +413,7 @@ void WebSocket::didStartClosingHandshake()
m_state = CLOSING;
}
-void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion)
+void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
LOG(Network, "WebSocket %p didClose", this);
if (!m_channel)
@@ -423,7 +423,7 @@ void WebSocket::didClose(unsigned long unhandledBufferedAmount, ClosingHandshake
m_bufferedAmountAfterClose += unhandledBufferedAmount;
ASSERT(scriptExecutionContext());
RefPtr<CloseEvent> event = CloseEvent::create();
- event->initCloseEvent(eventNames().closeEvent, false, false, wasClean);
+ event->initCloseEvent(eventNames().closeEvent, false, false, wasClean, code, reason);
dispatchEvent(event);
if (m_channel) {
m_channel->disconnect();
diff --git a/Source/WebCore/websockets/WebSocket.h b/Source/WebCore/websockets/WebSocket.h
index 2f71b31..2712541 100644
--- a/Source/WebCore/websockets/WebSocket.h
+++ b/Source/WebCore/websockets/WebSocket.h
@@ -102,7 +102,7 @@ namespace WebCore {
virtual void didReceiveMessage(const String& message);
virtual void didReceiveMessageError();
virtual void didStartClosingHandshake();
- virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus);
+ virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
private:
WebSocket(ScriptExecutionContext*);
diff --git a/Source/WebCore/websockets/WebSocketChannel.cpp b/Source/WebCore/websockets/WebSocketChannel.cpp
index 9afc74c..ee868ff 100644
--- a/Source/WebCore/websockets/WebSocketChannel.cpp
+++ b/Source/WebCore/websockets/WebSocketChannel.cpp
@@ -98,6 +98,7 @@ WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha
, m_identifier(0)
, m_useHixie76Protocol(true)
, m_hasContinuousFrame(false)
+ , m_closeEventCode(CloseEventCodeAbnormalClosure)
{
ASSERT(m_context->isDocument());
Document* document = static_cast<Document*>(m_context);
@@ -246,7 +247,7 @@ void WebSocketChannel::didCloseSocketStream(SocketStreamHandle* handle)
m_context = 0;
m_handle = 0;
if (client)
- client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete);
+ client->didClose(m_unhandledBufferedAmount, m_receivedClosingHandshake ? WebSocketChannelClient::ClosingHandshakeComplete : WebSocketChannelClient::ClosingHandshakeIncomplete, m_closeEventCode, m_closeEventReason);
}
deref();
}
@@ -623,7 +624,16 @@ bool WebSocketChannel::processFrame()
break;
case OpCodeClose:
- // FIXME: Handle payload.
+ if (frame.payloadLength >= 2) {
+ unsigned char highByte = static_cast<unsigned char>(frame.payload[0]);
+ unsigned char lowByte = static_cast<unsigned char>(frame.payload[1]);
+ m_closeEventCode = highByte << 8 | lowByte;
+ } else
+ m_closeEventCode = CloseEventCodeNoStatusRcvd;
+ if (frame.payloadLength >= 3)
+ m_closeEventReason = String::fromUTF8(&frame.payload[2], frame.payloadLength - 2);
+ else
+ m_closeEventReason = "";
skipBuffer(frame.frameEnd - m_buffer);
m_receivedClosingHandshake = true;
startClosingHandshake();
diff --git a/Source/WebCore/websockets/WebSocketChannel.h b/Source/WebCore/websockets/WebSocketChannel.h
index 0fd96f1..3884fcf 100644
--- a/Source/WebCore/websockets/WebSocketChannel.h
+++ b/Source/WebCore/websockets/WebSocketChannel.h
@@ -74,6 +74,17 @@ namespace WebCore {
virtual void didReceiveAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&);
virtual void didCancelAuthenticationChallenge(SocketStreamHandle*, const AuthenticationChallenge&);
+ enum CloseEventCode {
+ CloseEventCodeNormalClosure = 1000,
+ CloseEventCodeGoingAway = 1001,
+ CloseEventCodeProtocolError = 1002,
+ CloseEventCodeUnsupportedData = 1003,
+ CloseEventCodeFrameTooLarge = 1004,
+ CloseEventCodeNoStatusRcvd = 1005,
+ CloseEventCodeAbnormalClosure = 1006,
+ CloseEventCodeInvalidUTF8 = 1007
+ };
+
using RefCounted<WebSocketChannel>::ref;
using RefCounted<WebSocketChannel>::deref;
@@ -154,6 +165,8 @@ namespace WebCore {
bool m_hasContinuousFrame;
OpCode m_continuousFrameOpCode;
Vector<char> m_continuousFrameData;
+ unsigned short m_closeEventCode;
+ String m_closeEventReason;
};
} // namespace WebCore
diff --git a/Source/WebCore/websockets/WebSocketChannelClient.h b/Source/WebCore/websockets/WebSocketChannelClient.h
index 38bd17d..c38b05c 100644
--- a/Source/WebCore/websockets/WebSocketChannelClient.h
+++ b/Source/WebCore/websockets/WebSocketChannelClient.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 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
@@ -46,7 +46,7 @@ namespace WebCore {
ClosingHandshakeIncomplete,
ClosingHandshakeComplete
};
- virtual void didClose(unsigned long /* unhandledBufferedAmount */, ClosingHandshakeCompletionStatus) { }
+ virtual void didClose(unsigned long /* unhandledBufferedAmount */, ClosingHandshakeCompletionStatus, unsigned short /* code */, const String& /* reason */) { }
protected:
WebSocketChannelClient() { }
diff --git a/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp b/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp
index 334e752..9dab812 100644
--- a/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp
+++ b/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 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
@@ -265,17 +265,17 @@ void WorkerThreadableWebSocketChannel::Peer::didStartClosingHandshake()
m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidStartClosingHandshake, m_workerClientWrapper), m_taskMode);
}
-static void workerContextDidClose(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion)
+static void workerContextDidClose(ScriptExecutionContext* context, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, unsigned long unhandledBufferedAmount, WebSocketChannelClient::ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
ASSERT_UNUSED(context, context->isWorkerContext());
- workerClientWrapper->didClose(unhandledBufferedAmount, closingHandshakeCompletion);
+ workerClientWrapper->didClose(unhandledBufferedAmount, closingHandshakeCompletion, code, reason);
}
-void WorkerThreadableWebSocketChannel::Peer::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion)
+void WorkerThreadableWebSocketChannel::Peer::didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus closingHandshakeCompletion, unsigned short code, const String& reason)
{
ASSERT(isMainThread());
m_mainWebSocketChannel = 0;
- m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidClose, m_workerClientWrapper, unhandledBufferedAmount, closingHandshakeCompletion), m_taskMode);
+ m_loaderProxy.postTaskForModeToWorkerContext(createCallbackTask(&workerContextDidClose, m_workerClientWrapper, unhandledBufferedAmount, closingHandshakeCompletion, code, reason), m_taskMode);
}
void WorkerThreadableWebSocketChannel::Bridge::setWebSocketChannel(ScriptExecutionContext* context, Bridge* thisPtr, Peer* peer, PassRefPtr<ThreadableWebSocketChannelClientWrapper> workerClientWrapper, bool useHixie76Protocol)
diff --git a/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h b/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h
index 4400370..0dc38c3 100644
--- a/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h
+++ b/Source/WebCore/websockets/WorkerThreadableWebSocketChannel.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2011 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
@@ -103,7 +103,7 @@ private:
virtual void didConnect();
virtual void didReceiveMessage(const String& message);
virtual void didStartClosingHandshake();
- virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus);
+ virtual void didClose(unsigned long unhandledBufferedAmount, ClosingHandshakeCompletionStatus, unsigned short code, const String& reason);
private:
Peer(PassRefPtr<ThreadableWebSocketChannelClientWrapper>, WorkerLoaderProxy&, ScriptExecutionContext*, const String& taskMode);