diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 357620e..90b9d53 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -2769,10 +2769,19 @@ function connect()
 	    useToplevelWindows = true;
     }
 
+    var loc = window.location.toString().replace("http:", "ws:");
+    loc = loc.substr(0, loc.lastIndexOf('/')) + "/socket";
+    var ws = null;
+
     if ("WebSocket" in window) {
-	var loc = window.location.toString().replace("http:", "ws:");
-	loc = loc.substr(0, loc.lastIndexOf('/')) + "/socket";
-	var ws = new WebSocket(loc, "broadway");
+	ws = new WebSocket(loc, "broadway");
+    } else if ("MozWebSocket" in window) { // Firefox 6
+	ws = new MozWebSocket(loc);
+    } else {
+	alert("WebSocket not supported, input will not work!");
+	return;
+    }
+
 	ws.onopen = function() {
 	    inputSocket = ws;
 	    var w, h;
@@ -2797,9 +2806,7 @@ function connect()
 	ws.onmessage = function(event) {
 	    handleMessage(event.data);
 	};
-    } else {
-	alert("WebSocket not supported, input will not work!");
-    }
+
     setupDocument(document);
     window.onunload = function (ev) {
 	for (var i = 0; i < toplevelWindows.length; i++)
diff --git a/gdk/broadway/gdkdisplay-broadway.c b/gdk/broadway/gdkdisplay-broadway.c
index c0431bc..a0e202a 100644
--- a/gdk/broadway/gdkdisplay-broadway.c
+++ b/gdk/broadway/gdkdisplay-broadway.c
@@ -537,6 +537,36 @@ send_error (HttpRequest *request,
   http_request_free (request);
 }
 
+/* magic from: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17 */
+#define SEC_WEB_SOCKET_KEY_MAGIC "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
+
+/* 'x3JJHMbDL1EzLkh9GBhXDw==' generates 'HSmrc0sMlYUkAGmm5OPpG2HaGWk=' */
+static gchar *
+generate_handshake_response_wsietf_v7 (const gchar *key)
+{
+  guchar *digest;
+  gsize digest_len;
+  guchar* full_key;
+  GChecksum *checksum;
+
+  full_key = (guchar *)g_strconcat (key, SEC_WEB_SOCKET_KEY_MAGIC, NULL);
+
+  checksum = g_checksum_new (G_CHECKSUM_SHA1);
+  if (!checksum)
+    return NULL;
+
+  g_checksum_update (checksum, full_key, strlen ((char *)full_key));
+
+  digest = g_alloca (g_checksum_type_get_length (G_CHECKSUM_SHA1) + 1);
+  g_checksum_get_digest (checksum, digest, &digest_len);
+  g_checksum_free (checksum);
+  gchar* result = g_base64_encode (digest, digest_len);
+
+  g_free (full_key);
+
+  return result;
+}
+
 static void
 start_input (HttpRequest *request)
 {
@@ -556,6 +586,7 @@ start_input (HttpRequest *request)
   const void *data_buffer;
   gsize data_buffer_size;
   GInputStream *in;
+  char *key_v7;
 
   broadway_display = GDK_BROADWAY_DISPLAY (request->display);
 
@@ -605,6 +636,10 @@ start_input (HttpRequest *request)
 	  key2 /= num_space;
 	  num_key2++;
 	}
+      else if ((p = parse_line (lines[i], "Sec-WebSocket-Key")))
+	{
+	  key_v7 = p;
+	}
       else if ((p = parse_line (lines[i], "Origin")))
 	{
 	  origin = p;
@@ -615,6 +650,23 @@ start_input (HttpRequest *request)
 	}
     }
 
+  if (key_v7 != NULL)
+    {
+      char* accept = generate_handshake_response_wsietf_v7 (key_v7);
+      res = g_strdup_printf ("HTTP/1.1 101 Switching Protocols\r\n"
+			     "Upgrade: websocket\r\n"
+			     "Connection: Upgrade\r\n"
+			     "Sec-WebSocket-Accept: %s\r\n"
+			     "Sec-WebSocket-Protocol: chat\r\n"
+			     "\r\n", accept);
+      g_free (accept);
+
+      g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
+				 res, strlen (res), NULL, NULL, NULL);
+      g_free (res);
+    }
+  else
+    {
   if (num_key1 != 1 || num_key2 != 1 || origin == NULL || host == NULL)
     {
       g_strfreev (lines);
@@ -658,6 +710,7 @@ start_input (HttpRequest *request)
   g_free (res);
   g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (request->connection)),
 			     challenge, 16, NULL, NULL, NULL);
+    }
 
   input = g_new0 (BroadwayInput, 1);
 
