From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- dom/websocket/tests/chrome.ini | 4 + dom/websocket/tests/file_bug1384658.html | 18 + dom/websocket/tests/file_websocket_basic_wsh.py | 31 + dom/websocket/tests/file_websocket_bigBlob_wsh.py | 11 + dom/websocket/tests/file_websocket_hello_wsh.py | 12 + .../tests/file_websocket_http_resource.txt | 1 + ...le_websocket_permessage_deflate_disabled_wsh.py | 18 + ...file_websocket_permessage_deflate_params_wsh.py | 24 + ...le_websocket_permessage_deflate_rejected_wsh.py | 24 + .../tests/file_websocket_permessage_deflate_wsh.py | 23 + dom/websocket/tests/file_websocket_wsh.py | 168 +++ dom/websocket/tests/frame_bug1384658.html | 13 + dom/websocket/tests/iframe_websocket_sandbox.html | 65 + dom/websocket/tests/iframe_websocket_wss.html | 35 + dom/websocket/tests/mochitest.ini | 62 + dom/websocket/tests/test_bug1081686.html | 71 + dom/websocket/tests/test_bug1384658.html | 54 + dom/websocket/tests/test_event_listener_leaks.html | 57 + dom/websocket/tests/test_websocket1.html | 42 + dom/websocket/tests/test_websocket2.html | 44 + dom/websocket/tests/test_websocket3.html | 44 + dom/websocket/tests/test_websocket4.html | 42 + dom/websocket/tests/test_websocket5.html | 41 + dom/websocket/tests/test_websocket_basic.html | 289 ++++ dom/websocket/tests/test_websocket_bigBlob.html | 55 + dom/websocket/tests/test_websocket_frame.html | 161 +++ dom/websocket/tests/test_websocket_hello.html | 49 + dom/websocket/tests/test_websocket_longString.html | 48 + .../tests/test_websocket_mixed_content.html | 96 ++ .../tests/test_websocket_mixed_content_opener.html | 139 ++ .../tests/test_websocket_no_duplicate_packet.html | 106 ++ .../tests/test_websocket_permessage_deflate.html | 110 ++ dom/websocket/tests/test_websocket_sandbox.html | 34 + .../tests/test_websocket_sharedWorker.html | 30 + dom/websocket/tests/test_worker_websocket1.html | 46 + dom/websocket/tests/test_worker_websocket2.html | 46 + dom/websocket/tests/test_worker_websocket3.html | 46 + dom/websocket/tests/test_worker_websocket4.html | 46 + dom/websocket/tests/test_worker_websocket5.html | 46 + .../tests/test_worker_websocket_basic.html | 57 + .../tests/test_worker_websocket_https.html | 30 + .../tests/test_worker_websocket_loadgroup.html | 61 + dom/websocket/tests/websocket_basic_worker.js | 48 + dom/websocket/tests/websocket_helpers.js | 69 + dom/websocket/tests/websocket_https_worker.js | 11 + .../tests/websocket_hybi/file_binary-frames_wsh.py | 19 + .../file_check-binary-messages_wsh.py | 27 + dom/websocket/tests/websocket_hybi/mochitest.ini | 13 + .../websocket_hybi/test_receive-arraybuffer.html | 97 ++ .../tests/websocket_hybi/test_receive-blob.html | 110 ++ .../websocket_hybi/test_send-arraybuffer.html | 82 ++ .../tests/websocket_hybi/test_send-blob.html | 72 + dom/websocket/tests/websocket_loadgroup_worker.js | 26 + dom/websocket/tests/websocket_sharedWorker.js | 34 + dom/websocket/tests/websocket_tests.js | 1483 ++++++++++++++++++++ dom/websocket/tests/websocket_worker1.js | 19 + dom/websocket/tests/websocket_worker2.js | 19 + dom/websocket/tests/websocket_worker3.js | 17 + dom/websocket/tests/websocket_worker4.js | 19 + dom/websocket/tests/websocket_worker5.js | 14 + dom/websocket/tests/websocket_worker_helpers.js | 27 + dom/websocket/tests/websocket_worker_https.html | 14 + dom/websocket/tests/window_bug1384658.html | 19 + dom/websocket/tests/window_websocket_wss.html | 65 + 64 files changed, 4703 insertions(+) create mode 100644 dom/websocket/tests/chrome.ini create mode 100644 dom/websocket/tests/file_bug1384658.html create mode 100644 dom/websocket/tests/file_websocket_basic_wsh.py create mode 100644 dom/websocket/tests/file_websocket_bigBlob_wsh.py create mode 100644 dom/websocket/tests/file_websocket_hello_wsh.py create mode 100644 dom/websocket/tests/file_websocket_http_resource.txt create mode 100644 dom/websocket/tests/file_websocket_permessage_deflate_disabled_wsh.py create mode 100644 dom/websocket/tests/file_websocket_permessage_deflate_params_wsh.py create mode 100644 dom/websocket/tests/file_websocket_permessage_deflate_rejected_wsh.py create mode 100644 dom/websocket/tests/file_websocket_permessage_deflate_wsh.py create mode 100644 dom/websocket/tests/file_websocket_wsh.py create mode 100644 dom/websocket/tests/frame_bug1384658.html create mode 100644 dom/websocket/tests/iframe_websocket_sandbox.html create mode 100644 dom/websocket/tests/iframe_websocket_wss.html create mode 100644 dom/websocket/tests/mochitest.ini create mode 100644 dom/websocket/tests/test_bug1081686.html create mode 100644 dom/websocket/tests/test_bug1384658.html create mode 100644 dom/websocket/tests/test_event_listener_leaks.html create mode 100644 dom/websocket/tests/test_websocket1.html create mode 100644 dom/websocket/tests/test_websocket2.html create mode 100644 dom/websocket/tests/test_websocket3.html create mode 100644 dom/websocket/tests/test_websocket4.html create mode 100644 dom/websocket/tests/test_websocket5.html create mode 100644 dom/websocket/tests/test_websocket_basic.html create mode 100644 dom/websocket/tests/test_websocket_bigBlob.html create mode 100644 dom/websocket/tests/test_websocket_frame.html create mode 100644 dom/websocket/tests/test_websocket_hello.html create mode 100644 dom/websocket/tests/test_websocket_longString.html create mode 100644 dom/websocket/tests/test_websocket_mixed_content.html create mode 100644 dom/websocket/tests/test_websocket_mixed_content_opener.html create mode 100644 dom/websocket/tests/test_websocket_no_duplicate_packet.html create mode 100644 dom/websocket/tests/test_websocket_permessage_deflate.html create mode 100644 dom/websocket/tests/test_websocket_sandbox.html create mode 100644 dom/websocket/tests/test_websocket_sharedWorker.html create mode 100644 dom/websocket/tests/test_worker_websocket1.html create mode 100644 dom/websocket/tests/test_worker_websocket2.html create mode 100644 dom/websocket/tests/test_worker_websocket3.html create mode 100644 dom/websocket/tests/test_worker_websocket4.html create mode 100644 dom/websocket/tests/test_worker_websocket5.html create mode 100644 dom/websocket/tests/test_worker_websocket_basic.html create mode 100644 dom/websocket/tests/test_worker_websocket_https.html create mode 100644 dom/websocket/tests/test_worker_websocket_loadgroup.html create mode 100644 dom/websocket/tests/websocket_basic_worker.js create mode 100644 dom/websocket/tests/websocket_helpers.js create mode 100644 dom/websocket/tests/websocket_https_worker.js create mode 100644 dom/websocket/tests/websocket_hybi/file_binary-frames_wsh.py create mode 100644 dom/websocket/tests/websocket_hybi/file_check-binary-messages_wsh.py create mode 100644 dom/websocket/tests/websocket_hybi/mochitest.ini create mode 100644 dom/websocket/tests/websocket_hybi/test_receive-arraybuffer.html create mode 100644 dom/websocket/tests/websocket_hybi/test_receive-blob.html create mode 100644 dom/websocket/tests/websocket_hybi/test_send-arraybuffer.html create mode 100644 dom/websocket/tests/websocket_hybi/test_send-blob.html create mode 100644 dom/websocket/tests/websocket_loadgroup_worker.js create mode 100644 dom/websocket/tests/websocket_sharedWorker.js create mode 100644 dom/websocket/tests/websocket_tests.js create mode 100644 dom/websocket/tests/websocket_worker1.js create mode 100644 dom/websocket/tests/websocket_worker2.js create mode 100644 dom/websocket/tests/websocket_worker3.js create mode 100644 dom/websocket/tests/websocket_worker4.js create mode 100644 dom/websocket/tests/websocket_worker5.js create mode 100644 dom/websocket/tests/websocket_worker_helpers.js create mode 100644 dom/websocket/tests/websocket_worker_https.html create mode 100644 dom/websocket/tests/window_bug1384658.html create mode 100644 dom/websocket/tests/window_websocket_wss.html (limited to 'dom/websocket/tests') diff --git a/dom/websocket/tests/chrome.ini b/dom/websocket/tests/chrome.ini new file mode 100644 index 0000000000..b781f62e6e --- /dev/null +++ b/dom/websocket/tests/chrome.ini @@ -0,0 +1,4 @@ +[DEFAULT] +skip-if = os == 'android' + +[test_websocket_frame.html] diff --git a/dom/websocket/tests/file_bug1384658.html b/dom/websocket/tests/file_bug1384658.html new file mode 100644 index 0000000000..9db632831e --- /dev/null +++ b/dom/websocket/tests/file_bug1384658.html @@ -0,0 +1,18 @@ + + + + diff --git a/dom/websocket/tests/file_websocket_basic_wsh.py b/dom/websocket/tests/file_websocket_basic_wsh.py new file mode 100644 index 0000000000..050e7ccc10 --- /dev/null +++ b/dom/websocket/tests/file_websocket_basic_wsh.py @@ -0,0 +1,31 @@ +from mod_pywebsocket import msgutil + + +def web_socket_do_extra_handshake(request): + # must set request.ws_protocol to the selected version from ws_requested_protocols + request.ws_protocol = request.ws_requested_protocols[0] + + if request.ws_protocol == "error": + raise ValueError("Error") + pass + + +def web_socket_transfer_data(request): + while True: + line = msgutil.receive_message(request) + if line == "protocol": + msgutil.send_message(request, request.ws_protocol) + continue + + if line == "resource": + msgutil.send_message(request, request.ws_resource) + continue + + if line == "origin": + msgutil.send_message(request, request.ws_origin) + continue + + msgutil.send_message(request, line) + + if line == "end": + return diff --git a/dom/websocket/tests/file_websocket_bigBlob_wsh.py b/dom/websocket/tests/file_websocket_bigBlob_wsh.py new file mode 100644 index 0000000000..5ccc85f3a0 --- /dev/null +++ b/dom/websocket/tests/file_websocket_bigBlob_wsh.py @@ -0,0 +1,11 @@ +from mod_pywebsocket import msgutil + + +def web_socket_do_extra_handshake(request): + pass + + +def web_socket_transfer_data(request): + while True: + line = msgutil.receive_message(request) + msgutil.send_message(request, line, True, True) diff --git a/dom/websocket/tests/file_websocket_hello_wsh.py b/dom/websocket/tests/file_websocket_hello_wsh.py new file mode 100644 index 0000000000..5711d2283c --- /dev/null +++ b/dom/websocket/tests/file_websocket_hello_wsh.py @@ -0,0 +1,12 @@ +from mod_pywebsocket import msgutil + + +def web_socket_do_extra_handshake(request): + pass + + +def web_socket_transfer_data(request): + resp = "Test" + if msgutil.receive_message(request) == "data": + resp = "Hello world!" + msgutil.send_message(request, resp) diff --git a/dom/websocket/tests/file_websocket_http_resource.txt b/dom/websocket/tests/file_websocket_http_resource.txt new file mode 100644 index 0000000000..35dc67f08d --- /dev/null +++ b/dom/websocket/tests/file_websocket_http_resource.txt @@ -0,0 +1 @@ +server data diff --git a/dom/websocket/tests/file_websocket_permessage_deflate_disabled_wsh.py b/dom/websocket/tests/file_websocket_permessage_deflate_disabled_wsh.py new file mode 100644 index 0000000000..5853f8acd7 --- /dev/null +++ b/dom/websocket/tests/file_websocket_permessage_deflate_disabled_wsh.py @@ -0,0 +1,18 @@ +from mod_pywebsocket import common, msgutil + + +def web_socket_do_extra_handshake(request): + if request.ws_requested_extensions is not None: + for extension_request in request.ws_requested_extensions: + if extension_request.name() == "permessage-deflate": + raise ValueError("permessage-deflate should not be offered") + + +def web_socket_transfer_data(request): + while True: + rcvd = msgutil.receive_message(request) + opcode = request.ws_stream.get_last_received_opcode() + if opcode == common.OPCODE_BINARY: + msgutil.send_message(request, rcvd, binary=True) + elif opcode == common.OPCODE_TEXT: + msgutil.send_message(request, rcvd) diff --git a/dom/websocket/tests/file_websocket_permessage_deflate_params_wsh.py b/dom/websocket/tests/file_websocket_permessage_deflate_params_wsh.py new file mode 100644 index 0000000000..e6ea12232f --- /dev/null +++ b/dom/websocket/tests/file_websocket_permessage_deflate_params_wsh.py @@ -0,0 +1,24 @@ +from mod_pywebsocket import common, msgutil + + +def web_socket_do_extra_handshake(request): + deflate_found = False + + if request.ws_extension_processors is not None: + for extension_processor in request.ws_extension_processors: + if extension_processor.name() == "deflate": + extension_processor.set_client_no_context_takeover(True) + deflate_found = True + + if deflate_found is False: + raise ValueError("deflate extension processor not found") + + +def web_socket_transfer_data(request): + while True: + rcvd = msgutil.receive_message(request) + opcode = request.ws_stream.get_last_received_opcode() + if opcode == common.OPCODE_BINARY: + msgutil.send_message(request, rcvd, binary=True) + elif opcode == common.OPCODE_TEXT: + msgutil.send_message(request, rcvd) diff --git a/dom/websocket/tests/file_websocket_permessage_deflate_rejected_wsh.py b/dom/websocket/tests/file_websocket_permessage_deflate_rejected_wsh.py new file mode 100644 index 0000000000..b67627d67c --- /dev/null +++ b/dom/websocket/tests/file_websocket_permessage_deflate_rejected_wsh.py @@ -0,0 +1,24 @@ +from mod_pywebsocket import common, msgutil + + +def web_socket_do_extra_handshake(request): + deflate_removed = False + + if request.ws_extension_processors is not None: + for extension_processor in request.ws_extension_processors: + if extension_processor.name() == "deflate": + request.ws_extension_processors.remove(extension_processor) + deflate_removed = True + + if deflate_removed is False: + raise ValueError("deflate extension processor not found") + + +def web_socket_transfer_data(request): + while True: + rcvd = msgutil.receive_message(request) + opcode = request.ws_stream.get_last_received_opcode() + if opcode == common.OPCODE_BINARY: + msgutil.send_message(request, rcvd, binary=True) + elif opcode == common.OPCODE_TEXT: + msgutil.send_message(request, rcvd) diff --git a/dom/websocket/tests/file_websocket_permessage_deflate_wsh.py b/dom/websocket/tests/file_websocket_permessage_deflate_wsh.py new file mode 100644 index 0000000000..c6436c8499 --- /dev/null +++ b/dom/websocket/tests/file_websocket_permessage_deflate_wsh.py @@ -0,0 +1,23 @@ +from mod_pywebsocket import common, msgutil + + +def web_socket_do_extra_handshake(request): + pmce_offered = False + + if request.ws_requested_extensions is not None: + for extension_request in request.ws_requested_extensions: + if extension_request.name() == "permessage-deflate": + pmce_offered = True + + if pmce_offered is False: + raise ValueError("permessage-deflate not offered") + + +def web_socket_transfer_data(request): + while True: + rcvd = msgutil.receive_message(request) + opcode = request.ws_stream.get_last_received_opcode() + if opcode == common.OPCODE_BINARY: + msgutil.send_message(request, rcvd, binary=True) + elif opcode == common.OPCODE_TEXT: + msgutil.send_message(request, rcvd) diff --git a/dom/websocket/tests/file_websocket_wsh.py b/dom/websocket/tests/file_websocket_wsh.py new file mode 100644 index 0000000000..de69f747e8 --- /dev/null +++ b/dom/websocket/tests/file_websocket_wsh.py @@ -0,0 +1,168 @@ +import time + +import six +from mod_pywebsocket import msgutil + +# see the list of tests in test_websocket.html + + +def web_socket_do_extra_handshake(request): + # must set request.ws_protocol to the selected version from ws_requested_protocols + for x in request.ws_requested_protocols: + if x != "test-does-not-exist": + request.ws_protocol = x + break + + if request.ws_protocol == "test-2.1": + time.sleep(3) + elif request.ws_protocol == "test-9": + time.sleep(3) + elif request.ws_protocol == "test-10": + time.sleep(3) + elif request.ws_protocol == "test-19": + raise ValueError("Aborting (test-19)") + elif request.ws_protocol == "test-20" or request.ws_protocol == "test-17": + time.sleep(3) + elif request.ws_protocol == "test-22": + # The timeout is 5 seconds + time.sleep(13) + elif request.ws_protocol == "test-41b": + request.sts = "max-age=100" + elif request.ws_protocol == "test-49": + # subprotocols are compared case-sensitively, so this should fail + request.ws_protocol = "teST-49" + else: + pass + + +# Behave according to recommendation of RFC 6455, section # 5.5.1: +# "When sending a Close frame in response, the endpoint typically echos the +# status code it received." +# - Without this, pywebsocket replies with 1000 to any close code. +# +# Note that this function is only called when the client initiates the close + + +def web_socket_passive_closing_handshake(request): + if request.ws_close_code == 1005: + return None, None + return request.ws_close_code, request.ws_close_reason + + +def web_socket_transfer_data(request): + if request.ws_protocol == "test-2.1" or request.ws_protocol == "test-2.2": + msgutil.close_connection(request) + elif request.ws_protocol == "test-6": + resp = "wrong message" + if msgutil.receive_message(request) == "1": + resp = "2" + msgutil.send_message(request, six.ensure_text(resp)) + resp = "wrong message" + if msgutil.receive_message(request) == "3": + resp = "4" + msgutil.send_message(request, six.ensure_text(resp)) + resp = "wrong message" + if msgutil.receive_message(request) == "5": + resp = ( + b"\xe3\x81\x82\xe3\x81\x84\xe3\x81\x86\xe3\x81\x88\xe3\x81\x8a".decode( + "utf-8" + ) + ) + msgutil.send_message(request, six.ensure_text(resp)) + msgutil.close_connection(request) + elif request.ws_protocol == "test-7": + msgutil.send_message(request, "test-7 data") + elif request.ws_protocol == "test-10": + msgutil.close_connection(request) + elif request.ws_protocol == "test-11": + resp = "wrong message" + if msgutil.receive_message(request) == "client data": + resp = "server data" + msgutil.send_message(request, six.ensure_text(resp)) + elif request.ws_protocol == "test-12": + msg = msgutil.receive_message(request) + if msg == u"a\ufffdb": + # converted unpaired surrogate in UTF-16 to UTF-8 OK + msgutil.send_message(request, "SUCCESS") + else: + msgutil.send_message( + request, + "FAIL got '" + msg + "' instead of string with replacement char'", + ) + elif request.ws_protocol == "test-13": + # first one binary message containing the byte 0x61 ('a') + request.connection.write(b"\xff\x01\x61") + # after a bad utf8 message + request.connection.write(b"\x01\x61\xff") + msgutil.close_connection(request) + elif request.ws_protocol == "test-14": + msgutil.close_connection(request) + msgutil.send_message(request, "server data") + elif request.ws_protocol == "test-15": + # DISABLED: close_connection hasn't supported 2nd 'abort' argument for a + # long time. Passing extra arg was causing exception, which conveniently + # caused abort :) but as of pywebsocket v606 raising an exception here no + # longer aborts, and there's no obvious way to close TCP connection w/o + # sending websocket CLOSE. + raise RuntimeError("test-15 should be disabled for now") + # msgutil.close_connection(request, True) # OBSOLETE 2nd arg + # return + elif request.ws_protocol == "test-17" or request.ws_protocol == "test-21": + time.sleep(2) + resp = "wrong message" + if msgutil.receive_message(request) == "client data": + resp = "server data" + msgutil.send_message(request, six.ensure_text(resp)) + time.sleep(2) + msgutil.close_connection(request) + elif request.ws_protocol == "test-20": + msgutil.send_message(request, "server data") + msgutil.close_connection(request) + elif request.ws_protocol == "test-34": + request.ws_stream.close_connection(1001, "going away now") + elif request.ws_protocol == "test-35a": + while not request.client_terminated: + msgutil.receive_message(request) + global test35code + test35code = request.ws_close_code + global test35reason + test35reason = request.ws_close_reason + elif request.ws_protocol == "test-35b": + request.ws_stream.close_connection(test35code + 1, test35reason) + elif request.ws_protocol == "test-37b": + while not request.client_terminated: + msgutil.receive_message(request) + global test37code + test37code = request.ws_close_code + global test37reason + test37reason = request.ws_close_reason + elif request.ws_protocol == "test-37c": + request.ws_stream.close_connection(test37code, test37reason) + elif request.ws_protocol == "test-42": + # Echo back 3 messages + msgutil.send_message(request, msgutil.receive_message(request)) + msgutil.send_message(request, msgutil.receive_message(request)) + msgutil.send_message(request, msgutil.receive_message(request)) + elif request.ws_protocol == "test-44": + rcv = six.ensure_text(msgutil.receive_message(request)) + # check we received correct binary msg + if len(rcv) == 3 and ord(rcv[0]) == 5 and ord(rcv[1]) == 0 and ord(rcv[2]) == 7: + # reply with binary msg 0x04 + msgutil.send_message(request, b"\x00\x04", True, True) + else: + msgutil.send_message(request, "incorrect binary msg received!") + elif request.ws_protocol == "test-45": + rcv = msgutil.receive_message(request) + # check we received correct binary msg + if six.ensure_text(rcv) == "flob": + # send back same blob as binary msg + msgutil.send_message(request, rcv, True, True) + else: + msgutil.send_message( + request, "incorrect binary msg received: '" + rcv + "'" + ) + elif request.ws_protocol == "test-46": + msgutil.send_message(request, "client must drop this if close was called") + + while not request.client_terminated: + msgutil.receive_message(request) diff --git a/dom/websocket/tests/frame_bug1384658.html b/dom/websocket/tests/frame_bug1384658.html new file mode 100644 index 0000000000..c13cb17f3a --- /dev/null +++ b/dom/websocket/tests/frame_bug1384658.html @@ -0,0 +1,13 @@ + + +
+ + +
+ + + diff --git a/dom/websocket/tests/iframe_websocket_sandbox.html b/dom/websocket/tests/iframe_websocket_sandbox.html new file mode 100644 index 0000000000..0e6d1d97bf --- /dev/null +++ b/dom/websocket/tests/iframe_websocket_sandbox.html @@ -0,0 +1,65 @@ + + + + diff --git a/dom/websocket/tests/iframe_websocket_wss.html b/dom/websocket/tests/iframe_websocket_wss.html new file mode 100644 index 0000000000..71945a30d9 --- /dev/null +++ b/dom/websocket/tests/iframe_websocket_wss.html @@ -0,0 +1,35 @@ + +Creating WebSocket + + diff --git a/dom/websocket/tests/mochitest.ini b/dom/websocket/tests/mochitest.ini new file mode 100644 index 0000000000..425747b192 --- /dev/null +++ b/dom/websocket/tests/mochitest.ini @@ -0,0 +1,62 @@ +[DEFAULT] +skip-if = toolkit == 'android' # bug 982828 +support-files = + !/dom/events/test/event_leak_utils.js + file_websocket_basic_wsh.py + file_websocket_hello_wsh.py + file_websocket_http_resource.txt + file_websocket_permessage_deflate_wsh.py + file_websocket_permessage_deflate_disabled_wsh.py + file_websocket_permessage_deflate_rejected_wsh.py + file_websocket_permessage_deflate_params_wsh.py + file_websocket_wsh.py + websocket_helpers.js + websocket_tests.js + websocket_worker_helpers.js + +[test_bug1081686.html] +[test_bug1384658.html] +support-files = window_bug1384658.html frame_bug1384658.html file_bug1384658.html +[test_event_listener_leaks.html] +support-files = file_websocket_bigBlob_wsh.py +skip-if = (os == "win" && processor == "aarch64") #bug 1535784 +[test_websocket1.html] +[test_websocket2.html] +[test_websocket3.html] +[test_websocket4.html] +[test_websocket5.html] +[test_websocket_basic.html] +[test_websocket_hello.html] +[test_websocket_permessage_deflate.html] +[test_websocket_sandbox.html] +support-files = iframe_websocket_sandbox.html +[test_websocket_mixed_content.html] +scheme=https +support-files = iframe_websocket_wss.html +[test_websocket_mixed_content_opener.html] +scheme=https +support-files = window_websocket_wss.html +[test_worker_websocket1.html] +support-files = websocket_worker1.js +[test_worker_websocket2.html] +support-files = websocket_worker2.js +skip-if = socketprocess_networking # bug 1787044 +[test_worker_websocket3.html] +support-files = websocket_worker3.js +[test_worker_websocket4.html] +support-files = websocket_worker4.js +[test_worker_websocket5.html] +support-files = websocket_worker5.js +[test_worker_websocket_basic.html] +support-files = websocket_basic_worker.js +[test_worker_websocket_https.html] +support-files = websocket_worker_https.html websocket_https_worker.js +[test_worker_websocket_loadgroup.html] +support-files = websocket_loadgroup_worker.js +[test_websocket_sharedWorker.html] +support-files = websocket_sharedWorker.js +[test_websocket_bigBlob.html] +support-files = file_websocket_bigBlob_wsh.py +[test_websocket_longString.html] +[test_websocket_no_duplicate_packet.html] +scheme = https diff --git a/dom/websocket/tests/test_bug1081686.html b/dom/websocket/tests/test_bug1081686.html new file mode 100644 index 0000000000..debcd97184 --- /dev/null +++ b/dom/websocket/tests/test_bug1081686.html @@ -0,0 +1,71 @@ + + + + + bug 1081686 + + + + +

+ +
+
+
+
+ + +
+ + + + diff --git a/dom/websocket/tests/test_bug1384658.html b/dom/websocket/tests/test_bug1384658.html new file mode 100644 index 0000000000..dd90a0d5d3 --- /dev/null +++ b/dom/websocket/tests/test_bug1384658.html @@ -0,0 +1,54 @@ + + + + + + Test for Bug 1384658 + + + + + + + + diff --git a/dom/websocket/tests/test_event_listener_leaks.html b/dom/websocket/tests/test_event_listener_leaks.html new file mode 100644 index 0000000000..9a79fa1354 --- /dev/null +++ b/dom/websocket/tests/test_event_listener_leaks.html @@ -0,0 +1,57 @@ + + + + + Bug 1450358 - Test WebSocket event listener leak conditions + + + + + + + + + diff --git a/dom/websocket/tests/test_websocket1.html b/dom/websocket/tests/test_websocket1.html new file mode 100644 index 0000000000..1844a67f58 --- /dev/null +++ b/dom/websocket/tests/test_websocket1.html @@ -0,0 +1,42 @@ + + + + + WebSocket test + + + + + + + + +
+
+ + + diff --git a/dom/websocket/tests/test_websocket2.html b/dom/websocket/tests/test_websocket2.html new file mode 100644 index 0000000000..afbbaba62f --- /dev/null +++ b/dom/websocket/tests/test_websocket2.html @@ -0,0 +1,44 @@ + + + + + WebSocket test + + + + + + + + +
+
+ + + diff --git a/dom/websocket/tests/test_websocket3.html b/dom/websocket/tests/test_websocket3.html new file mode 100644 index 0000000000..cc2e091fda --- /dev/null +++ b/dom/websocket/tests/test_websocket3.html @@ -0,0 +1,44 @@ + + + + + WebSocket test + + + + + + + + +
+
+ + + diff --git a/dom/websocket/tests/test_websocket4.html b/dom/websocket/tests/test_websocket4.html new file mode 100644 index 0000000000..186a434ab3 --- /dev/null +++ b/dom/websocket/tests/test_websocket4.html @@ -0,0 +1,42 @@ + + + + + WebSocket test + + + + + + + + +
+
+ + + diff --git a/dom/websocket/tests/test_websocket5.html b/dom/websocket/tests/test_websocket5.html new file mode 100644 index 0000000000..d86752ed5a --- /dev/null +++ b/dom/websocket/tests/test_websocket5.html @@ -0,0 +1,41 @@ + + + + + WebSocket test + + + + + + + + +
+
+ + + diff --git a/dom/websocket/tests/test_websocket_basic.html b/dom/websocket/tests/test_websocket_basic.html new file mode 100644 index 0000000000..2ae2e690ac --- /dev/null +++ b/dom/websocket/tests/test_websocket_basic.html @@ -0,0 +1,289 @@ + + + + Basic WebSocket test + + + + + +Mozilla Bug 472529 +

+ +
+
+
+ + diff --git a/dom/websocket/tests/test_websocket_bigBlob.html b/dom/websocket/tests/test_websocket_bigBlob.html new file mode 100644 index 0000000000..9db01d6a7f --- /dev/null +++ b/dom/websocket/tests/test_websocket_bigBlob.html @@ -0,0 +1,55 @@ + + + + + WebSocket test - big blob on content side + + + + + + + + diff --git a/dom/websocket/tests/test_websocket_frame.html b/dom/websocket/tests/test_websocket_frame.html new file mode 100644 index 0000000000..6c95419bc2 --- /dev/null +++ b/dom/websocket/tests/test_websocket_frame.html @@ -0,0 +1,161 @@ + + + + + Basic websocket frame interception test + + + + + + + diff --git a/dom/websocket/tests/test_websocket_hello.html b/dom/websocket/tests/test_websocket_hello.html new file mode 100644 index 0000000000..8508fba97b --- /dev/null +++ b/dom/websocket/tests/test_websocket_hello.html @@ -0,0 +1,49 @@ + + + + + Basic websocket test + + + + +Mozilla Bug +

+ +
+
+
+
+ + +
+ + + + diff --git a/dom/websocket/tests/test_websocket_longString.html b/dom/websocket/tests/test_websocket_longString.html new file mode 100644 index 0000000000..78c8e471c7 --- /dev/null +++ b/dom/websocket/tests/test_websocket_longString.html @@ -0,0 +1,48 @@ + + + + + WebSocket test - big blob on content side + + + + + + + + diff --git a/dom/websocket/tests/test_websocket_mixed_content.html b/dom/websocket/tests/test_websocket_mixed_content.html new file mode 100644 index 0000000000..bc2ac40188 --- /dev/null +++ b/dom/websocket/tests/test_websocket_mixed_content.html @@ -0,0 +1,96 @@ + + + + + WebSocket mixed content tests - load secure and insecure websockets + + + + + + +
+ + + + diff --git a/dom/websocket/tests/test_websocket_mixed_content_opener.html b/dom/websocket/tests/test_websocket_mixed_content_opener.html new file mode 100644 index 0000000000..7db0325825 --- /dev/null +++ b/dom/websocket/tests/test_websocket_mixed_content_opener.html @@ -0,0 +1,139 @@ + + + + + WebSocket mixed content opener tests - load secure and insecure websockets in secure and insecure iframes through secure and insecure opened windows + + + + + + +
+ + + diff --git a/dom/websocket/tests/test_websocket_no_duplicate_packet.html b/dom/websocket/tests/test_websocket_no_duplicate_packet.html new file mode 100644 index 0000000000..7b2b0fc690 --- /dev/null +++ b/dom/websocket/tests/test_websocket_no_duplicate_packet.html @@ -0,0 +1,106 @@ + + + + + WebSocket test - big blob on content side + + + + + + + + diff --git a/dom/websocket/tests/test_websocket_permessage_deflate.html b/dom/websocket/tests/test_websocket_permessage_deflate.html new file mode 100644 index 0000000000..ecf66419f2 --- /dev/null +++ b/dom/websocket/tests/test_websocket_permessage_deflate.html @@ -0,0 +1,110 @@ + + + + Basic test of permessage compression websocket extension + + + + +Mozilla Bug +

+ +
+
+
+ + diff --git a/dom/websocket/tests/test_websocket_sandbox.html b/dom/websocket/tests/test_websocket_sandbox.html new file mode 100644 index 0000000000..2803186ff0 --- /dev/null +++ b/dom/websocket/tests/test_websocket_sandbox.html @@ -0,0 +1,34 @@ + + + + Bug 1252751 + + + + +
+ + + + diff --git a/dom/websocket/tests/test_websocket_sharedWorker.html b/dom/websocket/tests/test_websocket_sharedWorker.html new file mode 100644 index 0000000000..b79b0a6ced --- /dev/null +++ b/dom/websocket/tests/test_websocket_sharedWorker.html @@ -0,0 +1,30 @@ + + + + + Test for bug 1090183 + + + + + + + + + diff --git a/dom/websocket/tests/test_worker_websocket1.html b/dom/websocket/tests/test_worker_websocket1.html new file mode 100644 index 0000000000..71414fbe42 --- /dev/null +++ b/dom/websocket/tests/test_worker_websocket1.html @@ -0,0 +1,46 @@ + + + + + Test for WebSocket object in workers + + + + +

+

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket2.html b/dom/websocket/tests/test_worker_websocket2.html
new file mode 100644
index 0000000000..d9e16281b9
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket2.html
@@ -0,0 +1,46 @@
+
+
+
+
+  Test for WebSocket object in workers
+  
+  
+
+
+

+

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket3.html b/dom/websocket/tests/test_worker_websocket3.html
new file mode 100644
index 0000000000..4387192c42
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket3.html
@@ -0,0 +1,46 @@
+
+
+
+
+  Test for WebSocket object in workers
+  
+  
+
+
+

+

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket4.html b/dom/websocket/tests/test_worker_websocket4.html
new file mode 100644
index 0000000000..5f4c390574
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket4.html
@@ -0,0 +1,46 @@
+
+
+
+
+  Test for WebSocket object in workers
+  
+  
+
+
+

+

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket5.html b/dom/websocket/tests/test_worker_websocket5.html
new file mode 100644
index 0000000000..0b3450b7b6
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket5.html
@@ -0,0 +1,46 @@
+
+
+
+
+  Test for WebSocket object in workers
+  
+  
+
+
+

+

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket_basic.html b/dom/websocket/tests/test_worker_websocket_basic.html
new file mode 100644
index 0000000000..39ff1647e7
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket_basic.html
@@ -0,0 +1,57 @@
+
+
+
+
+  Test for WebSocket object in workers
+  
+  
+
+
+

+ +

+
+
+
+
diff --git a/dom/websocket/tests/test_worker_websocket_https.html b/dom/websocket/tests/test_worker_websocket_https.html
new file mode 100644
index 0000000000..9283b9bd09
--- /dev/null
+++ b/dom/websocket/tests/test_worker_websocket_https.html
@@ -0,0 +1,30 @@
+
+
+
+
+  Test that creating insecure websockets from https workers is not possible
+  
+  
+
+
+

+ +
+
+
+ + + diff --git a/dom/websocket/tests/test_worker_websocket_loadgroup.html b/dom/websocket/tests/test_worker_websocket_loadgroup.html new file mode 100644 index 0000000000..d02b8f149c --- /dev/null +++ b/dom/websocket/tests/test_worker_websocket_loadgroup.html @@ -0,0 +1,61 @@ + + + + + Test for WebSocket object in workers + + + + +

+ +

+
+
+
+
diff --git a/dom/websocket/tests/websocket_basic_worker.js b/dom/websocket/tests/websocket_basic_worker.js
new file mode 100644
index 0000000000..d1d263afcc
--- /dev/null
+++ b/dom/websocket/tests/websocket_basic_worker.js
@@ -0,0 +1,48 @@
+onmessage = function(event) {
+  if (event.data != 0) {
+    var worker = new Worker("websocket_basic_worker.js");
+    worker.onmessage = function(e) {
+      postMessage(e.data);
+    };
+
+    worker.postMessage(event.data - 1);
+    return;
+  }
+
+  status = false;
+  try {
+    if (WebSocket instanceof Object) {
+      status = true;
+    }
+  } catch (e) {}
+
+  postMessage({
+    type: "status",
+    status,
+    msg: "WebSocket object:" + WebSocket,
+  });
+
+  var ws = new WebSocket(
+    "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_hello"
+  );
+  ws.onopen = function(e) {
+    postMessage({ type: "status", status: true, msg: "OnOpen called" });
+    ws.send("data");
+  };
+
+  ws.onclose = function(e) {};
+
+  ws.onerror = function(e) {
+    postMessage({ type: "status", status: false, msg: "onerror called!" });
+  };
+
+  ws.onmessage = function(e) {
+    postMessage({
+      type: "status",
+      status: e.data == "Hello world!",
+      msg: "Wrong data",
+    });
+    ws.close();
+    postMessage({ type: "finish" });
+  };
+};
diff --git a/dom/websocket/tests/websocket_helpers.js b/dom/websocket/tests/websocket_helpers.js
new file mode 100644
index 0000000000..18f9f5a835
--- /dev/null
+++ b/dom/websocket/tests/websocket_helpers.js
@@ -0,0 +1,69 @@
+var current_test = 0;
+
+function shouldNotOpen(e) {
+  var ws = e.target;
+  ok(false, "onopen shouldn't be called on test " + ws._testNumber + "!");
+}
+
+function shouldCloseCleanly(e) {
+  var ws = e.target;
+  ok(
+    e.wasClean,
+    "the ws connection in test " + ws._testNumber + " should be closed cleanly"
+  );
+}
+
+function shouldCloseNotCleanly(e) {
+  var ws = e.target;
+  ok(
+    !e.wasClean,
+    "the ws connection in test " +
+      ws._testNumber +
+      " shouldn't be closed cleanly"
+  );
+}
+
+function ignoreError(e) {}
+
+function CreateTestWS(ws_location, ws_protocol) {
+  var ws;
+
+  if (ws_protocol == undefined) {
+    ws = new WebSocket(ws_location);
+  } else {
+    ws = new WebSocket(ws_location, ws_protocol);
+  }
+
+  ws._testNumber = current_test;
+  ok(true, "Created websocket for test " + ws._testNumber + "\n");
+
+  ws.onerror = function(e) {
+    ok(false, "onerror called on test " + e.target._testNumber + "!");
+  };
+
+  return ws;
+}
+
+function forcegc() {
+  SpecialPowers.forceGC();
+  SpecialPowers.gc();
+}
+
+function feedback() {
+  $("feedback").innerHTML =
+    "executing test: " + (current_test + 1) + " of " + tests.length + " tests.";
+}
+
+function finish() {
+  SimpleTest.finish();
+}
+
+function doTest() {
+  if (current_test >= tests.length) {
+    finish();
+    return;
+  }
+
+  feedback();
+  tests[current_test++]().then(doTest);
+}
diff --git a/dom/websocket/tests/websocket_https_worker.js b/dom/websocket/tests/websocket_https_worker.js
new file mode 100644
index 0000000000..6d7fd8376e
--- /dev/null
+++ b/dom/websocket/tests/websocket_https_worker.js
@@ -0,0 +1,11 @@
+onmessage = function() {
+  var wsCreated = true;
+  try {
+    new WebSocket(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_hello"
+    );
+  } catch (e) {
+    wsCreated = false;
+  }
+  postMessage(wsCreated ? "created" : "not created");
+};
diff --git a/dom/websocket/tests/websocket_hybi/file_binary-frames_wsh.py b/dom/websocket/tests/websocket_hybi/file_binary-frames_wsh.py
new file mode 100644
index 0000000000..16ace4d3a6
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/file_binary-frames_wsh.py
@@ -0,0 +1,19 @@
+import six
+from mod_pywebsocket import common, stream
+
+
+def web_socket_do_extra_handshake(request):
+    pass
+
+
+def web_socket_transfer_data(request):
+    messages_to_send = ["Hello, world!", "", all_distinct_bytes()]
+    for message in messages_to_send:
+        message = six.b(message)
+        # FIXME: Should use better API to send binary messages when pywebsocket supports it.
+        header = stream.create_header(common.OPCODE_BINARY, len(message), 1, 0, 0, 0, 0)
+        request.connection.write(header + message)
+
+
+def all_distinct_bytes():
+    return "".join([chr(i) for i in range(256)])
diff --git a/dom/websocket/tests/websocket_hybi/file_check-binary-messages_wsh.py b/dom/websocket/tests/websocket_hybi/file_check-binary-messages_wsh.py
new file mode 100644
index 0000000000..d72ec1f462
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/file_check-binary-messages_wsh.py
@@ -0,0 +1,27 @@
+import six
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+    pass  # Always accept.
+
+
+def web_socket_transfer_data(request):
+    expected_messages = ["Hello, world!", "", all_distinct_bytes()]
+
+    for test_number, expected_message in enumerate(expected_messages):
+        expected_message = six.b(expected_message)
+        message = msgutil.receive_message(request)
+        if message == expected_message:
+            msgutil.send_message(request, "PASS: Message #{:d}.".format(test_number))
+        else:
+            msgutil.send_message(
+                request,
+                "FAIL: Message #{:d}: Received unexpected message: {!r}".format(
+                    test_number, message
+                ),
+            )
+
+
+def all_distinct_bytes():
+    return "".join([chr(i) for i in range(256)])
diff --git a/dom/websocket/tests/websocket_hybi/mochitest.ini b/dom/websocket/tests/websocket_hybi/mochitest.ini
new file mode 100644
index 0000000000..21d61c8c86
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/mochitest.ini
@@ -0,0 +1,13 @@
+[DEFAULT]
+support-files =
+  file_binary-frames_wsh.py
+  file_check-binary-messages_wsh.py
+
+[test_receive-arraybuffer.html]
+skip-if = toolkit == 'android'
+[test_receive-blob.html]
+skip-if = toolkit == 'android'
+[test_send-arraybuffer.html]
+skip-if = toolkit == 'android'
+[test_send-blob.html]
+skip-if = toolkit == 'android'
diff --git a/dom/websocket/tests/websocket_hybi/test_receive-arraybuffer.html b/dom/websocket/tests/websocket_hybi/test_receive-arraybuffer.html
new file mode 100644
index 0000000000..6d465b7677
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/test_receive-arraybuffer.html
@@ -0,0 +1,97 @@
+
+
+
+  
+  
+
+
+
+

+ +
+
+
+
+
diff --git a/dom/websocket/tests/websocket_hybi/test_receive-blob.html b/dom/websocket/tests/websocket_hybi/test_receive-blob.html
new file mode 100644
index 0000000000..5589633a7c
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/test_receive-blob.html
@@ -0,0 +1,110 @@
+
+
+
+  
+  
+
+
+
+

+ +
+
+
+
+
diff --git a/dom/websocket/tests/websocket_hybi/test_send-arraybuffer.html b/dom/websocket/tests/websocket_hybi/test_send-arraybuffer.html
new file mode 100644
index 0000000000..6c71ca5415
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/test_send-arraybuffer.html
@@ -0,0 +1,82 @@
+
+
+
+  
+  
+
+
+
+

+ +
+
+
+
+
diff --git a/dom/websocket/tests/websocket_hybi/test_send-blob.html b/dom/websocket/tests/websocket_hybi/test_send-blob.html
new file mode 100644
index 0000000000..6af1e2df03
--- /dev/null
+++ b/dom/websocket/tests/websocket_hybi/test_send-blob.html
@@ -0,0 +1,72 @@
+
+
+
+  
+  
+
+
+
+

+

+ +
+
+
+
+
diff --git a/dom/websocket/tests/websocket_loadgroup_worker.js b/dom/websocket/tests/websocket_loadgroup_worker.js
new file mode 100644
index 0000000000..f97cd4c5f2
--- /dev/null
+++ b/dom/websocket/tests/websocket_loadgroup_worker.js
@@ -0,0 +1,26 @@
+onmessage = function(event) {
+  if (event.data != 0) {
+    var worker = new Worker("websocket_loadgroup_worker.js");
+    worker.onmessage = function(e) {
+      postMessage(e.data);
+    };
+
+    worker.postMessage(event.data - 1);
+    return;
+  }
+
+  var ws = new WebSocket(
+    "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_hello"
+  );
+  ws.onopen = function(e) {
+    postMessage("opened");
+  };
+
+  ws.onclose = function(e) {
+    postMessage("closed");
+  };
+
+  ws.onerror = function(e) {
+    postMessage("error");
+  };
+};
diff --git a/dom/websocket/tests/websocket_sharedWorker.js b/dom/websocket/tests/websocket_sharedWorker.js
new file mode 100644
index 0000000000..8943ce2ac3
--- /dev/null
+++ b/dom/websocket/tests/websocket_sharedWorker.js
@@ -0,0 +1,34 @@
+onconnect = function(evt) {
+  var ws = new WebSocket(
+    "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_hello"
+  );
+
+  ws.onopen = function(e) {
+    evt.ports[0].postMessage({
+      type: "status",
+      status: true,
+      msg: "OnOpen called",
+    });
+    ws.send("data");
+  };
+
+  ws.onclose = function(e) {};
+
+  ws.onerror = function(e) {
+    evt.ports[0].postMessage({
+      type: "status",
+      status: false,
+      msg: "onerror called!",
+    });
+  };
+
+  ws.onmessage = function(e) {
+    evt.ports[0].postMessage({
+      type: "status",
+      status: e.data == "Hello world!",
+      msg: "Wrong data",
+    });
+    ws.close();
+    evt.ports[0].postMessage({ type: "finish" });
+  };
+};
diff --git a/dom/websocket/tests/websocket_tests.js b/dom/websocket/tests/websocket_tests.js
new file mode 100644
index 0000000000..3a63326cde
--- /dev/null
+++ b/dom/websocket/tests/websocket_tests.js
@@ -0,0 +1,1483 @@
+// test1: client tries to connect to a http scheme location;
+function test1() {
+  return new Promise(function(resolve, reject) {
+    try {
+      var ws = CreateTestWS(
+        "http://mochi.test:8888/tests/dom/websocket/tests/file_websocket"
+      );
+      ok(false, "test1 failed");
+    } catch (e) {
+      ok(true, "test1 failed");
+    }
+
+    resolve();
+  });
+}
+
+// test2: assure serialization of the connections;
+// this test expects that the serialization list to connect to the proxy
+// is empty.
+function test2() {
+  return new Promise(function(resolve, reject) {
+    var waitTest2Part1 = true;
+    var waitTest2Part2 = true;
+
+    var ws1 = CreateTestWS(
+      "ws://sub2.test2.example.com/tests/dom/websocket/tests/file_websocket",
+      "test-2.1"
+    );
+    var ws2 = CreateTestWS(
+      "ws://sub2.test2.example.com/tests/dom/websocket/tests/file_websocket",
+      "test-2.2"
+    );
+
+    var ws2CanConnect = false;
+
+    function maybeFinished() {
+      if (!waitTest2Part1 && !waitTest2Part2) {
+        resolve();
+      }
+    }
+
+    ws1.onopen = function() {
+      ok(true, "ws1 open in test 2");
+      ws2CanConnect = true;
+      ws1.close();
+    };
+
+    ws1.onclose = function(e) {
+      waitTest2Part1 = false;
+      maybeFinished();
+    };
+
+    ws2.onopen = function() {
+      ok(ws2CanConnect, "shouldn't connect yet in test-2!");
+      ws2.close();
+    };
+
+    ws2.onclose = function(e) {
+      waitTest2Part2 = false;
+      maybeFinished();
+    };
+  });
+}
+
+// test3: client tries to connect to an non-existent ws server;
+function test3() {
+  return new Promise(function(resolve, reject) {
+    var hasError = false;
+    var ws = CreateTestWS("ws://this.websocket.server.probably.does.not.exist");
+
+    ws.onopen = shouldNotOpen;
+
+    ws.onerror = function(e) {
+      hasError = true;
+    };
+
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      ok(hasError, "rcvd onerror event");
+      is(e.code, 1006, "test-3 close code should be 1006 but is:" + e.code);
+      resolve();
+    };
+  });
+}
+
+// test4: client tries to connect using a relative url;
+function test4() {
+  return new Promise(function(resolve, reject) {
+    try {
+      var ws = CreateTestWS("file_websocket");
+      ok(false, "test-4 failed");
+    } catch (e) {
+      ok(true, "test-4 failed");
+    }
+
+    resolve();
+  });
+}
+
+// test5: client uses an invalid protocol value;
+function test5() {
+  return new Promise(function(resolve, reject) {
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        ""
+      );
+      ok(false, "couldn't accept an empty string in the protocol parameter");
+    } catch (e) {
+      ok(true, "couldn't accept an empty string in the protocol parameter");
+    }
+
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "\n"
+      );
+      ok(
+        false,
+        "couldn't accept any not printable ASCII character in the protocol parameter"
+      );
+    } catch (e) {
+      ok(
+        true,
+        "couldn't accept any not printable ASCII character in the protocol parameter"
+      );
+    }
+
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "test 5"
+      );
+      ok(false, "U+0020 not acceptable in protocol parameter");
+    } catch (e) {
+      ok(true, "U+0020 not acceptable in protocol parameter");
+    }
+
+    resolve();
+  });
+}
+
+// test6: counter and encoding check;
+function test6() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-6"
+    );
+    var counter = 1;
+
+    ws.onopen = function() {
+      ws.send(counter);
+    };
+
+    ws.onmessage = function(e) {
+      if (counter == 5) {
+        is(e.data, "あいうえお", "test-6 counter 5 data ok");
+        ws.close();
+      } else {
+        is(parseInt(e.data), counter + 1, "bad counter");
+        counter += 2;
+        ws.send(counter);
+      }
+    };
+
+    ws.onclose = function(e) {
+      shouldCloseCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test7: onmessage event origin property check
+function test7() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://sub2.test2.example.org/tests/dom/websocket/tests/file_websocket",
+      "test-7"
+    );
+    var gotmsg = false;
+
+    ws.onopen = function() {
+      ok(true, "test 7 open");
+    };
+
+    ws.onmessage = function(e) {
+      ok(true, "test 7 message");
+      is(
+        e.origin,
+        "ws://sub2.test2.example.org",
+        "onmessage origin set to ws:// host"
+      );
+      gotmsg = true;
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(gotmsg, "recvd message in test 7 before close");
+      shouldCloseCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test8: client calls close() and the server sends the close frame (with no
+//        code or reason) in acknowledgement;
+function test8() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-8"
+    );
+
+    ws.onopen = function() {
+      is(ws.protocol, "test-8", "test-8 subprotocol selection");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      shouldCloseCleanly(e);
+      // We called close() with no close code: so pywebsocket will also send no
+      // close code, which translates to code 1005
+      is(e.code, 1005, "test-8 close code has wrong value:" + e.code);
+      is(e.reason, "", "test-8 close reason has wrong value:" + e.reason);
+      resolve();
+    };
+  });
+}
+
+// test9: client closes the connection before the ws connection is established;
+function test9() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://test2.example.org/tests/dom/websocket/tests/file_websocket",
+      "test-9"
+    );
+
+    ws._receivedErrorEvent = false;
+
+    ws.onopen = shouldNotOpen;
+
+    ws.onerror = function(e) {
+      ws._receivedErrorEvent = true;
+    };
+
+    ws.onclose = function(e) {
+      ok(ws._receivedErrorEvent, "Didn't received the error event in test 9.");
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+
+    ws.close();
+  });
+}
+
+// test10: client sends a message before the ws connection is established;
+function test10() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://sub1.test1.example.com/tests/dom/websocket/tests/file_websocket",
+      "test-10"
+    );
+
+    ws.onclose = function(e) {
+      shouldCloseCleanly(e);
+      resolve();
+    };
+
+    try {
+      ws.send("client data");
+      ok(false, "Couldn't send data before connecting!");
+    } catch (e) {
+      ok(true, "Couldn't send data before connecting!");
+    }
+
+    ws.onopen = function() {
+      ok(true, "test 10 opened");
+      ws.close();
+    };
+  });
+}
+
+// test11: a simple hello echo;
+function test11() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-11"
+    );
+    is(ws.readyState, 0, "create bad readyState in test-11!");
+
+    ws.onopen = function() {
+      is(ws.readyState, 1, "open bad readyState in test-11!");
+      ws.send("client data");
+    };
+
+    ws.onmessage = function(e) {
+      is(e.data, "server data", "bad received message in test-11!");
+      ws.close(1000, "Have a nice day");
+
+      // this ok() is disabled due to a race condition - it state may have
+      // advanced through 2 (closing) and into 3 (closed) before it is evald
+      // ok(ws.readyState == 2, "onmessage bad readyState in test-11!");
+    };
+
+    ws.onclose = function(e) {
+      is(ws.readyState, 3, "onclose bad readyState in test-11!");
+      shouldCloseCleanly(e);
+      is(e.code, 1000, "test 11 got wrong close code: " + e.code);
+      is(
+        e.reason,
+        "Have a nice day",
+        "test 11 got wrong close reason: " + e.reason
+      );
+      resolve();
+    };
+  });
+}
+
+// test12: client sends a message containing unpaired surrogates
+function test12() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-12"
+    );
+
+    ws.onopen = function() {
+      try {
+        // send an unpaired surrogate
+        ws._gotMessage = false;
+        ws.send("a\ud800b");
+        ok(true, "ok to send an unpaired surrogate");
+      } catch (e) {
+        ok(
+          false,
+          "shouldn't fail any more when sending an unpaired surrogate!"
+        );
+      }
+    };
+
+    ws.onmessage = function(msg) {
+      is(
+        msg.data,
+        "SUCCESS",
+        "Unpaired surrogate in UTF-16 not converted in test-12"
+      );
+      ws._gotMessage = true;
+      // Must support unpaired surrogates in close reason, too
+      ws.close(1000, "a\ud800b");
+    };
+
+    ws.onclose = function(e) {
+      is(ws.readyState, 3, "onclose bad readyState in test-12!");
+      ok(ws._gotMessage, "didn't receive message!");
+      shouldCloseCleanly(e);
+      is(e.code, 1000, "test 12 got wrong close code: " + e.code);
+      is(
+        e.reason,
+        "a\ufffdb",
+        "test 11 didn't get replacement char in close reason: " + e.reason
+      );
+      resolve();
+    };
+  });
+}
+
+// test13: server sends an invalid message;
+function test13() {
+  return new Promise(function(resolve, reject) {
+    // previous versions of this test counted the number of protocol errors
+    // returned, but the protocol stack typically closes down after reporting a
+    // protocol level error - trying to resync is too dangerous
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-13"
+    );
+    ws._timesCalledOnError = 0;
+
+    ws.onerror = function() {
+      ws._timesCalledOnError++;
+    };
+
+    ws.onclose = function(e) {
+      ok(ws._timesCalledOnError > 0, "no error events");
+      resolve();
+    };
+  });
+}
+
+// test14: server sends the close frame, it doesn't close the tcp connection
+//         and it keeps sending normal ws messages;
+function test14() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-14"
+    );
+
+    ws.onmessage = function() {
+      ok(
+        false,
+        "shouldn't received message after the server sent the close frame"
+      );
+    };
+
+    ws.onclose = function(e) {
+      shouldCloseCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test15: server closes the tcp connection, but it doesn't send the close
+//         frame;
+function test15() {
+  return new Promise(function(resolve, reject) {
+    /*
+     * DISABLED: see comments for test-15 case in file_websocket_wsh.py
+     */
+    resolve();
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-15"
+    );
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+
+    // termination of the connection might cause an error event if it happens in OPEN
+    ws.onerror = function() {};
+  });
+}
+
+// test16: client calls close() and tries to send a message;
+function test16() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-16"
+    );
+
+    ws.onopen = function() {
+      ws.close();
+      ok(
+        !ws.send("client data"),
+        "shouldn't send message after calling close()"
+      );
+    };
+
+    ws.onmessage = function() {
+      ok(false, "shouldn't send message after calling close()");
+    };
+
+    ws.onerror = function() {};
+
+    ws.onclose = function() {
+      resolve();
+    };
+  });
+}
+
+// test17: see bug 572975 - all event listeners set
+function test17() {
+  return new Promise(function(resolve, reject) {
+    var status_test17 = "not started";
+
+    var test17func = function() {
+      var local_ws = new WebSocket(
+        "ws://sub1.test2.example.org/tests/dom/websocket/tests/file_websocket",
+        "test-17"
+      );
+      status_test17 = "started";
+
+      local_ws.onopen = function(e) {
+        status_test17 = "opened";
+        e.target.send("client data");
+        forcegc();
+      };
+
+      local_ws.onerror = function() {
+        ok(false, "onerror called on test " + current_test + "!");
+      };
+
+      local_ws.onmessage = function(e) {
+        ok(e.data == "server data", "Bad message in test-17");
+        status_test17 = "got message";
+        forcegc();
+      };
+
+      local_ws.onclose = function(e) {
+        ok(status_test17 == "got message", "Didn't got message in test-17!");
+        shouldCloseCleanly(e);
+        status_test17 = "closed";
+        forcegc();
+        resolve();
+      };
+
+      window._test17 = null;
+      forcegc();
+    };
+
+    window._test17 = test17func;
+    window._test17();
+  });
+}
+
+// The tests that expects that their websockets neither open nor close MUST
+// be in the end of the tests, i.e. HERE, in order to prevent blocking the other
+// tests.
+
+// test18: client tries to connect to an http resource;
+function test18() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket_http_resource.txt"
+    );
+    ws.onopen = shouldNotOpen;
+    ws.onerror = ignoreError;
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test19: server closes the tcp connection before establishing the ws
+//         connection;
+function test19() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-19"
+    );
+    ws.onopen = shouldNotOpen;
+    ws.onerror = ignoreError;
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test20: see bug 572975 - only on error and onclose event listeners set
+function test20() {
+  return new Promise(function(resolve, reject) {
+    var test20func = function() {
+      var local_ws = new WebSocket(
+        "ws://sub1.test1.example.org/tests/dom/websocket/tests/file_websocket",
+        "test-20"
+      );
+
+      local_ws.onerror = function() {
+        ok(false, "onerror called on test " + current_test + "!");
+      };
+
+      local_ws.onclose = function(e) {
+        ok(true, "test 20 closed despite gc");
+        resolve();
+      };
+
+      local_ws = null;
+      window._test20 = null;
+      forcegc();
+    };
+
+    window._test20 = test20func;
+    window._test20();
+  });
+}
+
+// test21: see bug 572975 - same as test 17, but delete strong event listeners
+//         when receiving the message event;
+function test21() {
+  return new Promise(function(resolve, reject) {
+    var test21func = function() {
+      var local_ws = new WebSocket(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "test-21"
+      );
+      var received_message = false;
+
+      local_ws.onopen = function(e) {
+        e.target.send("client data");
+        forcegc();
+        e.target.onopen = null;
+        forcegc();
+      };
+
+      local_ws.onerror = function() {
+        ok(false, "onerror called on test " + current_test + "!");
+      };
+
+      local_ws.onmessage = function(e) {
+        is(e.data, "server data", "Bad message in test-21");
+        received_message = true;
+        forcegc();
+        e.target.onmessage = null;
+        forcegc();
+      };
+
+      local_ws.onclose = function(e) {
+        shouldCloseCleanly(e);
+        ok(received_message, "close transitioned through onmessage");
+        resolve();
+      };
+
+      local_ws = null;
+      window._test21 = null;
+      forcegc();
+    };
+
+    window._test21 = test21func;
+    window._test21();
+  });
+}
+
+// test22: server takes too long to establish the ws connection;
+function test22() {
+  return new Promise(function(resolve, reject) {
+    const pref_open = "network.websocket.timeout.open";
+    SpecialPowers.setIntPref(pref_open, 5);
+
+    var ws = CreateTestWS(
+      "ws://sub2.test2.example.org/tests/dom/websocket/tests/file_websocket",
+      "test-22"
+    );
+
+    ws.onopen = shouldNotOpen;
+    ws.onerror = ignoreError;
+
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+
+    SpecialPowers.clearUserPref(pref_open);
+  });
+}
+
+// test23: should detect WebSocket on window object;
+function test23() {
+  return new Promise(function(resolve, reject) {
+    ok("WebSocket" in window, "WebSocket should be available on window object");
+    resolve();
+  });
+}
+
+// test24: server rejects sub-protocol string
+function test24() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-does-not-exist"
+    );
+
+    ws.onopen = shouldNotOpen;
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+
+    ws.onerror = function() {};
+  });
+}
+
+// test25: ctor with valid empty sub-protocol array
+function test25() {
+  return new Promise(function(resolve, reject) {
+    var prots = [];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    // This test errors because the server requires a sub-protocol, but
+    // the test just wants to ensure that the ctor doesn't generate an
+    // exception
+    ws.onerror = ignoreError;
+    ws.onopen = shouldNotOpen;
+
+    ws.onclose = function(e) {
+      is(ws.protocol, "", "test25 subprotocol selection");
+      ok(true, "test 25 protocol array close");
+      resolve();
+    };
+  });
+}
+
+// test26: ctor with invalid sub-protocol array containing 1 empty element
+function test26() {
+  return new Promise(function(resolve, reject) {
+    var prots = [""];
+
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        prots
+      );
+      ok(false, "testing empty element sub protocol array");
+    } catch (e) {
+      ok(true, "testing empty sub element protocol array");
+    }
+
+    resolve();
+  });
+}
+
+// test27: ctor with invalid sub-protocol array containing an empty element in
+//         list
+function test27() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test27", ""];
+
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        prots
+      );
+      ok(false, "testing empty element mixed sub protocol array");
+    } catch (e) {
+      ok(true, "testing empty element mixed sub protocol array");
+    }
+
+    resolve();
+  });
+}
+
+// test28: ctor using valid 1 element sub-protocol array
+function test28() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test28"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 28 protocol array open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      is(ws.protocol, "test28", "test28 subprotocol selection");
+      ok(true, "test 28 protocol array close");
+      resolve();
+    };
+  });
+}
+
+// test29: ctor using all valid 5 element sub-protocol array
+function test29() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test29a", "test29b"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 29 protocol array open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 29 protocol array close");
+      resolve();
+    };
+  });
+}
+
+// test30: ctor using valid 1 element sub-protocol array with element server
+//         will reject
+function test30() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-does-not-exist"];
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = shouldNotOpen;
+
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      resolve();
+    };
+
+    ws.onerror = function() {};
+  });
+}
+
+// test31: ctor using valid 2 element sub-protocol array with 1 element server
+//         will reject and one server will accept
+function test31() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-does-not-exist", "test31"];
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 31 protocol array open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      is(ws.protocol, "test31", "test31 subprotocol selection");
+      ok(true, "test 31 protocol array close");
+      resolve();
+    };
+  });
+}
+
+// test32: ctor using invalid sub-protocol array that contains duplicate items
+function test32() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test32", "test32"];
+
+    try {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        prots
+      );
+      ok(false, "testing duplicated element sub protocol array");
+    } catch (e) {
+      ok(true, "testing duplicated sub element protocol array");
+    }
+
+    resolve();
+  });
+}
+
+// test33: test for sending/receiving custom close code (but no close reason)
+function test33() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test33"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 33 open");
+      ws.close(3131); // pass code but not reason
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 33 close");
+      shouldCloseCleanly(e);
+      is(e.code, 3131, "test 33 got wrong close code: " + e.code);
+      is(e.reason, "", "test 33 got wrong close reason: " + e.reason);
+      resolve();
+    };
+  });
+}
+
+// test34: test for receiving custom close code and reason
+function test34() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-34"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 34 open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 34 close");
+      ok(e.wasClean, "test 34 closed cleanly");
+      is(e.code, 1001, "test 34 custom server code");
+      is(e.reason, "going away now", "test 34 custom server reason");
+      resolve();
+    };
+  });
+}
+
+// test35: test for sending custom close code and reason
+function test35() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-35a"
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 35a open");
+      ws.close(3500, "my code");
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 35a close");
+      ok(e.wasClean, "test 35a closed cleanly");
+      var wsb = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "test-35b"
+      );
+
+      wsb.onopen = function(event) {
+        ok(true, "test 35b open");
+        wsb.close();
+      };
+
+      wsb.onclose = function(event) {
+        ok(true, "test 35b close");
+        ok(event.wasClean, "test 35b closed cleanly");
+        is(event.code, 3501, "test 35 custom server code");
+        is(event.reason, "my code", "test 35 custom server reason");
+        resolve();
+      };
+    };
+  });
+}
+
+// test36: negative test for sending out of range close code
+function test36() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-36"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 36 open");
+
+      try {
+        ws.close(13200);
+        ok(false, "testing custom close code out of range");
+      } catch (ex) {
+        ok(true, "testing custom close code out of range");
+        ws.close(3200);
+      }
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 36 close");
+      ok(e.wasClean, "test 36 closed cleanly");
+      resolve();
+    };
+  });
+}
+
+// test37: negative test for too long of a close reason
+function test37() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-37"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 37 open");
+
+      try {
+        ws.close(
+          3100,
+          "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
+        );
+        ok(false, "testing custom close reason out of range");
+      } catch (ex) {
+        ok(true, "testing custom close reason out of range");
+        ws.close(
+          3100,
+          "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012"
+        );
+      }
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 37 close");
+      ok(e.wasClean, "test 37 closed cleanly");
+
+      var wsb = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "test-37b"
+      );
+
+      wsb.onopen = function(event) {
+        // now test that a rejected close code and reason dont persist
+        ok(true, "test 37b open");
+        try {
+          wsb.close(
+            3101,
+            "0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123"
+          );
+          ok(false, "testing custom close reason out of range 37b");
+        } catch (ex) {
+          ok(true, "testing custom close reason out of range 37b");
+          wsb.close();
+        }
+      };
+
+      wsb.onclose = function(event) {
+        ok(true, "test 37b close");
+        ok(event.wasClean, "test 37b closed cleanly");
+
+        var wsc = CreateTestWS(
+          "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+          "test-37c"
+        );
+
+        wsc.onopen = function(eventInner) {
+          ok(true, "test 37c open");
+          wsc.close();
+        };
+
+        wsc.onclose = function(eventInner) {
+          isnot(
+            eventInner.code,
+            3101,
+            "test 37c custom server code not present"
+          );
+          is(
+            eventInner.reason,
+            "",
+            "test 37c custom server reason not present"
+          );
+          resolve();
+        };
+      };
+    };
+  });
+}
+
+// test38: ensure extensions attribute is defined
+function test38() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-38"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 38 open");
+      isnot(ws.extensions, undefined, "extensions attribute defined");
+      //  is(ws.extensions, "deflate-stream", "extensions attribute deflate-stream");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 38 close");
+      resolve();
+    };
+  });
+}
+
+// test39: a basic wss:// connectivity test
+function test39() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-39"];
+
+    var ws = CreateTestWS(
+      "wss://example.com/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+    status_test39 = "started";
+
+    ws.onopen = function(e) {
+      status_test39 = "opened";
+      ok(true, "test 39 open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 39 close");
+      is(status_test39, "opened", "test 39 did open");
+      resolve();
+    };
+  });
+}
+
+// test40: negative test for wss:// with no cert
+function test40() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-40"];
+
+    var ws = CreateTestWS(
+      "wss://nocert.example.com/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    status_test40 = "started";
+    ws.onerror = ignoreError;
+
+    ws.onopen = function(e) {
+      status_test40 = "opened";
+      ok(false, "test 40 open");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 40 close");
+      is(status_test40, "started", "test 40 did not open");
+      resolve();
+    };
+  });
+}
+
+// test41: HSTS
+function test41() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://example.com/tests/dom/websocket/tests/file_websocket",
+      "test-41a",
+      1
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 41a open");
+      is(
+        ws.url,
+        "ws://example.com/tests/dom/websocket/tests/file_websocket",
+        "test 41a initial ws should not be redirected"
+      );
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 41a close");
+
+      // Since third-party loads can't set HSTS state, this will not set
+      // HSTS for example.com.
+      var wsb = CreateTestWS(
+        "wss://example.com/tests/dom/websocket/tests/file_websocket",
+        "test-41b",
+        1
+      );
+
+      wsb.onopen = function(event) {
+        ok(true, "test 41b open");
+        wsb.close();
+      };
+
+      wsb.onclose = function(event) {
+        ok(true, "test 41b close");
+
+        // try ws:// again, it should be done over ws:// again
+        var wsc = CreateTestWS(
+          "ws://example.com/tests/dom/websocket/tests/file_websocket",
+          "test-41c"
+        );
+
+        wsc.onopen = function() {
+          ok(true, "test 41c open");
+          is(
+            wsc.url,
+            "ws://example.com/tests/dom/websocket/tests/file_websocket",
+            "test 41c ws should not be redirected by hsts to wss"
+          );
+          wsc.close();
+        };
+
+        wsc.onclose = function() {
+          ok(true, "test 41c close");
+          resolve();
+        };
+      };
+    };
+  });
+}
+
+// test42: non-char utf-8 sequences
+function test42() {
+  return new Promise(function(resolve, reject) {
+    // test some utf-8 non-characters. They should be allowed in the
+    // websockets context. Test via round trip echo.
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-42"
+    );
+    var data = ["U+FFFE \ufffe", "U+FFFF \uffff", "U+10FFFF \udbff\udfff"];
+    var index = 0;
+
+    ws.onopen = function() {
+      ws.send(data[0]);
+      ws.send(data[1]);
+      ws.send(data[2]);
+    };
+
+    ws.onmessage = function(e) {
+      is(
+        e.data,
+        data[index],
+        "bad received message in test-42! index=" + index
+      );
+      index++;
+      if (index == 3) {
+        ws.close();
+      }
+    };
+
+    ws.onclose = function(e) {
+      resolve();
+    };
+  });
+}
+
+// test43: Test setting binaryType attribute
+function test43() {
+  return new Promise(function(resolve, reject) {
+    var prots = ["test-43"];
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      prots
+    );
+
+    ws.onopen = function(e) {
+      ok(true, "test 43 open");
+      // Test binaryType setting
+      ws.binaryType = "arraybuffer";
+      ws.binaryType = "blob";
+      ws.binaryType = ""; // illegal
+      is(ws.binaryType, "blob");
+      ws.binaryType = "ArrayBuffer"; // illegal
+      is(ws.binaryType, "blob");
+      ws.binaryType = "Blob"; // illegal
+      is(ws.binaryType, "blob");
+      ws.binaryType = "mcfoofluu"; // illegal
+      is(ws.binaryType, "blob");
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "test 43 close");
+      resolve();
+    };
+  });
+}
+
+// test44: Test sending/receving binary ArrayBuffer
+function test44() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-44"
+    );
+    is(ws.readyState, 0, "bad readyState in test-44!");
+    ws.binaryType = "arraybuffer";
+
+    ws.onopen = function() {
+      is(ws.readyState, 1, "open bad readyState in test-44!");
+      var buf = new ArrayBuffer(3);
+      // create byte view
+      var view = new Uint8Array(buf);
+      view[0] = 5;
+      view[1] = 0; // null byte
+      view[2] = 7;
+      ws.send(buf);
+    };
+
+    ws.onmessage = function(e) {
+      ok(e.data instanceof ArrayBuffer, "Should receive an arraybuffer!");
+      var view = new Uint8Array(e.data);
+      ok(
+        view.length == 2 && view[0] == 0 && view[1] == 4,
+        "testing Reply arraybuffer"
+      );
+      ws.close();
+    };
+
+    ws.onclose = function(e) {
+      is(ws.readyState, 3, "onclose bad readyState in test-44!");
+      shouldCloseCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test45: Test sending/receving binary Blob
+function test45() {
+  return new Promise(function(resolve, reject) {
+    function test45Real(blobFile) {
+      var ws = CreateTestWS(
+        "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+        "test-45"
+      );
+      is(ws.readyState, 0, "bad readyState in test-45!");
+      // ws.binaryType = "blob";  // Don't need to specify: blob is the default
+
+      ws.onopen = function() {
+        is(ws.readyState, 1, "open bad readyState in test-45!");
+        ws.send(blobFile);
+      };
+
+      var test45blob;
+
+      ws.onmessage = function(e) {
+        test45blob = e.data;
+        ok(test45blob instanceof Blob, "We should be receiving a Blob");
+
+        ws.close();
+      };
+
+      ws.onclose = function(e) {
+        is(ws.readyState, 3, "onclose bad readyState in test-45!");
+        shouldCloseCleanly(e);
+
+        // check blob contents
+        var reader = new FileReader();
+        reader.onload = function(event) {
+          is(
+            reader.result,
+            "flob",
+            "response should be 'flob': got '" + reader.result + "'"
+          );
+        };
+
+        reader.onerror = function(event) {
+          testFailed("Failed to read blob: error code = " + reader.error.code);
+        };
+
+        reader.onloadend = function(event) {
+          resolve();
+        };
+
+        reader.readAsBinaryString(test45blob);
+      };
+    }
+
+    SpecialPowers.createFiles(
+      [{ name: "testBlobFile", data: "flob" }],
+      function(files) {
+        test45Real(files[0]);
+      },
+      function(msg) {
+        testFailed("Failed to create file for test45: " + msg);
+        resolve();
+      }
+    );
+  });
+}
+
+// test46: Test that we don't dispatch incoming msgs once in CLOSING state
+function test46() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-46"
+    );
+    is(ws.readyState, 0, "create bad readyState in test-46!");
+
+    ws.onopen = function() {
+      is(ws.readyState, 1, "open bad readyState in test-46!");
+      ws.close();
+      is(ws.readyState, 2, "close must set readyState to 2 in test-46!");
+    };
+
+    ws.onmessage = function(e) {
+      ok(false, "received message after calling close in test-46!");
+    };
+
+    ws.onclose = function(e) {
+      is(ws.readyState, 3, "onclose bad readyState in test-46!");
+      shouldCloseCleanly(e);
+      resolve();
+    };
+  });
+}
+
+// test47: Make sure onerror/onclose aren't called during close()
+function test47() {
+  return new Promise(function(resolve, reject) {
+    var hasError = false;
+    var ws = CreateTestWS(
+      "ws://another.websocket.server.that.probably.does.not.exist"
+    );
+
+    ws.onopen = shouldNotOpen;
+
+    ws.onerror = function(e) {
+      is(
+        ws.readyState,
+        3,
+        "test-47: readyState should be CLOSED(3) in onerror: got " +
+          ws.readyState
+      );
+      ok(!ws._withinClose, "onerror() called during close()!");
+      hasError = true;
+    };
+
+    ws.onclose = function(e) {
+      shouldCloseNotCleanly(e);
+      ok(hasError, "test-47: should have called onerror before onclose");
+      is(
+        ws.readyState,
+        3,
+        "test-47: readyState should be CLOSED(3) in onclose: got " +
+          ws.readyState
+      );
+      ok(!ws._withinClose, "onclose() called during close()!");
+      is(e.code, 1006, "test-47 close code should be 1006 but is:" + e.code);
+      resolve();
+    };
+
+    // Call close before we're connected: throws error
+    // Make sure we call onerror/onclose asynchronously
+    ws._withinClose = 1;
+    ws.close(3333, "Closed before we were open: error");
+    ws._withinClose = 0;
+    is(
+      ws.readyState,
+      2,
+      "test-47: readyState should be CLOSING(2) after close(): got " +
+        ws.readyState
+    );
+  });
+}
+
+// test48: see bug 1227136 - client calls close() from onopen() and waits until
+// WebSocketChannel::mSocketIn is nulled out on socket thread.
+function test48() {
+  return new Promise(function(resolve, reject) {
+    const pref_close = "network.websocket.timeout.close";
+    SpecialPowers.setIntPref(pref_close, 1);
+
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-48"
+    );
+
+    ws.onopen = function() {
+      ws.close();
+
+      var date = new Date();
+      var curDate = null;
+      do {
+        curDate = new Date();
+      } while (curDate - date < 1500);
+    };
+
+    ws.onclose = function(e) {
+      ok(true, "ws close in test 48");
+      resolve();
+    };
+
+    SpecialPowers.clearUserPref(pref_close);
+  });
+}
+
+function test49() {
+  return new Promise(function(resolve, reject) {
+    var ws = CreateTestWS(
+      "ws://mochi.test:8888/tests/dom/websocket/tests/file_websocket",
+      "test-49"
+    );
+    var gotError = 0;
+    ok(ws.readyState == 0, "create bad readyState in test-49!");
+
+    ws.onopen = function() {
+      ok(false, "Connection must fail in test-49");
+    };
+
+    ws.onerror = function(e) {
+      gotError = 1;
+    };
+
+    ws.onclose = function(e) {
+      ok(gotError, "Should get error in test-49!");
+      resolve();
+    };
+  });
+}
diff --git a/dom/websocket/tests/websocket_worker1.js b/dom/websocket/tests/websocket_worker1.js
new file mode 100644
index 0000000000..26b37b8e48
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker1.js
@@ -0,0 +1,19 @@
+importScripts("websocket_helpers.js");
+importScripts("websocket_tests.js");
+importScripts("websocket_worker_helpers.js");
+
+var tests = [
+  test1, // client tries to connect to a http scheme location;
+  test2, // assure serialization of the connections;
+  test3, // client tries to connect to an non-existent ws server;
+  test4, // client tries to connect using a relative url;
+  test5, // client uses an invalid protocol value;
+  test6, // counter and encoding check;
+  test7, // onmessage event origin property check
+  test8, // client calls close() and the server sends the close frame (with no
+  // code or reason) in acknowledgement;
+  test9, // client closes the connection before the ws connection is established;
+  test10, // client sends a message before the ws connection is established;
+];
+
+doTest();
diff --git a/dom/websocket/tests/websocket_worker2.js b/dom/websocket/tests/websocket_worker2.js
new file mode 100644
index 0000000000..fbc4591bdb
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker2.js
@@ -0,0 +1,19 @@
+importScripts("websocket_helpers.js");
+importScripts("websocket_tests.js");
+importScripts("websocket_worker_helpers.js");
+
+var tests = [
+  test11, // a simple hello echo;
+  test12, // client sends a message containing unpaired surrogates
+  test13, //server sends an invalid message;
+  test14, // server sends the close frame, it doesn't close the tcp connection
+  // and it keeps sending normal ws messages;
+  test15, // server closes the tcp connection, but it doesn't send the close
+  // frame;
+  test16, // client calls close() and tries to send a message;
+  test18, // client tries to connect to an http resource;
+  test19, // server closes the tcp connection before establishing the ws
+  // connection;
+];
+
+doTest();
diff --git a/dom/websocket/tests/websocket_worker3.js b/dom/websocket/tests/websocket_worker3.js
new file mode 100644
index 0000000000..8fee7f4ca5
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker3.js
@@ -0,0 +1,17 @@
+importScripts("websocket_helpers.js");
+importScripts("websocket_tests.js");
+importScripts("websocket_worker_helpers.js");
+
+var tests = [
+  test24, // server rejects sub-protocol string
+  test25, // ctor with valid empty sub-protocol array
+  test26, // ctor with invalid sub-protocol array containing 1 empty element
+  test27, // ctor with invalid sub-protocol array containing an empty element in
+  // list
+  test28, // ctor using valid 1 element sub-protocol array
+  test29, // ctor using all valid 5 element sub-protocol array
+  test30, // ctor using valid 1 element sub-protocol array with element server
+  // will reject
+];
+
+doTest();
diff --git a/dom/websocket/tests/websocket_worker4.js b/dom/websocket/tests/websocket_worker4.js
new file mode 100644
index 0000000000..3e3408b019
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker4.js
@@ -0,0 +1,19 @@
+importScripts("websocket_helpers.js");
+importScripts("websocket_tests.js");
+importScripts("websocket_worker_helpers.js");
+
+var tests = [
+  test31, // ctor using valid 2 element sub-protocol array with 1 element server
+  // will reject and one server will accept
+  test32, // ctor using invalid sub-protocol array that contains duplicate items
+  test33, // test for sending/receiving custom close code (but no close reason)
+  test34, // test for receiving custom close code and reason
+  test35, // test for sending custom close code and reason
+  test36, // negative test for sending out of range close code
+  test37, // negative test for too long of a close reason
+  test38, // ensure extensions attribute is defined
+  test39, // a basic wss:// connectivity test
+  test40, // negative test for wss:// with no cert
+];
+
+doTest();
diff --git a/dom/websocket/tests/websocket_worker5.js b/dom/websocket/tests/websocket_worker5.js
new file mode 100644
index 0000000000..0ed1bbd486
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker5.js
@@ -0,0 +1,14 @@
+importScripts("websocket_helpers.js");
+importScripts("websocket_tests.js");
+importScripts("websocket_worker_helpers.js");
+
+var tests = [
+  test42, // non-char utf-8 sequences
+  test43, // Test setting binaryType attribute
+  test44, // Test sending/receving binary ArrayBuffer
+  test46, // Test that we don't dispatch incoming msgs once in CLOSING state
+  test47, // Make sure onerror/onclose aren't called during close()
+  test49, // Test that we fail if subprotocol returned from server doesn't match
+];
+
+doTest();
diff --git a/dom/websocket/tests/websocket_worker_helpers.js b/dom/websocket/tests/websocket_worker_helpers.js
new file mode 100644
index 0000000000..e9c55b1009
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker_helpers.js
@@ -0,0 +1,27 @@
+function feedback() {
+  postMessage({
+    type: "feedback",
+    msg:
+      "executing test: " +
+      (current_test + 1) +
+      " of " +
+      tests.length +
+      " tests.",
+  });
+}
+
+function ok(status, msg) {
+  postMessage({ type: "status", status: !!status, msg });
+}
+
+function is(a, b, msg) {
+  ok(a === b, msg);
+}
+
+function isnot(a, b, msg) {
+  ok(a != b, msg);
+}
+
+function finish() {
+  postMessage({ type: "finish" });
+}
diff --git a/dom/websocket/tests/websocket_worker_https.html b/dom/websocket/tests/websocket_worker_https.html
new file mode 100644
index 0000000000..0eb17af65b
--- /dev/null
+++ b/dom/websocket/tests/websocket_worker_https.html
@@ -0,0 +1,14 @@
+
+
diff --git a/dom/websocket/tests/window_bug1384658.html b/dom/websocket/tests/window_bug1384658.html
new file mode 100644
index 0000000000..c2d6e16c8d
--- /dev/null
+++ b/dom/websocket/tests/window_bug1384658.html
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
diff --git a/dom/websocket/tests/window_websocket_wss.html b/dom/websocket/tests/window_websocket_wss.html
new file mode 100644
index 0000000000..391ab74e40
--- /dev/null
+++ b/dom/websocket/tests/window_websocket_wss.html
@@ -0,0 +1,65 @@
+
+Creating WebSocket
+
+
+
-- 
cgit v1.2.3