Bug 1190349 - Update web-platform-tests to revision 2bd8c7dcf2e216e58ece63491f31b5d087ec740e, a=testonly
authorJames Graham <james@hoppipolla.co.uk>
Mon, 03 Aug 2015 10:49:53 +0100
changeset 287551 9b96fb4b36525282e10aea7defc9f7f8869c1b3d
parent 287550 10ed10f5e05e2f2a44e7668f49ac37f0ed7f42cc
child 287552 e9e8affa4d6ffdf0c3538279ee0c3033dfaf0f52
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1190349
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1190349 - Update web-platform-tests to revision 2bd8c7dcf2e216e58ece63491f31b5d087ec740e, a=testonly
testing/web-platform/meta/MANIFEST.json
testing/web-platform/meta/mozilla-sync
testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html
testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js
testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js
testing/web-platform/tests/docs/css-metadata.md
testing/web-platform/tests/docs/css-user-styles.md
testing/web-platform/tests/docs/reftests.md
testing/web-platform/tests/docs/review-process.md
testing/web-platform/tests/docs/running_tests.md
testing/web-platform/tests/docs/test-format-guidelines.md
testing/web-platform/tests/docs/test-style-guidelines.md
testing/web-platform/tests/dom/nodes/ChildNode-after.html
testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html
testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml
testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled.html
testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html
testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html
testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html.headers
testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html.headers
testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html
testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html.headers
testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
testing/web-platform/tests/mixed-content/generic/common.js
testing/web-platform/tests/mixed-content/generic/expect.py
testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js
testing/web-platform/tests/mixed-content/spec.src.json
testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
testing/web-platform/tests/tools/runner/index.html
testing/web-platform/tests/tools/runner/runner.js
testing/web-platform/tests/tools/serve/serve.py
testing/web-platform/tests/tools/wptserve/wptserve/handlers.py
testing/web-platform/tests/tools/wptserve/wptserve/stash.py
testing/web-platform/tests/websockets/Close-clamp.htm
testing/web-platform/tests/websockets/handlers/stash_responder_wsh.py
--- a/testing/web-platform/meta/MANIFEST.json
+++ b/testing/web-platform/meta/MANIFEST.json
@@ -16863,18 +16863,22 @@
         "path": "html/semantics/forms/the-datalist-element/datalistoptions.html",
         "url": "/html/semantics/forms/the-datalist-element/datalistoptions.html"
       },
       {
         "path": "html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html",
         "url": "/html/semantics/forms/the-fieldset-element/HTMLFieldSetElement.html"
       },
       {
-        "path": "html/semantics/forms/the-fieldset-element/disabled.html",
-        "url": "/html/semantics/forms/the-fieldset-element/disabled.html"
+        "path": "html/semantics/forms/the-fieldset-element/disabled-001.html",
+        "url": "/html/semantics/forms/the-fieldset-element/disabled-001.html"
+      },
+      {
+        "path": "html/semantics/forms/the-fieldset-element/disabled-002.xhtml",
+        "url": "/html/semantics/forms/the-fieldset-element/disabled-002.xhtml"
       },
       {
         "path": "html/semantics/forms/the-form-element/form-autocomplete.html",
         "url": "/html/semantics/forms/the-form-element/form-autocomplete.html"
       },
       {
         "path": "html/semantics/forms/the-form-element/form-elements-interfaces-01.html",
         "url": "/html/semantics/forms/the-form-element/form-elements-interfaces-01.html"
@@ -17031,16 +17035,20 @@
         "path": "html/semantics/forms/the-label-element/label-attributes.html",
         "url": "/html/semantics/forms/the-label-element/label-attributes.html"
       },
       {
         "path": "html/semantics/forms/the-label-element/labelable-elements.html",
         "url": "/html/semantics/forms/the-label-element/labelable-elements.html"
       },
       {
+        "path": "html/semantics/forms/the-legend-element/legend-form.html",
+        "url": "/html/semantics/forms/the-legend-element/legend-form.html"
+      },
+      {
         "path": "html/semantics/forms/the-meter-element/meter.html",
         "url": "/html/semantics/forms/the-meter-element/meter.html"
       },
       {
         "path": "html/semantics/forms/the-option-element/option-label.html",
         "url": "/html/semantics/forms/the-option-element/option-label.html"
       },
       {
@@ -18239,16 +18247,24 @@
         "path": "mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html"
       },
       {
         "path": "mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/http-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html"
       },
       {
+        "path": "mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html",
+        "url": "/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html"
+      },
+      {
+        "path": "mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html",
+        "url": "/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html"
+      },
+      {
         "path": "mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/meta-csp/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html"
       },
       {
         "path": "mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/meta-csp/same-host-https/fetch-request/top-level/no-redirect/allowed.https.html"
       },
       {
@@ -18291,16 +18307,20 @@
         "path": "mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/meta-csp/same-host-https/worker-request/top-level/no-redirect/allowed.https.html"
       },
       {
         "path": "mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/meta-csp/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html"
       },
       {
+        "path": "mixed-content/allowed/meta-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html",
+        "url": "/mixed-content/allowed/meta-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html"
+      },
+      {
         "path": "mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/keep-scheme-redirect/allowed.https.html"
       },
       {
         "path": "mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/no-opt-in/same-host-https/audio-tag/top-level/no-redirect/allowed.https.html"
       },
       {
@@ -18395,16 +18415,24 @@
         "path": "mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/keep-scheme-redirect/allowed.https.html"
       },
       {
         "path": "mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html",
         "url": "/mixed-content/allowed/no-opt-in/same-host-https/xhr-request/top-level/no-redirect/allowed.https.html"
       },
       {
+        "path": "mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html",
+        "url": "/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html"
+      },
+      {
+        "path": "mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html",
+        "url": "/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html"
+      },
+      {
         "path": "mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
@@ -18503,16 +18531,28 @@
         "path": "mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/keep-scheme-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
@@ -18611,16 +18651,28 @@
         "path": "mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/http-csp/same-host-http/xhr-request/top-level/swap-scheme-redirect/opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/cross-origin-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/cross-origin-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
@@ -18647,16 +18699,20 @@
         "path": "mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/cross-origin-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/cross-origin-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/meta-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/meta-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/same-host-http/fetch-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/same-host-http/form-tag/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
@@ -18683,16 +18739,20 @@
         "path": "mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/same-host-http/worker-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/meta-csp/same-host-http/xhr-request/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/meta-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/meta-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/cross-origin-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html"
       },
       {
@@ -18791,16 +18851,28 @@
         "path": "mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/cross-origin-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/keep-scheme-redirect/no-opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/same-host-http/fetch-request/top-level/no-redirect/no-opt-in-blocks.https.html"
       },
       {
@@ -18899,16 +18971,28 @@
         "path": "mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/no-redirect/no-opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html",
         "url": "/mixed-content/blockable/no-opt-in/same-host-http/xhr-request/top-level/swap-scheme-redirect/no-opt-in-blocks.https.html"
       },
       {
+        "path": "mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
+        "path": "mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html",
+        "url": "/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html"
+      },
+      {
         "path": "mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/keep-scheme-redirect/opt-in-blocks.https.html"
       },
       {
         "path": "mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html",
         "url": "/mixed-content/optionally-blockable/http-csp/cross-origin-http/audio-tag/top-level/no-redirect/opt-in-blocks.https.html"
       },
       {
@@ -25695,16 +25779,20 @@
         "path": "websockets/Close-NaN.htm",
         "url": "/websockets/Close-NaN.htm"
       },
       {
         "path": "websockets/Close-Reason-124Bytes.htm",
         "url": "/websockets/Close-Reason-124Bytes.htm"
       },
       {
+        "path": "websockets/Close-clamp.htm",
+        "url": "/websockets/Close-clamp.htm"
+      },
+      {
         "path": "websockets/Close-null.htm",
         "url": "/websockets/Close-null.htm"
       },
       {
         "path": "websockets/Close-reason-unpaired-surrogates.htm",
         "url": "/websockets/Close-reason-unpaired-surrogates.htm"
       },
       {
@@ -34109,12 +34197,12 @@
             "/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped-ref.html",
             "=="
           ]
         ],
         "url": "/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html"
       }
     ]
   },
-  "rev": "4bc69f287365a67585d470300a2ef109689cf465",
+  "rev": "2bd8c7dcf2e216e58ece63491f31b5d087ec740e",
   "url_base": "/",
   "version": 2
 }
\ No newline at end of file
--- a/testing/web-platform/meta/mozilla-sync
+++ b/testing/web-platform/meta/mozilla-sync
@@ -1,1 +1,1 @@
-757fde6c364d5c1ae56ad135b1ffe15bf455e5ff
\ No newline at end of file
+a5c1cbd20982ee041f870d3833728768ef095b40
\ No newline at end of file
--- a/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html
+++ b/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.html
@@ -4,11 +4,10 @@
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src=XMLHttpRequest-withCredentials.js></script>
 <link rel="help" href="https://xhr.spec.whatwg.org/#the-withcredentials-attribute"
       data-tested-assertations="following::ol/li[1] following::ol/li[2]
                                 following::ol/li[3] following::ol/li[4]">
 <div id="log"></div>
 <script>
-setup({ explicit_done: true })
 test_withCredentials(false)
 </script>
--- a/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js
+++ b/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.js
@@ -22,22 +22,27 @@ function test_withCredentials(worker) {
     } else {
       assert_throws("InvalidAccessError", function() {
         client.withCredentials = true
       })
       assert_false(client.withCredentials, "set in OPEN state")
     }
   }, "setting on synchronous XHR")
 
-  async_test("setting withCredentials when not in UNSENT, OPENED state").step(function() {
-    this.add_cleanup(done)
+  async_test(function() {
     var client = new XMLHttpRequest()
     client.open("GET", "resources/delay.py?ms=1000")
     client.send()
     assert_throws("InvalidStateError", function() { client.withCredentials = true })
     client.onreadystatechange = this.step_func(function() {
       assert_throws("InvalidStateError", function() { client.withCredentials = true })
       if (client.readyState === 4) {
         this.done()
       }
     })
-  })
+  }, "setting withCredentials when not in UNSENT, OPENED state (asynchronous)")
+
+  test(function() {
+    var client = new XMLHttpRequest()
+    client.open("GET", "resources/delay.py?ms=1000", false)
+    assert_throws("InvalidStateError", function() { client.withCredentials = true })
+  }, "setting withCredentials when in DONE state (synchronous)")
 }
--- a/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js
+++ b/testing/web-platform/tests/XMLHttpRequest/XMLHttpRequest-withCredentials.worker.js
@@ -1,3 +1,4 @@
 importScripts("/resources/testharness.js")
 importScripts("XMLHttpRequest-withCredentials.js")
 test_withCredentials(true);
+done()
--- a/testing/web-platform/tests/docs/css-metadata.md
+++ b/testing/web-platform/tests/docs/css-metadata.md
@@ -368,18 +368,18 @@ The assertion should not be:
 * A copy of the test verification instructions
 * A duplicate of another assertion in the test suite
 * A line or reference from the CSS specification unless that line is
   a complete assertion when taken out of context.
 
 The test assertion is **optional**. It helps the reviewer understand
 the goal of the test so that he or she can make sure it is being
 tested correctly. Also, in case a problem is found with the test
-later, the testing method (e.g. using 'color' to determine pass/fail)
-can be changed (e.g. to using 'background-color') while preserving
+later, the testing method (e.g. using `color` to determine pass/fail)
+can be changed (e.g. to using `background-color`) while preserving
 the intent of the test (e.g. testing support for ID selectors).
 
 Examples of good test assertions:
 
 * "This test checks that a background image with no intrinsic size
    covers the entire padding box."
 * "This test checks that 'word-spacing' affects each space (U+0020)
   and non-breaking space (U+00A0)."
--- a/testing/web-platform/tests/docs/css-user-styles.md
+++ b/testing/web-platform/tests/docs/css-user-styles.md
@@ -47,39 +47,42 @@ Harness userstyle flag NOT found:
 ``` html
 <p id="user-stylesheet-indication" class="nouserstyle">A user style
 sheet is applied.</p>
 ```
 
 Within the test case it is recommended that the case itself indicate
 the necessary user style sheet that is required.
 
-Examples: (code for the cascade.css file)
+Examples: (code for the [`cascade.css`][cascade-css] file)
 
 ``` css
 #cascade /* ID name should match user style sheet file name */
 {
     /* Used by the test to hide the prerequisite */
     display: none;
 }
 ```
 
 The rule ```#cascade``` in the example above is used by the test
 page to hide the prerequisite text. The rule name should match the
 user style sheet CSS file name in order to keep this orderly.
 
-Examples: (code for the cascade-### XHTML files)
+Examples: (code for [the `cascade-###.xht` files][cascade-xht])
 
 ``` html
 <p id="cascade">
     PREREQUISITE: The <a href="support/cascade.css">
     "cascade.css"</a> file is enabled as the user agent's user style
     sheet.
 </p>
 ```
 
 The id value should match the user style sheet CSS file name and the
 user style sheet rule that is used to hide this text when the style
 sheet is properly applied.
 
 Please flag test that require user style sheets with the userstyle
 flag so people running the tests know that a user style sheet is
 required.
+
+[cascade-css]: https://github.com/w3c/csswg-test/blob/master/css21/cascade/support/cascade.css
+[cascade-xht]: https://github.com/w3c/csswg-test/blob/master/css21/cascade/cascade-001.xht
--- a/testing/web-platform/tests/docs/reftests.md
+++ b/testing/web-platform/tests/docs/reftests.md
@@ -42,18 +42,18 @@ encouraged since it permits optimization
 
 ## Controlling When Comparison Occurs
 
 By default reftest screenshots are taken in response to the `load`
 event firing. In some cases it is necessary to delay the screenshot
 later than this, for example becase some DOM manipulation is
 required to set up the desired test conditions. To enable this, the
 test may have a `class="reftest-wait"` attribute specified on the root
-element. This will cause the screenshot to be delayed until the load
-event has fired and the reftest-wait class has been removed from the
+element. This will cause the screenshot to be delayed until the `load`
+event has fired and the `reftest-wait` class has been removed from the
 root element (technical note: the implementation in wptrunner uses
 mutation observers so the screenshot will be triggered in the
 microtask checkpoint after the class is removed. Because the harness
 isn't synchronized with the browser event loop it is dangerous to rely
 on precise timing here).
 
 ## Matching Multiple References
 
@@ -61,22 +61,22 @@ Sometimes it is desirable for a file to 
 in rare cases, to allow it to match more than one possible
 reference. Note: *this is not currently supported by test runners and
 so best avoided if possible until that support improves*.
 
 Multiple references linked from a single file are interpreted as
 multiple possible renderings for that file. `<link rel=[mis]match>`
 elements in a reference create further conditions that must be met in
 order for the test to pass. For example, consider a situation where
-a.html has `<link rel=match href=b.html>` and `<link rel=match
-href=c.html>`, b.html has `<link rel=match href=b1.html>` and c.html
+`a.html` has `<link rel=match href=b.html>` and `<link rel=match
+href=c.html>`, `b.html` has `<link rel=match href=b1.html>` and `c.html`
 has `<link rel=mismatch href=c1.html>`. In this case, to pass we must
-either have a.html, b.html and b1.html all rendering identically, or
-a.html and c.html rendering identically, but c.html rendering
-differently from c1.html.
+either have `a.html`, `b.html` and `b1.html` all rendering identically, or
+`a.html` and `c.html` rendering identically, but `c.html` rendering
+differently from `c1.html`.
 
 ## Fuzzy Matching
 
 In some situations a test may have subtle differences in rendering
 compared to the reference due to e.g. antialiasing. This may cause the
 test to pass on some platforms but fail on others. In this case some
 affordance for subtle discrepancies is desirable. However no mechanism
 to allow this has yet been standardized.
--- a/testing/web-platform/tests/docs/review-process.md
+++ b/testing/web-platform/tests/docs/review-process.md
@@ -19,32 +19,32 @@ is available.
 
 All new code submissions must use the GitHub pull request
 workflow. The GitHub UI for code review may be used, but other tools
 may also be used as long as the review is clearly linked.
 
 ### Critic
 
 [Critic][critic] is a code review tool that is frequently used for
-reviewing web-platform-tests sumbissions. Although it has a steeper
+reviewing web-platform-tests submissions. Although it has a steeper
 learning curve than the GitHub tools, it has more features that aid in
 conducting non-trivial reviews.
 
 If you want to use Critic to review code, visit the [homepage][critic]
 and log (authentication is via GitHub). On the homepage, click "Add
 Filter". In the resulting dialog, select the web-platform-tests
 repository and add the path of the folder(s) where you want to review
 code, e.g. `/` to review any submissions or `XMLHttpRequest/` to
-review only submissions in the XHMLHttpRequest directory. Ensure that
+review only submissions in the `XHMLHttpRequest` directory. Ensure that
 your email address is added so that you receive notifications of new
 reviews matching your filters, and activity on existing reviews.
 
 ## Labels
 
-Pull requests get automatically labelled in the Github repository. Check
+Pull requests get automatically labelled in the GitHub repository. Check
 out the [list of labels in Github][issues]
 to see the open pull requests for a given specification or a given Working Group.
 
 ## Status
 
 The
 [web-platform-tests dashboard](http://testthewebforward.org/dashboard/#all)
 shows the number of open review requests, and can be filtered by testsuite.
--- a/testing/web-platform/tests/docs/running_tests.md
+++ b/testing/web-platform/tests/docs/running_tests.md
@@ -21,14 +21,14 @@ edge-cases like tests that cause the bro
 
 ## By Automating the Browser
 
 For automated test running designed to be robust enough to use in a CI
 environment, the [wptrunner](http://github.com/w3c/wptrunner) test runner
 can be used. This is a test runner written in Python and designed to
 control the browser from the outside using some remote control
 protocol such as WebDriver. This allows it to handle cases such as the
-browser crashing that connot be handled by an in-browser harness. It
+browser crashing that cannot be handled by an in-browser harness. It
 also has the ability to automatically run both testharness-based tests
 and reftests.
 
 Full instructions for using wptrunner are provided in its own
 [documentation](http://wptrunner.readthedocs.org).
--- a/testing/web-platform/tests/docs/test-format-guidelines.md
+++ b/testing/web-platform/tests/docs/test-format-guidelines.md
@@ -106,17 +106,17 @@ Tests must be HTML, XHTML or SVG files.
 
 Note: For CSS tests, the test source will be parsed and
 re-serialized. This re-serialization will cause minor changes to the
 test file, notably: attribute values will always be quoted, whitespace
 between attributes will be collapsed to a single space, duplicate
 attributes will be removed, optional closing tags will be inserted,
 and invalid markup will be normalized.  If these changes should make
 the test inoperable, for example if the test is testing markup error
-recovery, add the [flag][requirement-flags] 'asis' to prevent
+recovery, add the [flag][requirement-flags] `asis` to prevent
 re-serialization. This flag will also prevent format conversions so it
 may be necessary to provide alternate versions of the test in other
 formats (XHTML, HTML, etc.)
 
 ## Character Encoding
 
 Except when specifically testing encoding, tests must be encoded in
 UTF-8, marked through the use of e.g. `<meta charset=utf-8>`, or in
@@ -257,17 +257,17 @@ is replaced with the second HTTP port.
 The request URL itself can be used as part of the substitution using
 the `location` dictionary, which has entries matching the
 `window.location` API. For example
 
 {% raw %}
     {{location[host]}}
 {% endraw %}
 
-is replaced by hostname:port for the current request.
+is replaced by `hostname:port` for the current request.
 
 ### Tests Requiring Special Headers
 
 For tests requiring that a certain HTTP header is set to some static
 value, a file with the same path as the test file except for an an
 additional `.headers` suffix may be created. For example for
 `/example/test.html`, the headers file would be
 `/example/test.html.headers`. This file consists of lines of the form
--- a/testing/web-platform/tests/docs/test-style-guidelines.md
+++ b/testing/web-platform/tests/docs/test-style-guidelines.md
@@ -191,40 +191,40 @@ pixels off some red is uncovered or othe
 
 [Text-only Example][red-text]
 
 _View the pages' source to see the usage of the color
 red to denote failure._
 
 #### Overlapped text
 
-Tests of the 'line-height', 'font-size' and similar properties can
+Tests of the `line-height`, `font-size` and similar properties can
 sometimes be devised in such a way that a failure will result in the
 text overlapping.
 
 #### The word "FAIL"
 
 Some properties lend themselves well to this kind of test, for
-example 'quotes' and 'content'. The idea is that if the word "FAIL"
+example `quotes` and `content`. The idea is that if the word "FAIL"
 appears anywhere, something must have gone wrong.
 
 [Example][fail-example]
 
 _View the page's source to see the usage of the word FAIL._
 
 ### Special Fonts
 
 #### Ahem
 Todd Fahrner has developed a font called [Ahem][ahem-readme], which
 consists of some very well defined glyphs of precise sizes and
 shapes. This font is especially useful for testing font and text
 properties. Without this font it would be very hard to use the
 overlapping technique with text.
 
-The font's em-square is exactly square. It's ascent and descent is
+The font's em-square is exactly square. Its ascent and descent is
 exactly the size of the em square. This means that the font's extent
 is exactly the same as its line-height, meaning that it can be
 exactly aligned with padding, borders, margins, and so forth.
 
 The font's alphabetic baseline is 0.2em above its bottom, and 0.8em
 below its top.
 
 The font has four glyphs:
@@ -258,34 +258,34 @@ E.g. Good:
 
 ``` css
 {font: 100px/1 Ahem;}
 {font: 1.25em/1 Ahem;} /* with computed 1.25em font-size being 20px
 */
 ```
 
 __If the test uses the Ahem font, make sure the line-height on block
-elements is specified; avoid 'line-height: normal'__. Also, for
+elements is specified; avoid `line-height: normal`__. Also, for
 absolute reliability, the difference between computed line-height
-and computed font-size should be dividable by 2.
+and computed font-size should be divisible by 2.
 
 E.g. Bad:
 
 ``` css
 {font: 1.25em Ahem;} /* computed line-height value is 'normal' */
 {font: 20px Ahem;} /* computed line-height value is 'normal' */
 {font-size: 25px; line-height: 50px;} /* the difference between
-computed line-height and computed font-size is not dividable by 2. */
+computed line-height and computed font-size is not divisible by 2. */
 ```
 
 E.g. Good:
 
 ``` css
 {font-size: 25px; line-height: 51px;} /* the difference between
-computed line-height and computed font-size is dividable by 2. */
+computed line-height and computed font-size is divisible by 2. */
 ```
 
 [Example test using Ahem][ahem-example]
 
 _View the page's source to see how the Ahem font is used._
 
 
 ##### Installing Ahem
@@ -342,21 +342,19 @@ methodical approach. For example, testin
 work for each property taking lengths is relatively easy, and can be
 done methodically simply by creating a test for each property/unit
 combination.
 
 In practice, the important thing to decide is when to be methodical
 and when to simply test, in an ad hoc fashion, a cross section of
 the possibilities.
 
-This example is a methodical test of the :not() pseudo-class with
-each attribute selector in turn, first for long values and then for
-short values:
-
-http://www.hixie.ch/tests/adhoc/css/selectors/not/010.xml
+This is an [example][methodical-test] of a methodical test of the
+`:not()` pseudo-class with each attribute selector in turn, first
+for long values and then for short values.
 
 ### Overlapping
 
 This technique should not be cast aside as a curiosity -- it is in
 fact one of the most useful techniques for testing CSS, especially
 for areas like positioning and the table model.
 
 The basic idea is that a red box is first placed using one set of
@@ -394,17 +392,17 @@ a problem.
 This is an [example][long-test] of a test that is too long.
 
 ### The counterintuitive "this should be red" test
 
 As mentioned many times in this document, red indicates a bug, so
 nothing should ever be red in a test.
 
 There is one important exception to this rule... the test for the
-'red' value for the color properties!
+`red` value for the color properties!
 
 ### Unobvious tests
 
 A test that has half a sentence of normal text with the second half
 bold if the test has passed is not very obvious, even if the
 sentence in question explains what should happen.
 
 There are various ways to avoid this kind of test, but no general
@@ -431,8 +429,9 @@ The last [subtest on this page][unobviou
 [red-visual]: http://test.csswg.org/source/css21/positioning/absolute-replaced-height-018.xht
 [red-text]: http://test.csswg.org/source/css21/syntax/comments-003.xht
 [fail-example]: http://test.csswg.org/source/css21/positioning/abspos-overflow-005.xht
 [ahem-example]: http://test.csswg.org/source/css21/positioning/absolute-non-replaced-width-001.xht
 [ahem-readme]: http://www.w3.org/Style/CSS/Test/Fonts/Ahem/README
 [download-ahem]: http://www.w3.org/Style/CSS/Test/Fonts/Ahem/AHEM____.TTF
 [long-test]: http://www.hixie.ch/tests/evil/mixed/lineheight3.html
 [unobvious-test]: http://www.w3.org/Style/CSS/Test/CSS1/current/sec525.htm
+[methodical-test]: http://www.hixie.ch/tests/adhoc/css/selectors/not/010.xml
--- a/testing/web-platform/tests/dom/nodes/ChildNode-after.html
+++ b/testing/web-platform/tests/dom/nodes/ChildNode-after.html
@@ -101,17 +101,17 @@ function test_after(child, nodeName, inn
         var parent = document.createElement('div');
         var x = document.createElement('x');
         var y = document.createElement('y');
         parent.appendChild(child);
         parent.appendChild(x);
         parent.appendChild(document.createTextNode('1'));
         parent.appendChild(y);
         child.after(x, '2');
-        var expected = innerHTML + '<x></x>12<y></y>';
+        var expected = innerHTML + '<x></x>21<y></y>';
         assert_equals(parent.innerHTML, expected);
     }, nodeName + '.after() with one sibling of child and text as arguments.');
 
     test(function() {
         var x = document.createElement('x');
         var y = document.createElement('y');
         x.after(y);
         assert_equals(x.nextSibling, null);
rename from testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled.html
rename to testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-001.html
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-fieldset-element/disabled-002.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+  <title>File input descendants of disabled fieldsets</title>
+  <link rel="author" title="Chris Rebert" href="http://chrisrebert.com" />
+  <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-fieldset-disabled" />
+  <script src="/resources/testharness.js"></script>
+  <script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+  <div id="log"></div>
+  <form>
+    <fieldset id="fs" disabled="disabled">
+      <input id="myfile" type="file" />
+    </fieldset>
+  </form>
+  <script>
+    test(function () {
+      assert_true(document.getElementById('fs').disabled, "disabled fieldset should be disabled");
+      assert_false(document.getElementById('myfile').willValidate, "form control descendant of disabled fieldset that is not also a descendant of a legend should be disabled");
+    }, "A file input without a disabled attribute that is a descendant of a disabled fieldset should be disabled (modulo legend-related complications that don't apply here)");
+  </script>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/forms/the-legend-element/legend-form.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTMLLegendElement Test: form</title>
+<link rel="author" title="Intel" href="http://www.intel.com/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div id="log"></div>
+
+<div style="display:none">
+  <form id="testform">
+    <legend id="testlegend">radio</legend>
+  </form>
+</div>
+
+<script>
+
+test(function () {
+  var legendEle = document.getElementById("testlegend");
+  assert_equals(legendEle.form, null);
+}, "Check if legend.form return null when legend has no fieldset element as its parent");
+
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Allowed content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of allowed content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: same-host-wss
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: allowed">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "same-host-wss",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "allowed"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Allowed content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of allowed content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: same-host-wss
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: allowed">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "same-host-wss",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "allowed"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/http-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/meta-csp/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Allowed content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of allowed content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/">
+    <meta name="assert" content="opt_in_method: meta-csp
+                                 origin: same-host-wss
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: allowed">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "meta-csp",
+          "origin": "same-host-wss",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "allowed"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/keep-scheme-redirect/websocket-allowed.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Allowed content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of allowed content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: same-host-wss
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: allowed">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "same-host-wss",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "allowed"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/allowed/no-opt-in/same-host-wss/websocket-request/top-level/no-redirect/websocket-allowed.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Allowed content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of allowed content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: same-host-wss
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: allowed">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "same-host-wss",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "allowed"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: swap-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "swap-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: http-csp
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: swap-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "http-csp",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "swap-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/http-csp/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html.headers
@@ -0,0 +1,1 @@
+Content-Security-Policy: block-all-mixed-content
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: meta-csp
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "meta-csp",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/meta-csp/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: meta-csp
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "meta-csp",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/cross-origin-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: cross-origin-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: swap-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "cross-origin-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "swap-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/keep-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: keep-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "keep-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/no-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: no-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "no-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/mixed-content/blockable/no-opt-in/same-host-ws/websocket-request/top-level/swap-scheme-redirect/ws-downgrade-blocks.https.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! Generated by mixed-content/generic/tools/generate.py using mixed-content/generic/template/test.release.html.template. -->
+<html>
+  <head>
+    <title>Mixed-Content: Blockable content</title>
+    <meta charset='utf-8'>
+    <meta name="description" content="Test behavior of blockable content.">
+    <link rel="author" title="Kristijan Burnik" href="burnik@chromium.org">
+    <link rel="help" href="http://www.w3.org/TR/mixed-content/#category-blockable">
+    <meta name="assert" content="opt_in_method: no-opt-in
+                                 origin: same-host-ws
+                                 source_scheme: https
+                                 context_nesting: top-level
+                                 redirection: swap-scheme-redirect
+                                 subresource: websocket-request
+                                 expectation: blocked">
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/mixed-content/generic/common.js"></script>
+    <script src="/mixed-content/generic/mixed-content-test-case.js?pipe=sub"></script>
+  </head>
+  <body>
+    <script>
+      MixedContentTestCase(
+        {
+          "opt_in_method": "no-opt-in",
+          "origin": "same-host-ws",
+          "source_scheme": "https",
+          "context_nesting": "top-level",
+          "redirection": "swap-scheme-redirect",
+          "subresource": "websocket-request",
+          "expectation": "blocked"
+        },
+        document.querySelector("meta[name=assert]").content,
+        new SanityChecker()
+      ).start();
+      </script>
+    <div id="log"></div>
+  </body>
+</html>
--- a/testing/web-platform/tests/mixed-content/generic/common.js
+++ b/testing/web-platform/tests/mixed-content/generic/common.js
@@ -349,13 +349,38 @@ function requestViaPicture(url) {
  *     url, and appends it to {@code document.body}.
  * @param {string} url The data URL.
  * @return {Promise} The promise for success/error events.
  */
 function requestViaObject(url) {
   return createRequestViaElement("object", {"data": url}, document.body);
 }
 
+/**
+ * Creates a new WebSocket pointing to {@code url} and sends a message string
+ * "echo". The {@code message} and {@code error} events are triggering the
+ * returned promise resolve/reject events.
+ * @param {string} url The URL for WebSocket to connect to.
+ * @return {Promise} The promise for success/error events.
+ */
+function requestViaWebSocket(url) {
+  return new Promise(function(resolve, reject) {
+    var websocket = new WebSocket(url);
+
+    websocket.addEventListener("message", function(e) {
+      resolve(JSON.parse(e.data));
+    });
+
+    websocket.addEventListener("open", function(e) {
+      websocket.send("echo");
+    });
+
+    websocket.addEventListener("error", function(e) {
+      reject(e)
+    });
+  });
+}
+
 // SanityChecker does nothing in release mode. See sanity-checker.js for debug
 // mode.
 function SanityChecker() {}
 SanityChecker.prototype.checkScenario = function() {};
 SanityChecker.prototype.setFailTimeout = function(test, timeout) {};
--- a/testing/web-platform/tests/mixed-content/generic/expect.py
+++ b/testing/web-platform/tests/mixed-content/generic/expect.py
@@ -53,24 +53,25 @@ def main(request, response):
     if "action" in request.GET:
         action = request.GET["action"]
 
         if "content_type" in request.GET:
             content_type = request.GET["content_type"]
 
         key = request.GET["key"]
         stash = request.server.stash
+        path = request.GET.get("path", request.url.split('?'))[0]
 
         if action == "put":
             value = request.GET["value"]
-            stash.take(key=key)
-            stash.put(key=key, value=value)
+            stash.take(key=key, path=path)
+            stash.put(key=key, value=value, path=path)
             response_data = json.dumps({"status": "success", "result": key})
         elif action == "purge":
-            value = stash.take(key=key)
+            value = stash.take(key=key, path=path)
             if content_type == "image/png":
                 response_data = open(os.path.join(request.doc_root,
                                                   "images",
                                                   "smiley.png")).read()
             elif content_type == "audio/mpeg":
                 response_data = open(os.path.join(request.doc_root,
                                                   "media",
                                                   "sound_5.oga")).read()
@@ -81,17 +82,17 @@ def main(request, response):
             elif content_type == "application/javascript":
                 response_data = open(os.path.join(request.doc_root,
                                                   "mixed-content",
                                                   "generic",
                                                   "worker.js")).read()
             else:
                 response_data = "/* purged */"
         elif action == "take":
-            value = stash.take(key=key)
+            value = stash.take(key=key, path=path)
             if value is None:
                 status = "allowed"
             else:
                 status = "blocked"
             response_data = json.dumps({"status": status, "result": value})
 
     response.add_required_headers = False
     response.writer.write_status(200)
--- a/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js
+++ b/testing/web-platform/tests/mixed-content/generic/mixed-content-test-case.js
@@ -11,40 +11,53 @@
  *     expectation(s). Refer to /mixed-content/spec.src.json for details.
  * @param {string} description The test scenario verbose description.
  * @param {SanityChecker} sanityChecker Instance of an object used to check the
  *     running scenario. Useful in debug mode. See ./sanity-checker.js.
  *     Run {@code ./tools/generate.py -h} for info on test generating modes.
  * @return {object} Object wrapping the start method used to run the test.
  */
 function MixedContentTestCase(scenario, description, sanityChecker) {
-  var insecureProtocol = "http";
-  var secureProtocol = "https";
+  var httpProtocol = "http";
+  var httpsProtocol = "https";
+  var wsProtocol = "ws";
+  var wssProtocol = "wss";
 
   var sameOriginHost = location.hostname;
   var crossOriginHost = "{{domains[www1]}}";
 
   // These values can evaluate to either empty strings or a ":port" string.
-  var insecurePort = getNormalizedPort(parseInt("{{ports[http][0]}}", 10));
-  var securePort = getNormalizedPort(parseInt("{{ports[https][0]}}", 10));
+  var httpPort = getNormalizedPort(parseInt("{{ports[http][0]}}", 10));
+  var httpsPort = getNormalizedPort(parseInt("{{ports[https][0]}}", 10));
+  var wsPort = getNormalizedPort(parseInt("{{ports[ws][0]}}", 10));
+  var wssPort = getNormalizedPort(parseInt("{{ports[wss][0]}}", 10));
 
   var resourcePath = "/mixed-content/generic/expect.py";
+  var wsResourcePath = "/stash_responder";
 
   // Map all endpoints to scenario for use in the test.
   var endpoint = {
     "same-origin":
       location.origin + resourcePath,
     "same-host-https":
-      secureProtocol + "://" + sameOriginHost + securePort + resourcePath,
+      httpsProtocol + "://" + sameOriginHost + httpsPort + resourcePath,
     "same-host-http":
-      insecureProtocol + "://" + sameOriginHost + insecurePort + resourcePath,
+      httpProtocol + "://" + sameOriginHost + httpPort + resourcePath,
     "cross-origin-https":
-      secureProtocol + "://" + crossOriginHost + securePort + resourcePath,
+      httpsProtocol + "://" + crossOriginHost + httpsPort + resourcePath,
     "cross-origin-http":
-      insecureProtocol + "://" + crossOriginHost + insecurePort + resourcePath
+      httpProtocol + "://" + crossOriginHost + httpPort + resourcePath,
+    "same-host-wss":
+      wssProtocol + "://" + sameOriginHost + wssPort + wsResourcePath,
+    "same-host-ws":
+      wsProtocol + "://" + sameOriginHost + wsPort + wsResourcePath,
+    "cross-origin-wss":
+      wssProtocol + "://" + crossOriginHost + wssPort + wsResourcePath,
+    "cross-origin-ws":
+      wsProtocol + "://" + crossOriginHost + wsPort + wsResourcePath
   };
 
   // Mapping all the resource requesting methods to the scenario.
   var resourceMap = {
     "a-tag": requestViaAnchor,
     "area-tag": requestViaArea,
     "fetch-request": requestViaFetch,
     "form-tag": requestViaForm,
@@ -53,17 +66,18 @@ function MixedContentTestCase(scenario, 
     "script-tag": requestViaScript,
     "worker-request": requestViaWorker,
     "xhr-request": requestViaXhr,
     "audio-tag": requestViaAudio,
     "video-tag": requestViaVideo,
     "picture-tag": requestViaPicture,
     "object-tag": requestViaObject,
     "link-css-tag": requestViaLinkStylesheet,
-    "link-prefetch-tag": requestViaLinkPrefetch
+    "link-prefetch-tag": requestViaLinkPrefetch,
+    "websocket-request": requestViaWebSocket
   };
 
   sanityChecker.checkScenario(scenario, resourceMap);
 
   // Mapping all expected MIME types to the scenario.
   var contentType = {
     "a-tag": "text/html",
     "area-tag": "text/html",
@@ -74,34 +88,39 @@ function MixedContentTestCase(scenario, 
     "script-tag": "text/javascript",
     "worker-request": "application/javascript",
     "xhr-request": "application/json",
     "audio-tag": "audio/mpeg",
     "video-tag": "video/mp4",
     "picture-tag": "image/png",
     "object-tag": "text/html",
     "link-css-tag": "text/css",
-    "link-prefetch-tag": "text/html"
+    "link-prefetch-tag": "text/html",
+    "websocket-request": "application/json"
   };
 
   var mixed_content_test = async_test(description);
 
   function runTest() {
     sanityChecker.setFailTimeout(mixed_content_test);
 
     var key = guid();
     var value = guid();
+    // We use the same path for both HTTP/S and WS/S stash requests.
+    var stash_path = encodeURIComponent("/mixed-content");
     var announceResourceRequestUrl = endpoint['same-origin'] +
                                      "?action=put&key=" + key +
-                                     "&value=" + value;
+                                     "&value=" + value +
+                                     "&path=" + stash_path;
     var assertResourceRequestUrl = endpoint['same-origin'] +
-                                  "?action=take&key=" + key;
+                                  "?action=take&key=" + key +
+                                  "&path=" + stash_path;
     var resourceRequestUrl = endpoint[scenario.origin] + "?redirection=" +
-                             scenario.redirection + "&action=purge&key=" +
-                             key + "&content_type=" +
+                             scenario.redirection + "&action=purge&key=" + key +
+                             "&path=" + stash_path + "&content_type=" +
                              contentType[scenario.subresource];
 
     xhrRequest(announceResourceRequestUrl)
       .then(function(response) {
         // Send out the real resource request.
         // This should tear down the key if it's not blocked.
         return resourceMap[scenario.subresource](resourceRequestUrl);
       })
--- a/testing/web-platform/tests/mixed-content/spec.src.json
+++ b/testing/web-platform/tests/mixed-content/spec.src.json
@@ -64,16 +64,30 @@
           "context_nesting": "top-level",
           "redirection": "*",
           "subresource": {
             "blockable": "*",
             "optionally-blockable": []
           },
           "origin": ["cross-origin-http", "same-host-http"],
           "expectation": "blocked"
+        },
+        {
+          "name": "ws-downgrade-blocks",
+          "expansion": "default",
+          "source_scheme": "https",
+          "opt_in_method": ["no-opt-in", "http-csp", "meta-csp"],
+          "context_nesting": "top-level",
+          "redirection": "*",
+          "subresource": {
+            "blockable": "websocket-request",
+            "optionally-blockable": []
+          },
+          "origin": ["cross-origin-ws", "same-host-ws"],
+          "expectation": "blocked"
         }
       ]
     },
     {
       "name": "allowed",
       "title": "Allowed content",
       "description": "Test behavior of allowed content.",
       "specification_url": "http://www.w3.org/TR/mixed-content/",
@@ -86,37 +100,71 @@
           "context_nesting": "top-level",
           "redirection": ["no-redirect", "keep-scheme-redirect"],
           "subresource": {
             "blockable": "*",
             "optionally-blockable": "*"
           },
           "origin": ["same-host-https"],
           "expectation": "allowed"
+        },
+        {
+          "name": "websocket-allowed",
+          "expansion": "default",
+          "source_scheme": "https",
+          "opt_in_method": "*",
+          "context_nesting": "top-level",
+          "redirection": ["no-redirect", "keep-scheme-redirect"],
+          "subresource": {
+            "blockable": "websocket-request",
+            "optionally-blockable": []
+          },
+          "origin": ["same-host-wss"],
+          "expectation": "allowed"
         }
       ]
     }
   ],
 
   "excluded_tests": [
     {
-      "name": "TODO-subresources-not-supported",
+      "name": "Redundant-subresources",
       "expansion": "*",
       "source_scheme": "*",
       "opt_in_method": "*",
       "context_nesting": "*",
       "redirection": "*",
       "subresource": {
         "blockable": [
-          "a-tag",
+          "a-tag"
+        ],
+        "optionally-blockable": []
+      },
+      "origin": "*",
+      "expectation": "*"
+    },
+    {
+      "name": "Skip-origins-not-applicable-to-websockets",
+      "expansion": "*",
+      "source_scheme": "*",
+      "opt_in_method": "*",
+      "context_nesting": "*",
+      "redirection": "*",
+      "subresource": {
+        "blockable": [
           "websocket-request"
         ],
         "optionally-blockable": []
       },
-      "origin": "*",
+      "origin": [
+        "same-host-https",
+        "same-host-http",
+        "cross-origin-https",
+        "cross-origin-http"
+      ],
       "expectation": "*"
     },
     {
       "name": "TODO-opt-in-method-img-cross-origin",
       "expansion": "*",
       "source_scheme": "*",
       "opt_in_method": "img-crossorigin",
       "context_nesting": "*",
@@ -170,17 +218,21 @@
     "context_nesting": [
       "top-level",
       "sub-level"
     ],
     "origin": [
       "same-host-https",
       "same-host-http",
       "cross-origin-https",
-      "cross-origin-http"
+      "cross-origin-http",
+      "same-host-wss",
+      "same-host-ws",
+      "cross-origin-wss",
+      "cross-origin-ws"
     ],
     "subresource": {
       "blockable": [
         "iframe-tag",
         "script-tag",
         "link-css-tag",
         "form-tag",
         "xhr-request",
--- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
+++ b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/elements-001.html
@@ -19,31 +19,44 @@ policies and contribution forms [3].
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="../../../testcommon.js"></script>
 <link rel="stylesheet" href="/resources/testharness.css">
 </head>
 <body>
 <div id="log"></div>
 <script>
+// These elements does not support creating shadow root.
+// instead, NotSupportedError should be thrown.
+// http://w3c.github.io/webcomponents/spec/shadow/#widl-Element-createShadowRoot-ShadowRoot-ShadowRootInit-shadowRootInitDict
+var BLACK_LISTED_ELEMENTS = [
+    "button",
+    "details",
+    "input",
+    "marquee",
+    "meter",
+    "progress",
+    "select",
+    "textarea",
+    "keygen"
+];
+
 function testElement(elementName) {
     var doc = document.implementation.createHTMLDocument('Test');
     var element = doc.createElement(elementName);
     doc.body.appendChild(element);
 
-    var shadowRoot1 = element.createShadowRoot();
-    assert_equals(shadowRoot1.ownerDocument, doc);
-
-    var shadowRoot2 = element.createShadowRoot();
-    assert_equals(shadowRoot2.ownerDocument, doc);
+    var shadowRoot = element.createShadowRoot();
+    assert_equals(shadowRoot.ownerDocument, doc);
 }
 
-var testParameters = HTML5_ELEMENT_NAMES.map(function (name) {
+var testParameters = HTML5_ELEMENT_NAMES.filter(function(name) {
+    return BLACK_LISTED_ELEMENTS.indexOf(name) == -1;
+}).map(function (name) {
     return [
         'Checks whether an element "' + name + '" can create a shadow root.',
         name
     ];
 });
-
 generate_tests(testElement, testParameters);
 </script>
 </body>
 </html>
--- a/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
+++ b/testing/web-platform/tests/shadow-dom/elements-and-dom-objects/extensions-to-element-interface/methods/non-element-nodes-001.html
@@ -56,41 +56,33 @@ function createAttributeNode() {
 
 function createDocumentFragmentNode() {
     var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
     var node = doc.createDocumentFragment();
     doc.documentElement.appendChild(node);
     return node;
 }
 
-function createEntityReferenceNode() {
-    var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createEntityReference('entity-reference-node');
-    doc.documentElement.appendChild(node);
-    return node;
-}
-
 function createProcessingInstructionNode() {
     var doc = document.implementation.createDocument(XHTML_NAMESPACE, 'html');
-    var node = doc.createProcessingInstruction('processing-instruction-node');
+    var node = doc.createProcessingInstruction('processing-instruction-node', '');
     doc.documentElement.appendChild(node);
     return node;
 }
 
 function createDocumentNode() {
     return document.implementation.createDocument(XHTML_NAMESPACE, 'html');
 }
 
 var factories = [
     ['a text node', createTextNode],
     ['a comment node', createCommentNode],
     ['a CDATA section node', createCDATASectionNode],
     ['an attribute node', createAttributeNode],
     ['a document fragment node', createDocumentFragmentNode],
-    ['an entity reference node', createEntityReferenceNode],
     ['a processing instruction node', createProcessingInstructionNode],
     ['a document node', createDocumentNode]
 ];
 
 // Non-element nodes should not have createShadowRoot() method.
 var noCreateShadowRootTestParameters = factories.map(
     function (nameAndFactory) {
         var name = nameAndFactory[0];
@@ -103,34 +95,11 @@ var noCreateShadowRootTestParameters = f
     });
 
 function testNoCreateShadowRoot(factory) {
     var node = factory();
     assert_equals(node.createShadowRoot, undefined);
 }
 
 generate_tests(testNoCreateShadowRoot, noCreateShadowRootTestParameters);
-
-// When createShadowRoot() is called on non-element nodes, it should throw
-// InvalidNodeTypeError (step 1 of section 10.2.2).
-function testThrowInvalidNodeTypeError(factory) {
-    var node = factory();
-    node.createShadowRoot = Element.prototype.createShadowRoot;
-    assert_throws('InvalidNodeTypeError',
-                  function () { node.createShadowRoot(); });
-}
-
-var throwInvalidNodeTypeErrorTestParameters = factories.map(
-    function (nameAndFactory) {
-        var name = nameAndFactory[0];
-        var factory = nameAndFactory[1];
-        return [
-            'When createShadowRoot() is called on ' + name + ', ' +
-                'InvalidNodeTypeError should be thrown.',
-            factory
-        ];
-    });
-
-generate_tests(testThrowInvalidNodeTypeError,
-               throwInvalidNodeTypeErrorTestParameters);
 </script>
 </body>
 </html>
--- a/testing/web-platform/tests/tools/runner/index.html
+++ b/testing/web-platform/tests/tools/runner/index.html
@@ -41,16 +41,20 @@
             </label>
           </div>
         </div>
 
         <div class="form-group">
           <label for="path" class="col-sm-3 control-label">Run tests under path</label>
           <div class="col-sm-9">
             <input value="/" id='path' class='path form-control' disabled>
+            <label>
+              <input type=checkbox id='use_regex'>
+              Use regular expression
+            </label>
           </div>
         </div>
 
         <div class="form-group">
           <label for="timeout_multiplier" class="col-sm-3 control-label">Timeout multiplier</label>
           <div class="col-sm-9">
             <input type=number value="1" id='timeout_multiplier' class='timeout_multiplier form-control'>
           </div>
@@ -80,31 +84,45 @@
     </div>
   </div>
 
   <div class="instructions">
     <p>
       To run a set of
       <a href="https://github.com/w3c/web-platform-tests/blob/master/README.md">web-platform-tests</a>
       tests, specify a path value in the <b>Run tests under path</b> field above. Example paths:
+    </p>
     <ul>
       <li><code>/</code> - runs all of the tests from the root down</li>
       <li><code>/websockets</code> - runs all of the
           <a href="http://w3c-test.org/websockets/">websockets</a> tests</li>
       <li><code>/websockets/constructor</code> - runs all of the
           <a href="http://w3c-test.org/websockets/constructor/">websockets/constructor</a> tests</li>
       <li><code>/html/syntax/parsing</code> - runs all of the
           <a href="http://w3c-test.org/html/syntax/parsing/">html/syntax/parsing</a> tests</li>
     </ul>
     <p>
+      Multiple test paths can be specified by separating them with comma or whitespace. For example,
+      <code>/js, /html</code> will run the <a href="http://w3c-test.org/js/">js</a> <em>and</em> <a href="http://w3c-test.org/html/">html</a>
+      tests.
+    </p>
+    <p>
+      <a href="http://www.w3schools.com/jsref/jsref_obj_regexp.asp" target="_blank">Javascript regular expressions</a> are also supported for filtering. When the option is checked,
+      only a test path matching the regex pattern will run. For example, you can specify <code>^/js/|^/html/</code>
+      to run the <a href="http://w3c-test.org/js/">js</a> <em>and</em> <a href="http://w3c-test.org/html/">html</a>
+      tests.
+    </p>
+    <p>
       If the test runner is run online, the set of tests available to run can be found in the
       <a href="http://w3c-test.org/">w3c-test.org</a> test repository.
+    </p>
     <p>
       Tests will run in a new window. For reftests and manual tests it’s best
       to put that window side-by-side with this one.
+    </p>
   </div>
 
   <div id="output">
     <div class="summary clearfix">
       <h4>Progress
         <span id="manifest">updating and loading test manifest; this may take several minutes</span>
       </h4>
       <div class="progress">
@@ -112,30 +130,44 @@
              aria-valuenow="0" aria-valuemin="0" aria-valuemax="0" style="width: 0">
           0%
         </div>
       </div>
       <div id='test_url'></div>
       <table class='table'>
         <thead>
           <tr>
-            <th>Passed
-            <th>Failed
-            <th>Timeouts
-            <th>Errors
+            <th></th>
+            <th>Passed</th>
+            <th>Failed</th>
+            <th>Timeouts</th>
+            <th>Errors</th>
             <th>Not Run</th>
           </tr>
         </thead>
         <tbody>
           <tr>
-            <td class='PASS'>0
-            <td class='FAIL'>0
-            <td class='TIMEOUT'>0
-            <td class='ERROR'>0
-            <td class='NOTRUN'>0
+            <td></td>
+            <td class='PASS'>0</td>
+            <td class='FAIL'>0</td>
+            <td class='TIMEOUT'>0</td>
+            <td class='ERROR'>0</td>
+            <td class='NOTRUN'>0</td>
+          </tr>
+           <tr>
+            <td>
+              <label>
+                Display:
+              </label>
+              </td>
+            <td><input type=checkbox class="result-display-filter" value="PASS" checked></td>
+            <td><input type=checkbox class="result-display-filter" value="FAIL" checked></td>
+            <td><input type=checkbox class="result-display-filter" value="TIMEOUT" checked></td>
+            <td><input type=checkbox class="result-display-filter" value="ERROR" checked></td>
+            <td><input type=checkbox class="result-display-filter" value="NOTRUN" checked></td>
           </tr>
         </tbody>
       </table>
       <a class="jsonResults btn btn-primary pull-right">Download JSON results</a>
     </div>
 
     <div class="results">
       <div id="manualUI">
--- a/testing/web-platform/tests/tools/runner/runner.js
+++ b/testing/web-platform/tests/tools/runner/runner.js
@@ -51,23 +51,31 @@ Manifest.prototype = {
         if (this.data.items.hasOwnProperty(type)) {
             return this.data.items[type];
         } else {
             return [];
         }
     }
 };
 
-function ManifestIterator(manifest, path, test_types) {
+function ManifestIterator(manifest, path, test_types, use_regex) {
     this.manifest = manifest;
-    this.path = path;
+    this.paths = null;
+    this.regex_pattern = null;
     this.test_types = test_types;
     this.test_types_index = -1;
     this.test_list = null;
     this.test_index = null;
+
+    if (use_regex) {
+        this.regex_pattern = path;
+    } else {
+        // Split paths by either a comma or whitespace, and ignore empty sub-strings.
+        this.paths = path.split(/[,\s]+/).filter(function(s) { return s.length > 0 });
+    }
 }
 
 ManifestIterator.prototype = {
     next: function() {
         var manifest_item = null;
 
         if (this.test_types.length === 0) {
             return null;
@@ -89,17 +97,23 @@ ManifestIterator.prototype = {
             }
             if (manifest_item) {
                 return this.to_test(manifest_item);
             }
         }
     },
 
     matches: function(manifest_item) {
-        return manifest_item.url.indexOf(this.path) === 0;
+        if (this.regex_pattern !== null) {
+            return manifest_item.url.match(this.regex_pattern);
+        } else {
+            return this.paths.some(function(p) {
+                return manifest_item.url.indexOf(p) === 0;
+            });
+        }
     },
 
     to_test: function(manifest_item) {
         var test = {
             type: this.test_types[this.test_types_index],
             url: manifest_item.url
         };
         if (manifest_item.hasOwnProperty("ref_url")) {
@@ -133,16 +147,28 @@ function VisualOutput(elem, runner) {
     this.json_results_area = this.elem.querySelector("textarea");
     this.instructions = document.querySelector(".instructions");
 
     this.elem.style.display = "none";
     this.runner.manifest_wait_callbacks.push(this.on_manifest_wait.bind(this));
     this.runner.start_callbacks.push(this.on_start.bind(this));
     this.runner.result_callbacks.push(this.on_result.bind(this));
     this.runner.done_callbacks.push(this.on_done.bind(this));
+
+    this.display_filter_state = {};
+
+    var visual_output = this;
+    var display_filter_inputs = this.elem.querySelectorAll(".result-display-filter");
+    for (var i = 0; i < display_filter_inputs.length; ++i) {
+        var display_filter_input = display_filter_inputs[i];
+        this.display_filter_state[display_filter_input.value] = display_filter_input.checked;
+        display_filter_input.addEventListener("change", function(e) {
+            visual_output.apply_display_filter(e.target.value, e.target.checked);
+        })
+    }
 }
 
 VisualOutput.prototype = {
     clear: function() {
         this.result_count = {"PASS":0,
                              "FAIL":0,
                              "ERROR":0,
                              "TIMEOUT":0,
@@ -233,16 +259,17 @@ VisualOutput.prototype = {
             }
         }
 
         var status_arr = ["PASS", "FAIL", "ERROR", "TIMEOUT", "NOTRUN"];
         for (var i = 0; i < status_arr.length; i++) {
             this.elem.querySelector("td." + status_arr[i]).textContent = this.result_count[status_arr[i]];
         }
 
+        this.apply_display_filter_to_result_row(row, this.display_filter_state[test_status]);
         this.results_table.tBodies[0].appendChild(row);
         this.update_meter(this.runner.progress(), this.runner.results.count(), this.runner.test_count());
     },
 
     on_done: function() {
         this.meter.setAttribute("aria-valuenow", this.meter.getAttribute("aria-valuemax"));
         this.meter.style.width = "100%";
         if (this.runner.stop_flag) {
@@ -290,18 +317,29 @@ VisualOutput.prototype = {
         link.textContent = href;
         return link;
     },
 
     update_meter: function(progress, count, total) {
         this.meter.setAttribute("aria-valuenow", count);
         this.meter.setAttribute("aria-valuemax", total);
         this.meter.textContent = this.meter.style.width = (progress * 100).toFixed(1) + "%";
+    },
+
+    apply_display_filter: function(test_status, display_state) {
+        this.display_filter_state[test_status] = display_state;
+        var result_cells = this.elem.querySelectorAll(".results > table tr td." + test_status);
+        for (var i = 0; i < result_cells.length; ++i) {
+            this.apply_display_filter_to_result_row(result_cells[i].parentNode, display_state)
+        }
+    },
+
+    apply_display_filter_to_result_row: function(result_row, display_state) {
+        result_row.style.display = display_state ? "" : "none";
     }
-
 };
 
 function ManualUI(elem, runner) {
     this.elem = elem;
     this.runner = runner;
     this.pass_button = this.elem.querySelector("button.pass");
     this.fail_button = this.elem.querySelector("button.fail");
     this.ref_buttons = this.elem.querySelector(".reftestUI");
@@ -377,16 +415,17 @@ ManualUI.prototype = {
     on_done: function() {
         this.hide();
     }
 };
 
 function TestControl(elem, runner) {
     this.elem = elem;
     this.path_input = this.elem.querySelector(".path");
+    this.use_regex_input = this.elem.querySelector("#use_regex");
     this.pause_button = this.elem.querySelector("button.togglePause");
     this.start_button = this.elem.querySelector("button.toggleStart");
     this.type_checkboxes = Array.prototype.slice.call(
         this.elem.querySelectorAll("input[type=checkbox].test-type"));
     this.type_checkboxes.forEach(function(elem) {
         elem.addEventListener("click", function() {
             this.start_button.disabled = this.get_test_types().length < 1;
         }.bind(this),
@@ -407,17 +446,18 @@ TestControl.prototype = {
         this.path_input.disabled = false;
         this.type_checkboxes.forEach(function(elem) {
             elem.disabled = false;
         });
         this.start_button.onclick = function() {
             var path = this.get_path();
             var test_types = this.get_test_types();
             var settings = this.get_testharness_settings();
-            this.runner.start(path, test_types, settings);
+            var use_regex = this.get_use_regex();
+            this.runner.start(path, test_types, settings, use_regex);
             this.set_stop();
             this.set_pause();
         }.bind(this);
     },
 
     set_stop: function() {
         clearTimeout(this.runner.timeout);
         this.pause_button.disabled = false;
@@ -461,16 +501,20 @@ TestControl.prototype = {
         });
     },
 
     get_testharness_settings: function() {
         return {timeout_multiplier: parseFloat(this.timeout_input.value),
                 output: this.render_checkbox.checked};
     },
 
+    get_use_regex: function() {
+        return this.use_regex_input.checked;
+    },
+
     on_done: function() {
         this.set_pause();
         this.set_start();
     }
 };
 
 function Results(runner) {
     this.test_results = null;
@@ -552,24 +596,25 @@ Runner.prototype = {
     },
 
     manifest_loaded: function() {
         if (this.start_after_manifest_load) {
             this.do_start();
         }
     },
 
-    start: function(path, test_types, testharness_settings) {
+    start: function(path, test_types, testharness_settings, use_regex) {
         this.pause_flag = false;
         this.stop_flag = false;
         this.done_flag = false;
         this.path = path;
+        this.use_regex = use_regex;
         this.test_types = test_types;
         window.testharness_properties = testharness_settings;
-        this.manifest_iterator = new ManifestIterator(this.manifest, this.path, this.test_types);
+        this.manifest_iterator = new ManifestIterator(this.manifest, this.path, this.test_types, this.use_regex);
         this.num_tests = null;
 
         if (this.manifest.data === null) {
             this.wait_for_manifest();
         } else {
             this.do_start();
         }
     },
@@ -704,17 +749,18 @@ function setup() {
     runner = new Runner("/MANIFEST.json", options);
     var test_control = new TestControl(document.getElementById("testControl"), runner);
     new ManualUI(document.getElementById("manualUI"), runner);
     new VisualOutput(document.getElementById("output"), runner);
 
     if (options.autorun === "1") {
         runner.start(test_control.get_path(),
                      test_control.get_test_types(),
-                     test_control.get_testharness_settings());
+                     test_control.get_testharness_settings(),
+                     test_control.get_use_regex());
         return;
     }
 }
 
 window.completion_callback = function(tests, status) {
     var harness_status_map = {0:"OK", 1:"ERROR", 2:"TIMEOUT", 3:"NOTRUN"};
     var subtest_status_map = {0:"PASS", 1:"FAIL", 2:"TIMEOUT", 3:"NOTRUN"};
 
--- a/testing/web-platform/tests/tools/serve/serve.py
+++ b/testing/web-platform/tests/tools/serve/serve.py
@@ -5,17 +5,17 @@ import os
 import signal
 import socket
 import sys
 import threading
 import time
 import traceback
 import urllib2
 import uuid
-from collections import defaultdict
+from collections import defaultdict, OrderedDict
 from multiprocessing import Process, Event
 
 from .. import localpaths
 
 import sslutils
 from wptserve import server as wptserve, handlers
 from wptserve import stash
 from wptserve.logger import set_logger
@@ -45,27 +45,65 @@ fetch_tests_from_worker(new Worker("%s")
 rewrites = [("GET", "/resources/WebIDLParser.js", "/resources/webidl2/lib/webidl2.js")]
 
 subdomains = [u"www",
               u"www1",
               u"www2",
               u"天気の良い日",
               u"élève"]
 
+class RoutesBuilder(object):
+    def __init__(self):
+        self.forbidden_override = [("GET", "/tools/runner/*", handlers.file_handler),
+                                   ("POST", "/tools/runner/update_manifest.py",
+                                    handlers.python_script_handler)]
+
+        self.forbidden = [("*", "/_certs/*", handlers.ErrorHandler(404)),
+                          ("*", "/tools/*", handlers.ErrorHandler(404)),
+                          ("*", "{spec}/tools/*", handlers.ErrorHandler(404)),
+                          ("*", "/serve.py", handlers.ErrorHandler(404))]
+
+        self.static = [("GET", "*.worker", WorkersHandler())]
+
+        self.mountpoint_routes = OrderedDict()
+
+        self.add_mount_point("/", None)
+
+    def get_routes(self):
+        routes = self.forbidden_override + self.forbidden + self.static
+        # Using reversed here means that mount points that are added later
+        # get higher priority. This makes sense since / is typically added
+        # first.
+        for item in reversed(self.mountpoint_routes.values()):
+            routes.extend(item)
+        return routes
+
+    def add_static(self, path, format_args, content_type, route):
+        handler = handlers.StaticHandler(path, format_args, content_type)
+        self.static.append((b"GET", str(route), handler))
+
+    def add_mount_point(self, url_base, path):
+        url_base = "/%s/" % url_base.strip("/") if url_base != "/" else "/"
+
+        self.mountpoint_routes[url_base] = []
+
+        routes = [("GET", "*.asis", handlers.AsIsHandler),
+                  ("*", "*.py", handlers.PythonScriptHandler),
+                  ("GET", "*", handlers.FileHandler)]
+
+        for (method, suffix, handler_cls) in routes:
+            self.mountpoint_routes[url_base].append(
+                (method,
+                 b"%s%s" % (str(url_base) if url_base != "/" else "", str(suffix)),
+                 handler_cls(base_path=path, url_base=url_base)))
+
+
 def default_routes():
-    return [("GET", "/tools/runner/*", handlers.file_handler),
-            ("POST", "/tools/runner/update_manifest.py", handlers.python_script_handler),
-            ("*", "/_certs/*", handlers.ErrorHandler(404)),
-            ("*", "/tools/*", handlers.ErrorHandler(404)),
-            ("*", "{spec}/tools/*", handlers.ErrorHandler(404)),
-            ("*", "/serve.py", handlers.ErrorHandler(404)),
-            ("*", "*.py", handlers.python_script_handler),
-            ("GET", "*.asis", handlers.as_is_handler),
-            ("GET", "*.worker", WorkersHandler()),
-            ("GET", "*", handlers.file_handler),]
+    return RoutesBuilder().get_routes()
+
 
 def setup_logger(level):
     import logging
     global logger
     logger = logging.getLogger("web-platform-tests")
     logging.basicConfig(level=getattr(logging, level.upper()))
     set_logger(logger)
 
--- a/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py
+++ b/testing/web-platform/tests/tools/wptserve/wptserve/handlers.py
@@ -46,23 +46,27 @@ def filesystem_path(base_path, request, 
 
     return new_path
 
 class DirectoryHandler(object):
     def __init__(self, base_path=None, url_base="/"):
         self.base_path = base_path
         self.url_base = url_base
 
+    def __repr__(self):
+        return "<%s base_path:%s url_base:%s>" % (self.__class__.__name__, self.base_path, self.url_base)
+
     def __call__(self, request, response):
         if not request.url_parts.path.endswith("/"):
             raise HTTPException(404)
 
         path = filesystem_path(self.base_path, request, self.url_base)
 
-        assert os.path.isdir(path)
+        if not os.path.isdir(path):
+            raise HTTPException(404, "%s is not a directory" % path)
 
         response.headers = [("Content-Type", "text/html")]
         response.content = """<!doctype html>
 <meta name="viewport" content="width=device-width">
 <title>Directory listing for %(path)s</title>
 <h1>Directory listing for %(path)s</h1>
 <ul>
 %(items)s
@@ -97,17 +101,20 @@ class DirectoryHandler(object):
 
 directory_handler = DirectoryHandler()
 
 
 class FileHandler(object):
     def __init__(self, base_path=None, url_base="/"):
         self.base_path = base_path
         self.url_base = url_base
-        self.directory_handler = DirectoryHandler(self.base_path)
+        self.directory_handler = DirectoryHandler(self.base_path, self.url_base)
+
+    def __repr__(self):
+        return "<%s base_path:%s url_base:%s>" % (self.__class__.__name__, self.base_path, self.url_base)
 
     def __call__(self, request, response):
         path = filesystem_path(self.base_path, request, self.url_base)
 
         if os.path.isdir(path):
             return self.directory_handler(request, response)
         try:
             #This is probably racy with some other process trying to change the file
@@ -204,16 +211,19 @@ class FileHandler(object):
 file_handler = FileHandler()
 
 
 class PythonScriptHandler(object):
     def __init__(self, base_path=None, url_base="/"):
         self.base_path = base_path
         self.url_base = url_base
 
+    def __repr__(self):
+        return "<%s base_path:%s url_base:%s>" % (self.__class__.__name__, self.base_path, self.url_base)
+
     def __call__(self, request, response):
         path = filesystem_path(self.base_path, request, self.url_base)
 
         try:
             environ = {"__file__": path}
             execfile(path, environ, environ)
             if "main" in environ:
                 handler = FunctionHandler(environ["main"])
@@ -325,8 +335,34 @@ class BasicAuthHandler(object):
 basic_auth_handler = BasicAuthHandler(file_handler, None, None)
 
 class ErrorHandler(object):
     def __init__(self, status):
         self.status = status
 
     def __call__(self, request, response):
         response.set_error(self.status)
+
+
+class StaticHandler(object):
+    def __init__(self, path, format_args, content_type, **headers):
+        """Hander that reads a file from a path and substitutes some fixed data
+
+        :param path: Path to the template file to use
+        :param format_args: Dictionary of values to substitute into the template file
+        :param content_type: Content type header to server the response with
+        :param headers: List of headers to send with responses"""
+
+        with open(path) as f:
+            self.data = f.read() % format_args
+
+        self.resp_headers = [("Content-Type", content_type)]
+        for k, v in headers.iteritems():
+            resp_headers.append((k.replace("_", "-"), v))
+
+        self.handler = handler(self.handle_request)
+
+    def handle_request(self, request, response):
+        return self.resp_headers, self.data
+
+    def __call__(self, request, response):
+        rv = self.handler(request, response)
+        return rv
--- a/testing/web-platform/tests/tools/wptserve/wptserve/stash.py
+++ b/testing/web-platform/tests/tools/wptserve/wptserve/stash.py
@@ -52,28 +52,29 @@ def start_server(address=None, authkey=N
     manager.start()
 
     return (manager, manager._address, manager._authkey)
 
 
 #TODO: Consider expiring values after some fixed time for long-running
 #servers
 
-# TODO(kristijanburnik): Provide shared Stash support for WebSockets.
+class Stash(object):
+    """Key-value store for persisting data across HTTP/S and WS/S requests.
 
-class Stash(object):
-    """Key-value store for persisting data across HTTP/S requests.
+    This data store is specifically designed for persisting data across server
+    requests. The synchronization is achieved by using the BaseManager from
+    the multiprocessing module so different processes can acccess the same data.
 
-    This data store is specifically designed for persisting data across
-    HTTP and HTTPS requests. The synchronization model is usually done by using
-    the SyncManager from the multiprocessing module.
-
-    Stash can be used interchangeably between HTTP and HTTPS requests as both
-    processes are accessing the same resource (e.g. a Manager.dict).
-    The WS and WSS servers are currently not supported.
+    Stash can be used interchangeably between HTTP, HTTPS, WS and WSS servers.
+    A thing to note about WS/S servers is that they require additional steps in
+    the handlers for accessing the same underlying shared data in the Stash.
+    This can usually be achieved by using load_env_config(). When using Stash
+    interchangeably between HTTP/S and WS/S request, the path part of the key
+    should be expliclitly specified if accessing the same key/value subset.
 
     The store has several unusual properties. Keys are of the form (path,
     uuid), where path is, by default, the path in the HTTP request and
     uuid is a unique id. In addition, the store is write-once, read-once,
     i.e. the value associated with a particular key cannot be changed once
     written and the read operation (called "take") is destructive. Taken together,
     these properties make it difficult for data to accidentally leak
     between different resources or different requests for the same
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/websockets/Close-clamp.htm
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<title>WebSocket#close(2**16+1000)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="websocket.js?pipe=sub"></script>
+<div id="log"></div>
+<script>
+test(function() {
+    var ws = CreateWebSocket(false, false, false);
+    assert_throws("InvalidAccessError", function () {
+        ws.close(0x10000 + 1000);
+    });
+});
+</script>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/websockets/handlers/stash_responder_wsh.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+import urlparse, json
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+from wptserve import stash
+
+address, authkey = stash.load_env_config()
+stash = stash.Stash("/stash_responder", address=address, authkey=authkey)
+
+def web_socket_do_extra_handshake(request):
+    return
+
+def web_socket_transfer_data(request):
+    while True:
+        line = request.ws_stream.receive_message()
+        if line == "echo":
+            query = request.unparsed_uri.split('?')[1]
+            GET = dict(urlparse.parse_qsl(query))
+
+            # TODO(kristijanburnik): This code should be reused from
+            # /mixed-content/generic/expect.py or implemented more generally
+            # for other tests.
+            path = GET.get("path", request.unparsed_uri.split('?')[0])
+            key = GET["key"]
+            action = GET["action"]
+
+            if action == "put":
+              value = GET["value"]
+              stash.take(key=key, path=path)
+              stash.put(key=key, value=value, path=path)
+              response_data = json.dumps({"status": "success", "result": key})
+            elif action == "purge":
+             value = stash.take(key=key, path=path)
+             response_data = json.dumps({"status": "success", "result": value})
+            elif action == "take":
+              value = stash.take(key=key, path=path)
+              if value is None:
+                  status = "allowed"
+              else:
+                  status = "blocked"
+              response_data = json.dumps({"status": status, "result": value})
+
+            msgutil.send_message(request, response_data)
+
+            return