| Differences between
and this patch
- a/LayoutTests/ChangeLog +58 lines
Lines 1-3 a/LayoutTests/ChangeLog_sec1
1
2011-07-18  Yuta Kitamura  <yutak@chromium.org>
2
3
        WebSocket: Implement hybi framing
4
        https://bugs.webkit.org/show_bug.cgi?id=64522
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Fix existing tests so they match the new frame format, and add tests for the new frame types
9
        and error conditions related to the new frame format.
10
11
        Unskip hybi tests on mac, win and chromium. Other ports (wk2, qt and gtk) still skip these tests
12
        because they do not support changing the value of "WebKitHixie76WebSocketProtocolEnabled"
13
        preference key via layoutTestController.overridePreferences() yet.
14
15
        * http/tests/websocket/tests/hybi/broken-utf8-expected.txt: Added.
16
        * http/tests/websocket/tests/hybi/broken-utf8.html: Added.
17
        * http/tests/websocket/tests/hybi/broken-utf8_wsh.py: Added.
18
        * http/tests/websocket/tests/hybi/client-close-expected.txt:
19
        * http/tests/websocket/tests/hybi/client-close.html:
20
        The format of a close frame has been changed. Currently, we do not include any payload
21
        in a close frame, thus it must start with "\x88\x80" (see section 4.1 of hybi-10
22
        specification for more details).
23
        * http/tests/websocket/tests/hybi/client-close_wsh.py:
24
        * http/tests/websocket/tests/hybi/fragmented-control-frame-expected.txt: Added.
25
        * http/tests/websocket/tests/hybi/fragmented-control-frame.html: Added.
26
        * http/tests/websocket/tests/hybi/fragmented-control-frame_wsh.py: Added.
27
        * http/tests/websocket/tests/hybi/fragmented-frames-expected.txt: Added.
28
        * http/tests/websocket/tests/hybi/fragmented-frames.html: Added.
29
        * http/tests/websocket/tests/hybi/fragmented-frames_wsh.py: Added.
30
        * http/tests/websocket/tests/hybi/interleaved-fragments-expected.txt: Added.
31
        * http/tests/websocket/tests/hybi/interleaved-fragments.html: Added.
32
        * http/tests/websocket/tests/hybi/interleaved-fragments_wsh.py: Added.
33
        * http/tests/websocket/tests/hybi/long-control-frame-expected.txt: Added.
34
        * http/tests/websocket/tests/hybi/long-control-frame.html: Added.
35
        * http/tests/websocket/tests/hybi/long-control-frame_wsh.py: Added.
36
        * http/tests/websocket/tests/hybi/masked-frames-expected.txt: Added.
37
        * http/tests/websocket/tests/hybi/masked-frames.html: Added.
38
        * http/tests/websocket/tests/hybi/masked-frames_wsh.py: Added.
39
        * http/tests/websocket/tests/hybi/pong-expected.txt: Added.
40
        * http/tests/websocket/tests/hybi/pong.html: Added.
41
        * http/tests/websocket/tests/hybi/pong_wsh.py: Added.
42
        * http/tests/websocket/tests/hybi/reserved-bits-expected.txt: Added.
43
        * http/tests/websocket/tests/hybi/reserved-bits.html: Added.
44
        * http/tests/websocket/tests/hybi/reserved-bits_wsh.py: Added.
45
        * http/tests/websocket/tests/hybi/reserved-opcodes-expected.txt: Added.
46
        * http/tests/websocket/tests/hybi/reserved-opcodes.html: Added.
47
        * http/tests/websocket/tests/hybi/reserved-opcodes_wsh.py: Added.
48
        * http/tests/websocket/tests/hybi/send2_wsh.py:
49
        Send two text frames at once.
50
        * http/tests/websocket/tests/hybi/too-long-payload-expected.txt: Added.
51
        * http/tests/websocket/tests/hybi/too-long-payload.html: Added.
52
        * http/tests/websocket/tests/hybi/too-long-payload_wsh.py: Added.
53
        * platform/chromium/test_expectations.txt:
54
        Derive test expectations of hixie76 tests, because these tests are likely to behave
55
        the same way as hixie76 tests. Will be checked later whether they really do.
56
        * platform/mac/Skipped:
57
        * platform/win/Skipped:
58
1
2011-07-18  Stephen White  <senorblanco@chromium.org>
59
2011-07-18  Stephen White  <senorblanco@chromium.org>
2
60
3
        Unreviewed; updated chromium test expectations.
61
        Unreviewed; updated chromium test expectations.
- a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8-expected.txt +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Could not decode a text frame as UTF-8.
2
Test whether WebSocket aborts the connection when it receives a text frame containing broken UTF-8 data.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
onopen() was called.
7
onclose() was called.
8
PASS closeEvent.wasClean is false
9
PASS successfullyParsed is true
10
11
TEST COMPLETE
12
- a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8.html +43 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket aborts the connection when it receives a text frame containing broken UTF-8 data.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/broken-utf8");
18
var closeEvent;
19
20
ws.onopen = function()
21
{
22
    debug("onopen() was called.");
23
};
24
25
ws.onmessage = function(event)
26
{
27
    var message = event.data;
28
    testFailed("onmessage() was called. (message = \"" + message + "\")");
29
};
30
31
ws.onclose = function(event)
32
{
33
    debug("onclose() was called.");
34
    closeEvent = event;
35
    shouldBeFalse("closeEvent.wasClean");
36
    finishJSTest();
37
};
38
39
var successfullyParsed = true;
40
</script>
41
<script src="../../../../js-test-resources/js-test-post.js"></script>
42
</body>
43
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8_wsh.py +11 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/broken-utf8_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import stream
3
4
5
def web_socket_do_extra_handshake(request):
6
    pass
7
8
9
def web_socket_transfer_data(request):
10
    payload = 'This text should be ignored. \xff' # '\xff' will never appear in UTF-8 encoded data.
11
    request.connection.write(stream.create_header(common.OPCODE_TEXT, len(payload), 1, 0, 0, 0, 0) + payload)
- a/LayoutTests/http/tests/websocket/tests/hybi/client-close-expected.txt -2 / +2 lines
Lines 3-11 WebSocket: Test client-initiated close. a/LayoutTests/http/tests/websocket/tests/hybi/client-close-expected.txt_sec1
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
4
5
Connected
5
Connected
6
Received: close_frame='\xff\x00'
6
Received: close_frame[:2]='\x88\x80'
7
Closed
7
Closed
8
PASS receivedMessage is "close_frame='\\xff\\x00'"
8
PASS receivedMessage is "close_frame[:2]='\\x88\\x80'"
9
PASS closeEvent.wasClean is true
9
PASS closeEvent.wasClean is true
10
PASS successfullyParsed is true
10
PASS successfullyParsed is true
11
11
- a/LayoutTests/http/tests/websocket/tests/hybi/client-close.html -1 / +1 lines
Lines 34-40 ws.onclose = function(event) a/LayoutTests/http/tests/websocket/tests/hybi/client-close.html_sec1
34
{
34
{
35
    debug("Closed");
35
    debug("Closed");
36
    closeEvent = event;
36
    closeEvent = event;
37
    shouldBeEqualToString("receivedMessage", "close_frame='\\xff\\x00'");
37
    shouldBeEqualToString("receivedMessage", "close_frame[:2]='\\x88\\x80'");
38
    shouldBeTrue("closeEvent.wasClean");
38
    shouldBeTrue("closeEvent.wasClean");
39
    finishJSTest();
39
    finishJSTest();
40
};
40
};
- a/LayoutTests/http/tests/websocket/tests/hybi/client-close_wsh.py -4 / +5 lines
Lines 7-22 def web_socket_do_extra_handshake(request): a/LayoutTests/http/tests/websocket/tests/hybi/client-close_wsh.py_sec1
7
7
8
def web_socket_transfer_data(request):
8
def web_socket_transfer_data(request):
9
    # Wait for a close frame sent from the client.
9
    # Wait for a close frame sent from the client.
10
    close_frame = request.ws_stream.receive_bytes(2)
10
    close_frame = request.ws_stream.receive_bytes(6)
11
11
12
    # Tell the client what we have received.
12
    # Send only first two bytes of the received frame. The remaining four bytes are
13
    msgutil.send_message(request, 'close_frame=%r' % close_frame)
13
    # "masking key", which changes every time the test runs.
14
    msgutil.send_message(request, 'close_frame[:2]=%r' % close_frame[:2])
14
15
15
    # If the following assertion fails, AssertionError will be raised,
16
    # If the following assertion fails, AssertionError will be raised,
16
    # which will prevent pywebsocket from sending a close frame.
17
    # which will prevent pywebsocket from sending a close frame.
17
    # In this case, the client will fail to finish closing handshake, thus
18
    # In this case, the client will fail to finish closing handshake, thus
18
    # closeEvent.wasClean will become false.
19
    # closeEvent.wasClean will become false.
19
    assert close_frame == '\xff\x00'
20
    assert close_frame[:2] == '\x88\x80'
20
21
21
    # Pretend we have received a close frame from the client.
22
    # Pretend we have received a close frame from the client.
22
    # After this function exits, pywebsocket will send a close frame automatically.
23
    # After this function exits, pywebsocket will send a close frame automatically.
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame-expected.txt +11 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Received fragmented control frame: opcode = 9
2
Test whether WebSocket rejects a fragmented control frame and aborts the connection.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
onopen() was called.
7
PASS closeEvent.wasClean is false
8
PASS successfullyParsed is true
9
10
TEST COMPLETE
11
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame.html +43 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket rejects a fragmented control frame and aborts the connection.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/fragmented-control-frame";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
21
ws.onopen = function()
22
{
23
    debug("onopen() was called.");
24
};
25
26
ws.onmessage = function(event)
27
{
28
    var message = event.data;
29
    testFailed("onmessage() was called. (message = \"" + message + "\")");
30
};
31
32
ws.onclose = function(event)
33
{
34
    closeEvent = event;
35
    shouldBeFalse("closeEvent.wasClean");
36
    finishJSTest();
37
};
38
39
var successfullyParsed = true;
40
</script>
41
<script src="../../../../js-test-resources/js-test-post.js"></script>
42
</body>
43
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame_wsh.py +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-control-frame_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import msgutil
3
from mod_pywebsocket import stream
4
5
6
def web_socket_do_extra_handshake(request):
7
    pass
8
9
10
def web_socket_transfer_data(request):
11
    # Fragmented control frame is prohibited. The client must abort the connection.
12
    request.connection.write(stream.create_text_frame('This message should be ignored.', opcode=common.OPCODE_PING, fin=0))
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames-expected.txt +17 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames-expected.txt_sec1
1
Receive fragmented WebSocket frames.
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
onopen() was called.
6
onmessage() was called. (message = "First message")
7
onmessage() was called. (message = "Second message")
8
onmessage() was called. (message = "Third message")
9
PASS closeEvent.wasClean is true
10
PASS actualMessages.length === expectedMessages.length is true
11
PASS actualMessages[0] is "First message"
12
PASS actualMessages[1] is "Second message"
13
PASS actualMessages[2] is "Third message"
14
PASS successfullyParsed is true
15
16
TEST COMPLETE
17
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames.html +50 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Receive fragmented WebSocket frames.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/fragmented-frames";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
var expectedMessages = ["First message", "Second message", "Third message"];
21
var actualMessages = [];
22
23
ws.onopen = function()
24
{
25
    debug("onopen() was called.");
26
    ws.close();
27
};
28
29
ws.onmessage = function(event)
30
{
31
    var message = event.data;
32
    debug("onmessage() was called. (message = \"" + message + "\")");
33
    actualMessages.push(message);
34
};
35
36
ws.onclose = function(event)
37
{
38
    closeEvent = event;
39
    shouldBeTrue("closeEvent.wasClean");
40
    shouldBeTrue("actualMessages.length === expectedMessages.length");
41
    for (var i = 0; i < expectedMessages.length; ++i)
42
        shouldBeEqualToString("actualMessages[" + i + "]", expectedMessages[i]);
43
    finishJSTest();
44
};
45
46
var successfullyParsed = true;
47
</script>
48
<script src="../../../../js-test-resources/js-test-post.js"></script>
49
</body>
50
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames_wsh.py +34 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/fragmented-frames_wsh.py_sec1
1
from mod_pywebsocket import msgutil
2
3
4
def web_socket_do_extra_handshake(request):
5
    pass
6
7
8
def web_socket_transfer_data(request):
9
    # send_message's third argument corresponds to "fin" bit;
10
    # it is set to True if this frame is the final fragment of a message.
11
    msgutil.send_message(request, 'First ', False)
12
    msgutil.send_message(request, 'message', True)
13
14
    # Empty fragment is allowed.
15
    msgutil.send_message(request, '', False)
16
    msgutil.send_message(request, 'Second ', False)
17
    msgutil.send_message(request, '', False)
18
    msgutil.send_message(request, 'message', False)
19
    msgutil.send_message(request, '', True)
20
21
    # Fragment aggressively.
22
    msgutil.send_message(request, 'T', False)
23
    msgutil.send_message(request, 'h', False)
24
    msgutil.send_message(request, 'i', False)
25
    msgutil.send_message(request, 'r', False)
26
    msgutil.send_message(request, 'd', False)
27
    msgutil.send_message(request, ' ', False)
28
    msgutil.send_message(request, 'm', False)
29
    msgutil.send_message(request, 'e', False)
30
    msgutil.send_message(request, 's', False)
31
    msgutil.send_message(request, 's', False)
32
    msgutil.send_message(request, 'a', False)
33
    msgutil.send_message(request, 'g', False)
34
    msgutil.send_message(request, 'e', True)
- a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments-expected.txt +11 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Received new data frame but previous continuous frame is unfinished.
2
Test whether WebSocket rejects interleaved fragmented frames.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
onopen() was called.
7
PASS closeEvent.wasClean is false
8
PASS successfullyParsed is true
9
10
TEST COMPLETE
11
- a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments.html +43 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket rejects interleaved fragmented frames.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/interleaved-fragments";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
21
ws.onopen = function()
22
{
23
    debug("onopen() was called.");
24
};
25
26
ws.onmessage = function(event)
27
{
28
    var message = event.data;
29
    testFailed("onmessage() was called. (message = \"" + message + "\")");
30
};
31
32
ws.onclose = function(event)
33
{
34
    closeEvent = event;
35
    shouldBeFalse("closeEvent.wasClean");
36
    finishJSTest();
37
};
38
39
var successfullyParsed = true;
40
</script>
41
<script src="../../../../js-test-resources/js-test-post.js"></script>
42
</body>
43
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments_wsh.py +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/interleaved-fragments_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import stream
3
4
5
def web_socket_do_extra_handshake(request):
6
    pass
7
8
9
def web_socket_transfer_data(request):
10
    # A new frame is arrived before the previous fragmented frame has finished.
11
    request.connection.write(stream.create_text_frame('This message ', opcode=common.OPCODE_TEXT, fin=0))
12
    request.connection.write(stream.create_text_frame('should be ignored.', opcode=common.OPCODE_TEXT, fin=1)) # Not OPCODE_CONTINUATION.
- a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame-expected.txt +11 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Received control frame having too long payload: 126 bytes
2
Test whether WebSocket rejects control frames longer than 125 bytes.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
onopen() was called.
7
PASS closeEvent.wasClean is false
8
PASS successfullyParsed is true
9
10
TEST COMPLETE
11
- a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame.html +38 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket rejects control frames longer than 125 bytes.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/long-control-frame";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
var message;
21
22
ws.onopen = function()
23
{
24
    debug("onopen() was called.");
25
};
26
27
ws.onclose = function(event)
28
{
29
    closeEvent = event;
30
    shouldBeFalse("closeEvent.wasClean");
31
    finishJSTest();
32
};
33
34
var successfullyParsed = true;
35
</script>
36
<script src="../../../../js-test-resources/js-test-post.js"></script>
37
</body>
38
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame_wsh.py +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/long-control-frame_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import stream
3
4
5
def web_socket_do_extra_handshake(request):
6
    pass
7
8
9
def web_socket_transfer_data(request):
10
    # All control frames must have a payload length of 125 bytes or less.
11
    message = 'X' * 126
12
    request.connection.write(stream.create_text_frame(message, opcode=common.OPCODE_PING, fin=1))
- a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames-expected.txt +18 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames-expected.txt_sec1
1
Receive masked WebSocket frames.
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
onopen() was called.
6
onmessage() was called. (message = "First message")
7
onmessage() was called. (message = "Fragmented message")
8
onmessage() was called. (message = "")
9
onmessage() was called. (message = "END")
10
PASS actualMessages.length === expectedMessages.length is true
11
PASS actualMessages[0] is "First message"
12
PASS actualMessages[1] is "Fragmented message"
13
PASS actualMessages[2] is ""
14
PASS closeEvent.wasClean is true
15
PASS successfullyParsed is true
16
17
TEST COMPLETE
18
- a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames.html +54 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Receive masked WebSocket frames.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/masked-frames";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
var expectedMessages = ["First message", "Fragmented message", ""];
21
var actualMessages = [];
22
23
ws.onopen = function()
24
{
25
    debug("onopen() was called.");
26
    ws.close();
27
};
28
29
ws.onmessage = function(event)
30
{
31
    var message = event.data;
32
    debug("onmessage() was called. (message = \"" + message + "\")");
33
    if (message === "END") {
34
        ws.close();
35
        return;
36
    }
37
    actualMessages.push(message);
38
};
39
40
ws.onclose = function(event)
41
{
42
    closeEvent = event;
43
    shouldBeTrue("actualMessages.length === expectedMessages.length");
44
    for (var i = 0; i < expectedMessages.length; ++i)
45
        shouldBeEqualToString("actualMessages[" + i + "]", expectedMessages[i]);
46
    shouldBeTrue("closeEvent.wasClean");
47
    finishJSTest();
48
};
49
50
var successfullyParsed = true;
51
</script>
52
<script src="../../../../js-test-resources/js-test-post.js"></script>
53
</body>
54
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames_wsh.py +34 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/masked-frames_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import stream
3
from mod_pywebsocket import msgutil
4
5
6
def web_socket_do_extra_handshake(request):
7
    pass
8
9
10
def web_socket_transfer_data(request):
11
    # pywebsocket does not mask message by default. We need to build a frame manually to mask it.
12
    request.connection.write(stream.create_text_frame('First message', mask=True))
13
14
    request.connection.write(stream.create_text_frame('Fragmented ', opcode=common.OPCODE_TEXT, fin=0, mask=True))
15
    request.connection.write(stream.create_text_frame('message', opcode=common.OPCODE_CONTINUATION, fin=1, mask=True))
16
17
    request.connection.write(stream.create_text_frame('', mask=True))
18
19
    msgutil.send_message(request, 'END')
20
21
    # Wait for the client to start closing handshake.
22
    # To receive a close frame, we must use an internal method of request.ws_stream.
23
    opcode, payload, final, reserved1, reserved2, reserved3 = request.ws_stream._receive_frame()
24
    assert opcode == common.OPCODE_CLOSE
25
    assert final
26
    assert not reserved1
27
    assert not reserved2
28
    assert not reserved3
29
30
    # Send a masked close frame. Clients should be able to handle this frame and
31
    # the WebSocket object should be closed cleanly.
32
    request.connection.write(stream.create_close_frame('', mask=True))
33
34
    raise Exception('Abort the connection') # Prevents pywebsocket from starting its own closing handshake.
- a/LayoutTests/http/tests/websocket/tests/hybi/pong-expected.txt +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/pong-expected.txt_sec1
1
Test whether WebSocket correctly responds to a ping message sent from the server.
2
3
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
4
5
onopen() was called.
6
onmessage() was called. (message = "PASS")
7
PASS message is "PASS"
8
PASS closeEvent.wasClean is true
9
PASS successfullyParsed is true
10
11
TEST COMPLETE
12
- a/LayoutTests/http/tests/websocket/tests/hybi/pong.html +45 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/pong.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket correctly responds to a ping message sent from the server.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var url = "ws://localhost:8880/websocket/tests/hybi/pong";
18
var ws = new WebSocket(url);
19
var closeEvent;
20
var message;
21
22
ws.onopen = function()
23
{
24
    debug("onopen() was called.");
25
};
26
27
ws.onmessage = function(event)
28
{
29
    message = event.data;
30
    debug("onmessage() was called. (message = \"" + message + "\")");
31
    shouldBeEqualToString("message", "PASS");
32
};
33
34
ws.onclose = function(event)
35
{
36
    closeEvent = event;
37
    shouldBeTrue("closeEvent.wasClean");
38
    finishJSTest();
39
};
40
41
var successfullyParsed = true;
42
</script>
43
<script src="../../../../js-test-resources/js-test-post.js"></script>
44
</body>
45
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/pong_wsh.py +19 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/pong_wsh.py_sec1
1
from mod_pywebsocket import common
2
from mod_pywebsocket import msgutil
3
4
5
def web_socket_do_extra_handshake(request):
6
    pass
7
8
9
def web_socket_transfer_data(request):
10
    msgutil.send_ping(request, 'Hello, world!')
11
12
    # We need to use an internal function to detect a pong frame from the client.
13
    opcode, payload, final, reserved1, reserved2, reserved3 = request.ws_stream._receive_frame()
14
    if opcode == common.OPCODE_PONG and payload == 'Hello, world!' and final and not reserved1 and not reserved2 and not reserved3:
15
        msgutil.send_message(request, 'PASS')
16
    else:
17
        msgutil.send_message(request,
18
                             'FAIL: Received unexpected frame: opcode = %r, payload = %r, final = %r, reserved1 = %r, reserved2 = %r, reserved3 = %r' %
19
                             (opcode, payload, final, reserved1, reserved2, reserved3))
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits-expected.txt +23 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: One or more reserved bits are on: reserved1 = 1, reserved2 = 0, reserved3 = 0
2
CONSOLE MESSAGE: line 0: One or more reserved bits are on: reserved1 = 0, reserved2 = 1, reserved3 = 0
3
CONSOLE MESSAGE: line 0: One or more reserved bits are on: reserved1 = 0, reserved2 = 0, reserved3 = 1
4
Test whether WebSocket rejects frames whose reserved bit is on.
5
6
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
7
8
Bit 1: Test started.
9
onopen() was called.
10
onclose() was called.
11
PASS closeEvent.wasClean is false
12
Bit 2: Test started.
13
onopen() was called.
14
onclose() was called.
15
PASS closeEvent.wasClean is false
16
Bit 3: Test started.
17
onopen() was called.
18
onclose() was called.
19
PASS closeEvent.wasClean is false
20
PASS successfullyParsed is true
21
22
TEST COMPLETE
23
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits.html +56 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script>
11
description("Test whether WebSocket rejects frames whose reserved bit is on.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var closeEvent;
18
19
// bitNumber must be 1, 2, or 3.
20
function doTest(bitNumber)
21
{
22
    var url = "ws://localhost:8880/websocket/tests/hybi/reserved-bits?bit=" + bitNumber;
23
    var ws = new WebSocket(url);
24
25
    debug("Bit " + bitNumber + ": Test started.");
26
27
    ws.onopen = function()
28
    {
29
        debug("onopen() was called.");
30
    };
31
32
    ws.onmessage = function(event)
33
    {
34
        var message = event.data;
35
        testFailed("onmessage() was called. (message = \"" + message + "\")");
36
    };
37
38
    ws.onclose = function(event)
39
    {
40
        debug("onclose() was called.");
41
        closeEvent = event;
42
        shouldBeFalse("closeEvent.wasClean");
43
        if (bitNumber === 3)
44
            finishJSTest();
45
        else
46
            doTest(bitNumber + 1);
47
    };
48
}
49
50
doTest(1);
51
52
var successfullyParsed = true;
53
</script>
54
<script src="../../../../js-test-resources/js-test-post.js"></script>
55
</body>
56
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits_wsh.py +26 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-bits_wsh.py_sec1
1
import re
2
from mod_pywebsocket import common
3
from mod_pywebsocket import stream
4
5
6
def web_socket_do_extra_handshake(request):
7
    pass
8
9
10
def web_socket_transfer_data(request):
11
    match = re.search(r'\?bit=(\d+)$', request.ws_resource)
12
    if match is None:
13
        msgutil.send_message(request, 'FAIL: Query value is incorrect or missing')
14
        return
15
16
    bit = int(match.group(1))
17
    message = "This message should be ignored."
18
    if bit == 1:
19
        frame = stream.create_header(common.OPCODE_TEXT, len(message), 1, 1, 0, 0, 0) + message
20
    elif bit == 2:
21
        frame = stream.create_header(common.OPCODE_TEXT, len(message), 1, 0, 1, 0, 0) + message
22
    elif bit == 3:
23
        frame = stream.create_header(common.OPCODE_TEXT, len(message), 1, 0, 0, 1, 0) + message
24
    else:
25
        frame = stream.create_text_frame('FAIL: Invalid bit number: %d' % bit)
26
    request.connection.write(frame)
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes-expected.txt +58 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 3
2
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 4
3
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 5
4
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 6
5
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 7
6
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 11
7
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 12
8
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 13
9
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 14
10
CONSOLE MESSAGE: line 0: Unrecognized frame opcode: 15
11
Tests whether WebSocket ignores frames with reserved opcode.
12
13
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
14
15
Opcode 3: Test started.
16
onopen() was called.
17
onclose() was called.
18
PASS closeEvent.wasClean is false
19
Opcode 4: Test started.
20
onopen() was called.
21
onclose() was called.
22
PASS closeEvent.wasClean is false
23
Opcode 5: Test started.
24
onopen() was called.
25
onclose() was called.
26
PASS closeEvent.wasClean is false
27
Opcode 6: Test started.
28
onopen() was called.
29
onclose() was called.
30
PASS closeEvent.wasClean is false
31
Opcode 7: Test started.
32
onopen() was called.
33
onclose() was called.
34
PASS closeEvent.wasClean is false
35
Opcode 11: Test started.
36
onopen() was called.
37
onclose() was called.
38
PASS closeEvent.wasClean is false
39
Opcode 12: Test started.
40
onopen() was called.
41
onclose() was called.
42
PASS closeEvent.wasClean is false
43
Opcode 13: Test started.
44
onopen() was called.
45
onclose() was called.
46
PASS closeEvent.wasClean is false
47
Opcode 14: Test started.
48
onopen() was called.
49
onclose() was called.
50
PASS closeEvent.wasClean is false
51
Opcode 15: Test started.
52
onopen() was called.
53
onclose() was called.
54
PASS closeEvent.wasClean is false
55
PASS successfullyParsed is true
56
57
TEST COMPLETE
58
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes.html +61 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script type="text/javascript">
11
description("Tests whether WebSocket ignores frames with reserved opcode.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var closeEvent;
18
19
function doTest(opcode)
20
{
21
    if (opcode >= 0x10) {
22
        finishJSTest();
23
        return;
24
    }
25
    if (opcode == 0x0 || opcode == 0x1 || opcode == 0x2 || opcode == 0x8 || opcode == 0x9 || opcode == 0xA) {
26
        doTest(opcode + 1);
27
        return;
28
    }
29
30
    debug("Opcode " + opcode + ": Test started.");
31
32
    var url = "ws://localhost:8880/websocket/tests/hybi/reserved-opcodes?opcode=" + opcode;
33
    var ws = new WebSocket(url);
34
35
    ws.onopen = function()
36
    {
37
        debug("onopen() was called.");
38
    };
39
40
    ws.onmessage = function(event)
41
    {
42
        var message = event.data;
43
        testFailed("onmessage() was called. (message = \"" + message + "\")");
44
    };
45
46
    ws.onclose = function(event)
47
    {
48
        debug("onclose() was called.");
49
        closeEvent = event;
50
        shouldBeFalse("closeEvent.wasClean");
51
        doTest(opcode + 1);
52
    };
53
}
54
55
doTest(0);
56
57
var successfullyParsed = true;
58
</script>
59
<script src="../../../../js-test-resources/js-test-post.js"></script>
60
</body>
61
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes_wsh.py +19 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/reserved-opcodes_wsh.py_sec1
1
import re
2
from mod_pywebsocket import common
3
from mod_pywebsocket import stream
4
from mod_pywebsocket import msgutil
5
6
7
def web_socket_do_extra_handshake(request):
8
    pass
9
10
11
def web_socket_transfer_data(request):
12
    match = re.search(r'\?opcode=(\d+)$', request.ws_resource)
13
    if match is None:
14
        msgutil.send_message(request, 'FAIL: Query value is incorrect or missing')
15
        return
16
17
    opcode = int(match.group(1))
18
    payload = 'This text should be ignored. (opcode = %d)' % opcode
19
    request.connection.write(stream.create_header(opcode, len(payload), 1, 0, 0, 0, 0) + payload)
- a/LayoutTests/http/tests/websocket/tests/hybi/send2_wsh.py -2 / +4 lines
Lines 1-8 a/LayoutTests/http/tests/websocket/tests/hybi/send2_wsh.py_sec1
1
from mod_pywebsocket import stream
2
3
1
def web_socket_do_extra_handshake(request):
4
def web_socket_do_extra_handshake(request):
2
    pass # Always accept.
5
    pass # Always accept.
3
6
4
7
5
def web_socket_transfer_data(request):
8
def web_socket_transfer_data(request):
6
    # send 2 messages in one packet.
9
    # send 2 messages in one packet.
7
    request.connection.write("\x00" + "first message" + "\xff" +
10
    request.connection.write(stream.create_text_frame("first message") + stream.create_text_frame("second message"))
8
                             "\x00" + "second message" + "\xff")
- a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload-expected.txt +12 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload-expected.txt_sec1
1
CONSOLE MESSAGE: line 0: WebSocket frame length too large: 9223372036854775808 bytes
2
Tests whether WebSocket correctly aborts the connection when it receives a frame with too long payload.
3
4
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
5
6
onopen() was called.
7
onclose() was called.
8
PASS closeEvent.wasClean is false
9
PASS successfullyParsed is true
10
11
TEST COMPLETE
12
- a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload.html +43 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload.html_sec1
1
<!DOCTYPE HTML>
2
<html>
3
<head>
4
<link rel="stylesheet" href="../../../../js-test-resources/js-test-style.css">
5
<script src="../../../../js-test-resources/js-test-pre.js"></script>
6
</head>
7
<body>
8
<div id="description"></div>
9
<div id="console"></div>
10
<script type="text/javascript">
11
description("Tests whether WebSocket correctly aborts the connection when it receives a frame with too long payload.");
12
13
window.jsTestIsAsync = true;
14
if (window.layoutTestController)
15
    layoutTestController.overridePreference("WebKitHixie76WebSocketProtocolEnabled", 0);
16
17
var ws = new WebSocket("ws://127.0.0.1:8880/websocket/tests/hybi/too-long-payload");
18
var closeEvent;
19
20
ws.onopen = function()
21
{
22
    debug("onopen() was called.");
23
};
24
25
ws.onmessage = function(event)
26
{
27
    var message = event.data;
28
    testFailed("onmessage() was called. (message = \"" + message + "\")");
29
};
30
31
ws.onclose = function(event)
32
{
33
    debug("onclose() was called.");
34
    closeEvent = event;
35
    shouldBeFalse("closeEvent.wasClean");
36
    finishJSTest();
37
};
38
39
var successfullyParsed = true;
40
</script>
41
<script src="../../../../js-test-resources/js-test-post.js"></script>
42
</body>
43
</html>
- a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload_wsh.py +24 lines
Line 0 a/LayoutTests/http/tests/websocket/tests/hybi/too-long-payload_wsh.py_sec1
1
import struct
2
import time
3
from mod_pywebsocket import common
4
5
6
def web_socket_do_extra_handshake(request):
7
    pass
8
9
10
def web_socket_transfer_data(request):
11
    length = 0x8000000000000000
12
13
    # pywebsocket refuses to send a frame with too long payload.
14
    # Thus, we need to build a frame manually.
15
    header = chr(0x80 | common.OPCODE_TEXT) # 0x80 is for "fin" bit.
16
    header += chr(127)
17
    header += struct.pack('!Q', length)
18
    request.connection.write(header)
19
20
    # Send data indefinitely to simulate a real (broken) server sending a big frame.
21
    # A client should ignore these bytes and abort the connection.
22
    while True:
23
        request.connection.write('X' * 4096)
24
        time.sleep(1)
- a/LayoutTests/platform/chromium/test_expectations.txt -3 / +5 lines
Lines 46-51 BUGCR18702 WIN : http/tests/xmlhttprequest/supported-xml-content-types.html = PA a/LayoutTests/platform/chromium/test_expectations.txt_sec1
46
BUGCR36539 SLOW : http/tests/misc/uncacheable-script-repeated.html = PASS
46
BUGCR36539 SLOW : http/tests/misc/uncacheable-script-repeated.html = PASS
47
47
48
BUGCR32018 SLOW : http/tests/websocket/tests/hixie76/frame-lengths.html = PASS
48
BUGCR32018 SLOW : http/tests/websocket/tests/hixie76/frame-lengths.html = PASS
49
BUGCR32018 SLOW : http/tests/websocket/tests/hybi/frame-lengths.html = PASS
49
BUGCR69513 DEBUG SLOW : html5lib/webkit-resumer.html = PASS
50
BUGCR69513 DEBUG SLOW : html5lib/webkit-resumer.html = PASS
50
51
51
BUGWK55913 RELEASE SLOW : jquery/effects.html = PASS
52
BUGWK55913 RELEASE SLOW : jquery/effects.html = PASS
Lines 105-110 WONTFIX SKIP : http/tests/workers = PASS TIMEOUT FAIL a/LayoutTests/platform/chromium/test_expectations.txt_sec2
105
WONTFIX SKIP : http/tests/xmlhttprequest/workers = PASS TIMEOUT FAIL
106
WONTFIX SKIP : http/tests/xmlhttprequest/workers = PASS TIMEOUT FAIL
106
WONTFIX SKIP : http/tests/eventsource/workers = PASS TIMEOUT FAIL
107
WONTFIX SKIP : http/tests/eventsource/workers = PASS TIMEOUT FAIL
107
WONTFIX SKIP : http/tests/websocket/tests/hixie76/workers/ = PASS TIMEOUT FAIL
108
WONTFIX SKIP : http/tests/websocket/tests/hixie76/workers/ = PASS TIMEOUT FAIL
109
WONTFIX SKIP : http/tests/websocket/tests/hybi/workers/ = PASS TIMEOUT FAIL
108
WONTFIX SKIP : inspector/debugger/script-formatter.html = PASS TIMEOUT FAIL
110
WONTFIX SKIP : inspector/debugger/script-formatter.html = PASS TIMEOUT FAIL
109
111
110
// Page Cache - based tests. Chromium disables page cache because the WebKit page cache keeps previously
112
// Page Cache - based tests. Chromium disables page cache because the WebKit page cache keeps previously
Lines 161-169 WONTFIX SKIP : animations/animation-api-1.html = FAIL a/LayoutTests/platform/chromium/test_expectations.txt_sec3
161
// Unskip after implementing LayoutTestController::setDefersLoading and ::goBack.
163
// Unskip after implementing LayoutTestController::setDefersLoading and ::goBack.
162
BUGWK60877 SKIP : loader/navigation-while-deferring-loads.html = FAIL
164
BUGWK60877 SKIP : loader/navigation-while-deferring-loads.html = FAIL
163
165
164
// Skipped until new WebSocket protocol is implemented.
165
BUGWK50099 SKIP : http/tests/websocket/tests/hybi/ = PASS FAIL TIMEOUT
166
167
// CSS3 Selectors3 test suite
166
// CSS3 Selectors3 test suite
168
BUGCR89468 : css3/selectors3 = PASS FAIL
167
BUGCR89468 : css3/selectors3 = PASS FAIL
169
168
Lines 1726-1731 BUGCR31623 WIN : http/tests/appcache/remove-cache.html = PASS TEXT TIMEOUT a/LayoutTests/platform/chromium/test_expectations.txt_sec4
1726
1725
1727
// WebKit roll 52852 -> 52867
1726
// WebKit roll 52852 -> 52867
1728
BUGCR32018 DEBUG : http/tests/websocket/tests/hixie76/simple-stress.html = PASS TEXT TIMEOUT
1727
BUGCR32018 DEBUG : http/tests/websocket/tests/hixie76/simple-stress.html = PASS TEXT TIMEOUT
1728
BUGCR32018 DEBUG : http/tests/websocket/tests/hybi/simple-stress.html = PASS TEXT TIMEOUT
1729
1729
1730
// V8's implementation of getOwnPropertyNames has different results for built-in
1730
// V8's implementation of getOwnPropertyNames has different results for built-in
1731
// functions.
1731
// functions.
Lines 2805-2810 BUGCR73080 LINUX DEBUG : fast/forms/form-attribute-elements-order.html = PASS TI a/LayoutTests/platform/chromium/test_expectations.txt_sec5
2805
BUGCR73091 : animations/play-state-suspend.html = PASS TEXT
2805
BUGCR73091 : animations/play-state-suspend.html = PASS TEXT
2806
BUGCR73092 WIN : fast/dom/gc-11.html = PASS TEXT
2806
BUGCR73092 WIN : fast/dom/gc-11.html = PASS TEXT
2807
BUGCR73094 LINUX : http/tests/websocket/tests/hixie76/send-after-close-on-unload.html = PASS TIMEOUT
2807
BUGCR73094 LINUX : http/tests/websocket/tests/hixie76/send-after-close-on-unload.html = PASS TIMEOUT
2808
BUGCR73094 LINUX : http/tests/websocket/tests/hybi/send-after-close-on-unload.html = PASS TIMEOUT
2808
2809
2809
BUGV8_1168 : fast/js/mozilla/eval/exhaustive-fun-normalcaller-indirect-strictcode.html = TEXT
2810
BUGV8_1168 : fast/js/mozilla/eval/exhaustive-fun-normalcaller-indirect-strictcode.html = TEXT
2810
BUGV8_1168 : fast/js/mozilla/eval/exhaustive-fun-strictcaller-indirect-strictcode.html = TEXT
2811
BUGV8_1168 : fast/js/mozilla/eval/exhaustive-fun-strictcaller-indirect-strictcode.html = TEXT
Lines 3655-3660 BUGWK61664 LINUX : svg/zoom/page/relative-sized-document-scrollbars.svg = IMAGE a/LayoutTests/platform/chromium/test_expectations.txt_sec6
3655
BUGCR84317 DEBUG : svg/wicd/test-scalable-background-image1.xhtml = CRASH
3656
BUGCR84317 DEBUG : svg/wicd/test-scalable-background-image1.xhtml = CRASH
3656
3657
3657
BUGWK61767 WIN DEBUG : http/tests/websocket/tests/hixie76/client-close.html = PASS TEXT
3658
BUGWK61767 WIN DEBUG : http/tests/websocket/tests/hixie76/client-close.html = PASS TEXT
3659
BUGWK61767 WIN DEBUG : http/tests/websocket/tests/hybi/client-close.html = PASS TEXT
3658
3660
3659
BUGWK59782 WIN LINUX DEBUG : svg/dynamic-updates/SVGFEDropShadowElement-dom-dx-attr.html = TIMEOUT
3661
BUGWK59782 WIN LINUX DEBUG : svg/dynamic-updates/SVGFEDropShadowElement-dom-dx-attr.html = TIMEOUT
3660
BUGWK59782 WIN LINUX DEBUG : svg/dynamic-updates/SVGFEDropShadowElement-dom-dy-attr.html = TIMEOUT
3662
BUGWK59782 WIN LINUX DEBUG : svg/dynamic-updates/SVGFEDropShadowElement-dom-dy-attr.html = TIMEOUT
- a/LayoutTests/platform/mac/Skipped -3 lines
Lines 386-391 compositing/rtl/rtl-iframe-fixed-overflow-scrolled.html a/LayoutTests/platform/mac/Skipped_sec1
386
compositing/rtl/rtl-iframe-fixed-overflow.html
386
compositing/rtl/rtl-iframe-fixed-overflow.html
387
compositing/rtl/rtl-iframe-fixed.html
387
compositing/rtl/rtl-iframe-fixed.html
388
compositing/rtl/rtl-iframe-relative.html
388
compositing/rtl/rtl-iframe-relative.html
389
390
# Skipped until new WebSocket protocol is implemented. http://webkit.org/b/50099
391
http/tests/websocket/tests/hybi/
- a/LayoutTests/platform/win/Skipped -3 lines
Lines 1346-1353 fast/workers/worker-crash-with-invalid-location.html a/LayoutTests/platform/win/Skipped_sec1
1346
# Need to implement getFormValue().
1346
# Need to implement getFormValue().
1347
plugins/form-value.html
1347
plugins/form-value.html
1348
1348
1349
# Skipped until new WebSocket protocol is implemented. http://webkit.org/b/50099
1350
http/tests/websocket/tests/hybi/
1351
1352
# Needs generated results
1349
# Needs generated results
1353
css3/selectors3
1350
css3/selectors3
- a/Source/WebCore/ChangeLog +62 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2011-07-18  Yuta Kitamura  <yutak@chromium.org>
2
3
        WebSocket: Implement hybi framing
4
        https://bugs.webkit.org/show_bug.cgi?id=64522
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        Implement WebSocket framing protocol which is mainly described in
9
        <http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-4> and
10
        <http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-10#section-6>.
11
12
        Hybi protocol introduces a new frame format which is drastically different from
13
        the old one. Notable differences are:
14
        - Binary data support.
15
        - Fragmentation support: a single message can be fragmented to multiple frames.
16
        - Ping-pong support.
17
        - Masking: frame content of a client must be masked to prevent cross-protocol attacks.
18
19
        This patch covers the following features:
20
        - Send a pong frame when a ping frame is received.
21
        - Receive fragmented frames.
22
        - Receive masked frames. (Servers do not have to mask frames, but they may if they wish.)
23
24
        The following features are NOT implemented yet:
25
        - Send or receive binary messages.
26
        - Send a ping message.
27
        - Send fragmented frames. (It is unclear whether this is necessary.)
28
        - Rewrite the frame content by WebSocket protocol extensions (like frame compression).
29
30
        New tests: http/tests/websocket/tests/hybi/broken-utf8.html
31
                   http/tests/websocket/tests/hybi/fragmented-control-frame.html
32
                   http/tests/websocket/tests/hybi/fragmented-frames.html
33
                   http/tests/websocket/tests/hybi/interleaved-fragments.html
34
                   http/tests/websocket/tests/hybi/long-control-frame.html
35
                   http/tests/websocket/tests/hybi/masked-frames.html
36
                   http/tests/websocket/tests/hybi/pong.html
37
                   http/tests/websocket/tests/hybi/reserved-bits.html
38
                   http/tests/websocket/tests/hybi/reserved-opcodes.html
39
                   http/tests/websocket/tests/hybi/too-long-payload.html
40
41
        * websockets/WebSocketChannel.cpp:
42
        (WebCore::WebSocketChannel::WebSocketChannel):
43
        (WebCore::WebSocketChannel::send):
44
        The original content of send() was moved to a private method sendFrameHixie76().
45
        (WebCore::WebSocketChannel::fail):
46
        Stop handling incoming data after the WebSocket connection is failed.
47
        It was unclear to me whether we should do the same thing for hixie-76 connection;
48
        for now, I kept the original behavior.
49
        (WebCore::WebSocketChannel::processBuffer):
50
        (WebCore::WebSocketChannel::resumeTimerFired):
51
        (WebCore::WebSocketChannel::startClosingHandshake):
52
        (WebCore::WebSocketChannel::closingTimerFired):
53
        (WebCore::WebSocketChannel::parseFrame):
54
        (WebCore::WebSocketChannel::processFrame):
55
        (WebCore::WebSocketChannel::processFrameHixie76):
56
        (WebCore::WebSocketChannel::sendFrame):
57
        (WebCore::WebSocketChannel::sendFrameHixie76):
58
        * websockets/WebSocketChannel.h:
59
        (WebCore::WebSocketChannel::isNonControlOpCode):
60
        (WebCore::WebSocketChannel::isControlOpCode):
61
        (WebCore::WebSocketChannel::isReservedOpCode):
62
1
2011-07-18  Vsevolod Vlasov  <vsevik@chromium.org>
63
2011-07-18  Vsevolod Vlasov  <vsevik@chromium.org>
2
64
3
        Web Inspector: Web Inspector: provide unique identifiers for loaders
65
        Web Inspector: Web Inspector: provide unique identifiers for loaders
- a/Source/WebCore/websockets/WebSocketChannel.cpp -42 / +331 lines
Lines 48-64 a/Source/WebCore/websockets/WebSocketChannel.cpp_sec1
48
#include "WebSocketChannelClient.h"
48
#include "WebSocketChannelClient.h"
49
#include "WebSocketHandshake.h"
49
#include "WebSocketHandshake.h"
50
50
51
#include <wtf/text/CString.h>
51
#include <stdint.h>
52
#include <wtf/text/WTFString.h>
52
#include <wtf/CryptographicallyRandomNumber.h>
53
#include <wtf/text/StringHash.h>
54
#include <wtf/Deque.h>
53
#include <wtf/Deque.h>
55
#include <wtf/FastMalloc.h>
54
#include <wtf/FastMalloc.h>
56
#include <wtf/HashMap.h>
55
#include <wtf/HashMap.h>
56
#include <wtf/text/CString.h>
57
#include <wtf/text/StringHash.h>
58
#include <wtf/text/WTFString.h>
57
59
58
namespace WebCore {
60
namespace WebCore {
59
61
60
const double TCPMaximumSegmentLifetime = 2 * 60.0;
62
const double TCPMaximumSegmentLifetime = 2 * 60.0;
61
63
64
// Constants for hybi-10 frame format.
65
const unsigned char finalBit = 0x80;
66
const unsigned char reserved1Bit = 0x40;
67
const unsigned char reserved2Bit = 0x20;
68
const unsigned char reserved3Bit = 0x10;
69
const unsigned char opCodeMask = 0xF;
70
const unsigned char maskBit = 0x80;
71
const unsigned char payloadLengthMask = 0x7F;
72
const size_t maxPayloadLengthWithoutExtendedLengthField = 125;
73
const size_t payloadLengthWithTwoByteExtendedLengthField = 126;
74
const size_t payloadLengthWithEightByteExtendedLengthField = 127;
75
const size_t maskingKeyWidthInBytes = 4;
76
77
const WebSocketChannel::OpCode WebSocketChannel::OpCodeContinuation = 0x0;
78
const WebSocketChannel::OpCode WebSocketChannel::OpCodeText = 0x1;
79
const WebSocketChannel::OpCode WebSocketChannel::OpCodeBinary = 0x2;
80
const WebSocketChannel::OpCode WebSocketChannel::OpCodeClose = 0x8;
81
const WebSocketChannel::OpCode WebSocketChannel::OpCodePing = 0x9;
82
const WebSocketChannel::OpCode WebSocketChannel::OpCodePong = 0xA;
83
62
WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketChannelClient* client, const KURL& url, const String& protocol)
84
WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketChannelClient* client, const KURL& url, const String& protocol)
63
    : m_context(context)
85
    : m_context(context)
64
    , m_client(client)
86
    , m_client(client)
Lines 74-79 WebSocketChannel::WebSocketChannel(ScriptExecutionContext* context, WebSocketCha a/Source/WebCore/websockets/WebSocketChannel.cpp_sec2
74
    , m_unhandledBufferedAmount(0)
96
    , m_unhandledBufferedAmount(0)
75
    , m_identifier(0)
97
    , m_identifier(0)
76
    , m_useHixie76Protocol(true)
98
    , m_useHixie76Protocol(true)
99
    , m_hasContinuousFrame(false)
77
{
100
{
78
    ASSERT(m_context->isDocument());
101
    ASSERT(m_context->isDocument());
79
    Document* document = static_cast<Document*>(m_context);
102
    Document* document = static_cast<Document*>(m_context);
Lines 102-118 void WebSocketChannel::connect() a/Source/WebCore/websockets/WebSocketChannel.cpp_sec3
102
    m_handle = SocketStreamHandle::create(m_handshake->url(), this);
125
    m_handle = SocketStreamHandle::create(m_handshake->url(), this);
103
}
126
}
104
127
105
bool WebSocketChannel::send(const String& msg)
128
bool WebSocketChannel::send(const String& message)
106
{
129
{
107
    LOG(Network, "WebSocketChannel %p send %s", this, msg.utf8().data());
130
    LOG(Network, "WebSocketChannel %p send %s", this, message.utf8().data());
108
    ASSERT(m_handle);
131
    CString utf8 = message.utf8();
109
    ASSERT(!m_suspended);
132
    if (m_useHixie76Protocol)
110
    Vector<char> buf;
133
        return sendFrameHixie76(utf8.data(), utf8.length());
111
    buf.append('\0');  // frame type
134
    return sendFrame(OpCodeText, utf8.data(), utf8.length());
112
    CString utf8 = msg.utf8();
113
    buf.append(utf8.data(), utf8.length());
114
    buf.append('\xff');  // frame end
115
    return m_handle->send(buf.data(), buf.size());
116
}
135
}
117
136
118
unsigned long WebSocketChannel::bufferedAmount() const
137
unsigned long WebSocketChannel::bufferedAmount() const
Lines 140-145 void WebSocketChannel::fail(const String& reason) a/Source/WebCore/websockets/WebSocketChannel.cpp_sec4
140
    ASSERT(!m_suspended);
159
    ASSERT(!m_suspended);
141
    if (m_context)
160
    if (m_context)
142
        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, reason, 0, m_handshake->clientOrigin(), 0);
161
        m_context->addMessage(JSMessageSource, LogMessageType, ErrorMessageLevel, reason, 0, m_handshake->clientOrigin(), 0);
162
    if (!m_useHixie76Protocol) {
163
        // Hybi-10 specification explicitly states we must not continue to handle incoming data
164
        // once the WebSocket connection is failed (section 7.1.7).
165
        // FIXME: Should we do this in hixie-76 too?
166
        m_shouldDiscardReceivedData = true;
167
        if (m_buffer)
168
            skipBuffer(m_bufferSize); // Save memory.
169
        m_hasContinuousFrame = false;
170
        m_continuousFrameData.clear();
171
    }
143
    if (m_handle && !m_closed)
172
    if (m_handle && !m_closed)
144
        m_handle->disconnect(); // Will call didClose().
173
        m_handle->disconnect(); // Will call didClose().
145
}
174
}
Lines 345-350 bool WebSocketChannel::processBuffer() a/Source/WebCore/websockets/WebSocketChannel.cpp_sec5
345
    if (m_handshake->mode() != WebSocketHandshake::Connected)
374
    if (m_handshake->mode() != WebSocketHandshake::Connected)
346
        return false;
375
        return false;
347
376
377
    if (m_useHixie76Protocol)
378
        return processFrameHixie76();
379
380
    return processFrame();
381
}
382
383
void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer)
384
{
385
    ASSERT_UNUSED(timer, timer == &m_resumeTimer);
386
387
    RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
388
    while (!m_suspended && m_client && m_buffer)
389
        if (!processBuffer())
390
            break;
391
    if (!m_suspended && m_client && m_closed && m_handle)
392
        didClose(m_handle.get());
393
}
394
395
void WebSocketChannel::startClosingHandshake()
396
{
397
    LOG(Network, "WebSocketChannel %p closing %d %d", this, m_closing, m_receivedClosingHandshake);
398
    if (m_closing)
399
        return;
400
    ASSERT(m_handle);
401
    bool sentSuccessfully;
402
    if (m_useHixie76Protocol) {
403
        Vector<char> buf;
404
        buf.append('\xff');
405
        buf.append('\0');
406
        sentSuccessfully = m_handle->send(buf.data(), buf.size());
407
    } else
408
        sentSuccessfully = sendFrame(OpCodeClose, "", 0); // FIXME: Send status code and reason message.
409
410
    if (!sentSuccessfully) {
411
        m_handle->disconnect();
412
        return;
413
    }
414
    m_closing = true;
415
    if (m_client)
416
        m_client->didStartClosingHandshake();
417
}
418
419
void WebSocketChannel::closingTimerFired(Timer<WebSocketChannel>* timer)
420
{
421
    LOG(Network, "WebSocketChannel %p closing timer", this);
422
    ASSERT_UNUSED(timer, &m_closingTimer == timer);
423
    if (m_handle)
424
        m_handle->disconnect();
425
}
426
427
WebSocketChannel::ParseFrameResult WebSocketChannel::parseFrame(FrameData& frame)
428
{
429
    const char* p = m_buffer;
430
    const char* bufferEnd = m_buffer + m_bufferSize;
431
432
    if (m_bufferSize < 2)
433
        return FrameIncomplete;
434
435
    unsigned char firstByte = *p++;
436
    unsigned char secondByte = *p++;
437
438
    bool final = firstByte & finalBit;
439
    bool reserved1 = firstByte & reserved1Bit;
440
    bool reserved2 = firstByte & reserved2Bit;
441
    bool reserved3 = firstByte & reserved3Bit;
442
    OpCode opCode = firstByte & opCodeMask;
443
444
    bool masked = secondByte & maskBit;
445
    uint64_t payloadLength64 = secondByte & payloadLengthMask;
446
    if (payloadLength64 > maxPayloadLengthWithoutExtendedLengthField) {
447
        int extendedPayloadLengthSize;
448
        if (payloadLength64 == payloadLengthWithTwoByteExtendedLengthField)
449
            extendedPayloadLengthSize = 2;
450
        else {
451
            ASSERT(payloadLength64 == payloadLengthWithEightByteExtendedLengthField);
452
            extendedPayloadLengthSize = 8;
453
        }
454
        if (bufferEnd - p < extendedPayloadLengthSize)
455
            return FrameIncomplete;
456
        payloadLength64 = 0;
457
        for (int i = 0; i < extendedPayloadLengthSize; ++i) {
458
            payloadLength64 <<= 8;
459
            payloadLength64 |= static_cast<unsigned char>(*p++);
460
        }
461
    }
462
463
    static const uint64_t maxPayloadLength = UINT64_C(0x7FFFFFFFFFFFFFFF);
464
    size_t maskingKeyLength = masked ? maskingKeyWidthInBytes : 0;
465
    if (payloadLength64 > maxPayloadLength || payloadLength64 + maskingKeyLength > std::numeric_limits<size_t>::max()) {
466
        fail("WebSocket frame length too large: " + String::number(payloadLength64) + " bytes");
467
        return FrameError;
468
    }
469
    size_t payloadLength = static_cast<size_t>(payloadLength64);
470
471
    if (static_cast<size_t>(bufferEnd - p) < maskingKeyLength + payloadLength)
472
        return FrameIncomplete;
473
474
    if (masked) {
475
        const char* maskingKey = p;
476
        char* payload = const_cast<char*>(p + maskingKeyWidthInBytes);
477
        for (size_t i = 0; i < payloadLength; ++i)
478
            payload[i] ^= maskingKey[i % maskingKeyWidthInBytes]; // Unmask the payload.
479
    }
480
481
    frame.opCode = opCode;
482
    frame.final = final;
483
    frame.reserved1 = reserved1;
484
    frame.reserved2 = reserved2;
485
    frame.reserved3 = reserved3;
486
    frame.masked = masked;
487
    frame.payload = p + maskingKeyLength;
488
    frame.payloadLength = payloadLength;
489
    frame.frameEnd = p + maskingKeyLength + payloadLength;
490
    return FrameOK;
491
}
492
493
bool WebSocketChannel::processFrame()
494
{
495
    ASSERT(m_buffer);
496
497
    FrameData frame;
498
    if (parseFrame(frame) != FrameOK)
499
        return false;
500
501
    // Validate the frame data.
502
    if (isReservedOpCode(frame.opCode)) {
503
        fail("Unrecognized frame opcode: " + String::number(frame.opCode));
504
        return false;
505
    }
506
507
    if (frame.reserved1 || frame.reserved2 || frame.reserved3) {
508
        fail("One or more reserved bits are on: reserved1 = " + String::number(frame.reserved1) + ", reserved2 = " + String::number(frame.reserved2) + ", reserved3 = " + String::number(frame.reserved3));
509
        return false;
510
    }
511
512
    // All control frames must not be fragmented.
513
    if (isControlOpCode(frame.opCode) && !frame.final) {
514
        fail("Received fragmented control frame: opcode = " + String::number(frame.opCode));
515
        return false;
516
    }
517
518
    // All control frames must have a payload of 125 bytes or less, which means the frame must not contain
519
    // the "extended payload length" field.
520
    if (isControlOpCode(frame.opCode) && frame.payloadLength > maxPayloadLengthWithoutExtendedLengthField) {
521
        fail("Received control frame having too long payload: " + String::number(frame.payloadLength) + " bytes");
522
        return false;
523
    }
524
525
    // A new data frame is received before the previous continuous frame finishes.
526
    // Note that control frames are allowed to come in the middle of continuous frames.
527
    if (m_hasContinuousFrame && frame.opCode != OpCodeContinuation && !isControlOpCode(frame.opCode)) {
528
        fail("Received new data frame but previous continuous frame is unfinished.");
529
        return false;
530
    }
531
532
    switch (frame.opCode) {
533
    case OpCodeContinuation:
534
        // Throw away content of a binary message because binary messages are not supported yet.
535
        if (m_continuousFrameOpCode == OpCodeText)
536
            m_continuousFrameData.append(frame.payload, frame.payloadLength);
537
        skipBuffer(frame.frameEnd - m_buffer);
538
        if (frame.final) {
539
            // onmessage handler may eventually call the other methods of this channel,
540
            // so we should pretend that we have finished to read this frame and
541
            // make sure that the member variables are in a consistent state before
542
            // the handler is invoked.
543
            // Vector<char>::swap() is used here to clear m_continuousFrameData.
544
            Vector<char> continuousFrameData;
545
            m_continuousFrameData.swap(continuousFrameData);
546
            m_hasContinuousFrame = false;
547
            if (m_continuousFrameOpCode == OpCodeText) {
548
                String message = String::fromUTF8(continuousFrameData.data(), continuousFrameData.size());
549
                if (message.isNull())
550
                    fail("Could not decode a text frame as UTF-8.");
551
                else
552
                    m_client->didReceiveMessage(message);
553
            } else if (m_continuousFrameOpCode == OpCodeBinary) {
554
                ASSERT(m_continuousFrameData.isEmpty());
555
                fail("Received a binary frame which is not supported yet.");
556
            }
557
        }
558
        break;
559
560
    case OpCodeText:
561
        if (frame.final) {
562
            String message = String::fromUTF8(frame.payload, frame.payloadLength);
563
            skipBuffer(frame.frameEnd - m_buffer);
564
            if (message.isNull())
565
                fail("Could not decode a text frame as UTF-8.");
566
            else
567
                m_client->didReceiveMessage(message);
568
        } else {
569
            m_hasContinuousFrame = true;
570
            m_continuousFrameOpCode = OpCodeText;
571
            ASSERT(m_continuousFrameData.isEmpty());
572
            m_continuousFrameData.append(frame.payload, frame.payloadLength);
573
            skipBuffer(frame.frameEnd - m_buffer);
574
        }
575
        break;
576
577
    case OpCodeBinary:
578
        if (frame.final)
579
            fail("Received a binary frame which is not supported yet.");
580
        else {
581
            m_hasContinuousFrame = true;
582
            m_continuousFrameOpCode = OpCodeBinary;
583
            ASSERT(m_continuousFrameData.isEmpty());
584
            // Do not store data of a binary message to m_continuousFrameData to save memory.
585
            skipBuffer(frame.frameEnd - m_buffer);
586
        }
587
        break;
588
589
    case OpCodeClose:
590
        // FIXME: Handle payload.
591
        skipBuffer(frame.frameEnd - m_buffer);
592
        m_receivedClosingHandshake = true;
593
        startClosingHandshake();
594
        if (m_closing)
595
            m_handle->close(); // Close after sending a close frame.
596
        break;
597
598
    case OpCodePing: {
599
        bool result = sendFrame(OpCodePong, frame.payload, frame.payloadLength);
600
        skipBuffer(frame.frameEnd - m_buffer);
601
        if (!result)
602
            fail("Failed to send a pong frame.");
603
        break;
604
    }
605
606
    case OpCodePong:
607
        // A server may send a pong in response to our ping, or an unsolicited pong which is not associated with
608
        // any specific ping. Either way, there's nothing to do on receipt of pong.
609
        skipBuffer(frame.frameEnd - m_buffer);
610
        break;
611
612
    default:
613
        ASSERT_NOT_REACHED();
614
        skipBuffer(frame.frameEnd - m_buffer);
615
        break;
616
    }
617
618
    return m_buffer;
619
}
620
621
bool WebSocketChannel::processFrameHixie76()
622
{
348
    const char* nextFrame = m_buffer;
623
    const char* nextFrame = m_buffer;
349
    const char* p = m_buffer;
624
    const char* p = m_buffer;
350
    const char* end = p + m_bufferSize;
625
    const char* end = p + m_bufferSize;
Lines 427-468 bool WebSocketChannel::processBuffer() a/Source/WebCore/websockets/WebSocketChannel.cpp_sec6
427
    return false;
702
    return false;
428
}
703
}
429
704
430
void WebSocketChannel::resumeTimerFired(Timer<WebSocketChannel>* timer)
705
bool WebSocketChannel::sendFrame(OpCode opCode, const char* data, size_t dataLength)
431
{
706
{
432
    ASSERT_UNUSED(timer, timer == &m_resumeTimer);
707
    ASSERT(m_handle);
708
    ASSERT(!m_suspended);
433
709
434
    RefPtr<WebSocketChannel> protect(this); // The client can close the channel, potentially removing the last reference.
710
    Vector<char> frame;
435
    while (!m_suspended && m_client && m_buffer)
711
    ASSERT(!(opCode & ~opCodeMask)); // Checks whether "opCode" fits in the range of opCodes.
436
        if (!processBuffer())
712
    frame.append(finalBit | opCode);
437
            break;
713
    if (dataLength <= maxPayloadLengthWithoutExtendedLengthField)
438
    if (!m_suspended && m_client && m_closed && m_handle)
714
        frame.append(maskBit | dataLength);
439
        didClose(m_handle.get());
715
    else if (dataLength <= 0xFFFF) {
716
        frame.append(maskBit | payloadLengthWithTwoByteExtendedLengthField);
717
        frame.append((dataLength & 0xFF00) >> 8);
718
        frame.append(dataLength & 0xFF);
719
    } else {
720
        frame.append(maskBit | payloadLengthWithEightByteExtendedLengthField);
721
        char extendedPayloadLength[8];
722
        size_t remaining = dataLength;
723
        // Fill the length into extendedPayloadLength in the network byte order.
724
        for (int i = 0; i < 8; ++i) {
725
            extendedPayloadLength[7 - i] = remaining & 0xFF;
726
            remaining >>= 8;
727
        }
728
        ASSERT(!remaining);
729
        frame.append(extendedPayloadLength, 8);
730
    }
731
732
    // Mask the frame.
733
    size_t maskingKeyStart = frame.size();
734
    frame.grow(frame.size() + maskingKeyWidthInBytes); // Add placeholder for masking key. Will be overwritten.
735
    size_t payloadStart = frame.size();
736
    frame.append(data, dataLength);
737
738
    cryptographicallyRandomValues(frame.data() + maskingKeyStart, maskingKeyWidthInBytes);
739
    for (size_t i = 0; i < dataLength; ++i)
740
        frame[payloadStart + i] ^= frame[maskingKeyStart + i % maskingKeyWidthInBytes];
741
742
    return m_handle->send(frame.data(), frame.size());
440
}
743
}
441
744
442
void WebSocketChannel::startClosingHandshake()
745
bool WebSocketChannel::sendFrameHixie76(const char* data, size_t dataLength)
443
{
746
{
444
    LOG(Network, "WebSocketChannel %p closing %d %d", this, m_closing, m_receivedClosingHandshake);
445
    if (m_closing)
446
        return;
447
    ASSERT(m_handle);
747
    ASSERT(m_handle);
448
    Vector<char> buf;
748
    ASSERT(!m_suspended);
449
    buf.append('\xff');
450
    buf.append('\0');
451
    if (!m_handle->send(buf.data(), buf.size())) {
452
        m_handle->disconnect();
453
        return;
454
    }
455
    m_closing = true;
456
    if (m_client)
457
        m_client->didStartClosingHandshake();
458
}
459
749
460
void WebSocketChannel::closingTimerFired(Timer<WebSocketChannel>* timer)
750
    Vector<char> frame;
461
{
751
    frame.append('\0'); // Frame type.
462
    LOG(Network, "WebSocketChannel %p closing timer", this);
752
    frame.append(data, dataLength);
463
    ASSERT_UNUSED(timer, &m_closingTimer == timer);
753
    frame.append('\xff'); // Frame end.
464
    if (m_handle)
754
    return m_handle->send(frame.data(), frame.size());
465
        m_handle->disconnect();
466
}
755
}
467
756
468
}  // namespace WebCore
757
}  // namespace WebCore
- a/Source/WebCore/websockets/WebSocketChannel.h -1 / +45 lines
Lines 1-5 a/Source/WebCore/websockets/WebSocketChannel.h_sec1
1
/*
1
/*
2
 * Copyright (C) 2009 Google Inc.  All rights reserved.
2
 * Copyright (C) 2011 Google Inc.  All rights reserved.
3
 *
3
 *
4
 * Redistribution and use in source and binary forms, with or without
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are
5
 * modification, are permitted provided that the following conditions are
Lines 88-93 namespace WebCore { a/Source/WebCore/websockets/WebSocketChannel.h_sec2
88
        void startClosingHandshake();
88
        void startClosingHandshake();
89
        void closingTimerFired(Timer<WebSocketChannel>*);
89
        void closingTimerFired(Timer<WebSocketChannel>*);
90
90
91
        // Hybi-10 opcodes.
92
        typedef unsigned int OpCode;
93
        static const OpCode OpCodeContinuation;
94
        static const OpCode OpCodeText;
95
        static const OpCode OpCodeBinary;
96
        static const OpCode OpCodeClose;
97
        static const OpCode OpCodePing;
98
        static const OpCode OpCodePong;
99
100
        static bool isNonControlOpCode(OpCode opCode) { return opCode == OpCodeContinuation || opCode == OpCodeText || opCode == OpCodeBinary; }
101
        static bool isControlOpCode(OpCode opCode) { return opCode == OpCodeClose || opCode == OpCodePing || opCode == OpCodePong; }
102
        static bool isReservedOpCode(OpCode opCode) { return !isNonControlOpCode(opCode) && !isControlOpCode(opCode); }
103
104
        enum ParseFrameResult {
105
            FrameOK,
106
            FrameIncomplete,
107
            FrameError
108
        };
109
110
        struct FrameData {
111
            OpCode opCode;
112
            bool final;
113
            bool reserved1;
114
            bool reserved2;
115
            bool reserved3;
116
            bool masked;
117
            const char* payload;
118
            size_t payloadLength;
119
            const char* frameEnd;
120
        };
121
122
        ParseFrameResult parseFrame(FrameData&); // May modify part of m_buffer to unmask the frame.
123
124
        bool processFrame();
125
        bool processFrameHixie76();
126
127
        bool sendFrame(OpCode, const char* data, size_t dataLength);
128
        bool sendFrameHixie76(const char* data, size_t dataLength);
129
91
        ScriptExecutionContext* m_context;
130
        ScriptExecutionContext* m_context;
92
        WebSocketChannelClient* m_client;
131
        WebSocketChannelClient* m_client;
93
        OwnPtr<WebSocketHandshake> m_handshake;
132
        OwnPtr<WebSocketHandshake> m_handshake;
Lines 107-112 namespace WebCore { a/Source/WebCore/websockets/WebSocketChannel.h_sec3
107
        unsigned long m_identifier; // m_identifier == 0 means that we could not obtain a valid identifier.
146
        unsigned long m_identifier; // m_identifier == 0 means that we could not obtain a valid identifier.
108
147
109
        bool m_useHixie76Protocol;
148
        bool m_useHixie76Protocol;
149
150
        // Private members only for hybi-10 protocol.
151
        bool m_hasContinuousFrame;
152
        OpCode m_continuousFrameOpCode;
153
        Vector<char> m_continuousFrameData;
110
    };
154
    };
111
155
112
} // namespace WebCore
156
} // namespace WebCore

Return to Bug 64522