Bug 1529459 [wpt PR 15179] - Add tentative WPT to verify download in sandbox, a=testonly
☠☠ backed out by 66b1aba3fb43 ☠ ☠
authorYao Xiao <yaoxia@chromium.org>
Wed, 06 Mar 2019 12:34:11 +0000
changeset 522266 6caf4fe5691dab0ede6322408e1c878493626088
parent 522265 ee028b57d61360d222f87731cd8e66733b2dcf5d
child 522267 c6ad6c137153b4991c9aaf643513aa9a9b23dd2e
push id10871
push usercbrindusan@mozilla.com
push dateMon, 18 Mar 2019 15:49:32 +0000
treeherdermozilla-beta@018abdd16060 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstestonly
bugs1529459, 15179, 539938, 927183, 1446395, 634249
milestone67.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 1529459 [wpt PR 15179] - Add tentative WPT to verify download in sandbox, a=testonly Automatic update from web-platform-tests Add tentative WPT to verify download in sandbox General testing idea: For a network request, the server stores a token in stash. And after a fixed period of time, we validate the token in the stash to verify a download has happened. Also assert that no additional navigation should happen. In the case of <a download> where the decision of download can be made before resource fetching, the server sets the token immediately. In the case of navigation to a download, the server will stream a response over 1 seconds and set the token at the end only when the socket has been connected. So it is able to detect any download cancellation while fetching the resource. Bug: 539938, 927183 Change-Id: I7b90d46504603f60938a46acee9fbd7d1483988b Reviewed-on: https://chromium-review.googlesource.com/c/1446395 Reviewed-by: Mike West <mkwst@chromium.org> Commit-Queue: Yao Xiao <yaoxia@chromium.org> Cr-Commit-Position: refs/heads/master@{#634249} -- wpt-commits: 245334dcc1695c3dbc4e1fcdbe849224234093fc wpt-pr: 15179
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/support/iframe_sandbox_download_helper.js
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_allow_downloads_without_user_activation.sub.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>&lt;a download&gt; triggered download in sandbox is allowed by allow-downloads-without-user-activation.</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<script src="/resources/testharness.js"></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src="support/iframe_sandbox_download_helper.js"></script>
+<body>
+<script>
+"use strict";
+
+async_test(t => {
+    const token = "{{$id:uuid()}}";
+    var iframe = document.createElement("iframe");
+    iframe.srcdoc = "<a>Download</a>";
+    iframe.sandbox = "allow-same-origin allow-downloads-without-user-activation";
+    iframe.onload = t.step_func(function () {
+        iframe.contentWindow.addEventListener(
+            "unload", t.unreached_func("Unexpected navigation."));
+        var anchor = iframe.contentDocument.getElementsByTagName('a')[0];
+        anchor.href = "support/download_stash.py?token=" + token;
+        anchor.download = null;
+        anchor.click();
+        AssertDownloadSuccess(t, token, DownloadVerifyDelay());
+    });
+
+    document.body.appendChild(iframe);
+}, "<a download> triggered download in sandbox is allowed by allow-downloads-without-user-activation.");
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_anchor_download_block_downloads_without_user_activation.sub.tentative.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>&lt;a download&gt; triggered download in sandbox is blocked.</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<script src="/resources/testharness.js"></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src="support/iframe_sandbox_download_helper.js"></script>
+<body>
+<script>
+"use strict";
+
+async_test(t => {
+    const token = "{{$id:uuid()}}";
+    var iframe = document.createElement("iframe");
+    iframe.srcdoc = "<a>Download</a>";
+    iframe.sandbox = "allow-same-origin";
+    iframe.onload = t.step_func(function () {
+        iframe.contentWindow.addEventListener(
+            "unload", t.unreached_func("Unexpected navigation."));
+        var anchor = iframe.contentDocument.getElementsByTagName('a')[0];
+        anchor.href = "support/download_stash.py?token=" + token;
+        anchor.download = null;
+        anchor.click();
+        AssertDownloadFailure(t, token, DownloadVerifyDelay());
+    });
+
+    document.body.appendChild(iframe);
+}, "<a download> triggered download in sandbox is blocked.");
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_allow_downloads_without_user_activation.sub.tentative.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Navigation resulted download in sandbox is allowed by allow-downloads-without-user-activation.</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<script src="/resources/testharness.js"></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src="support/iframe_sandbox_download_helper.js"></script>
+<body>
+<script>
+"use strict";
+
+async_test(t => {
+    const token = "{{$id:uuid()}}";
+    var iframe = document.createElement("iframe");
+    iframe.srcdoc = "<a>Download</a>";
+    iframe.sandbox = "allow-same-origin allow-downloads-without-user-activation";
+    iframe.onload = t.step_func(function () {
+        iframe.contentWindow.addEventListener(
+            "unload", t.unreached_func("Unexpected navigation."));
+        var anchor = iframe.contentDocument.getElementsByTagName('a')[0];
+        // Set |finish-delay| to let the server stream a response over a  period
+        // of time, so it's able to catch potential download cancellation by
+        // detecting a socket close.
+        anchor.href = "support/download_stash.py?token=" + token + "&finish-delay=" + StreamDownloadFinishDelay();
+        anchor.click();
+        AssertDownloadSuccess(t, token, StreamDownloadFinishDelay() + DownloadVerifyDelay());
+    });
+
+    document.body.appendChild(iframe);
+}, "Navigation resulted download in sandbox is allowed by allow-downloads-without-user-activation.");
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigation_download_block_downloads_without_user_activation.sub.tentative.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Navigation resulted download in sandbox is blocked.</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-iframe-sandbox">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-iframe-element">
+<script src="/resources/testharness.js"></script>
+<script src='/resources/testharnessreport.js'></script>
+<script src="support/iframe_sandbox_download_helper.js"></script>
+<body>
+<script>
+"use strict";
+
+async_test(t => {
+    const token = "{{$id:uuid()}}";
+    var iframe = document.createElement("iframe");
+    iframe.srcdoc = "<a>Download</a>";
+    iframe.sandbox = "allow-same-origin";
+    iframe.onload = t.step_func(function () {
+        iframe.contentWindow.addEventListener(
+            "unload", t.unreached_func("Unexpected navigation."));
+        var anchor = iframe.contentDocument.getElementsByTagName('a')[0];
+        // Set |finish-delay| to let the server stream a response over a  period
+        // of time, so it's able to catch potential download cancellation by
+        // detecting a socket close.
+        anchor.href = "support/download_stash.py?token=" + token + "&finish-delay=" + StreamDownloadFinishDelay();
+        anchor.click();
+        AssertDownloadFailure(t, token, StreamDownloadFinishDelay() + DownloadVerifyDelay());
+    });
+
+    document.body.appendChild(iframe);
+}, "Navigation resulted download in sandbox is blocked.");
+</script>
+</body>
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/support/download_stash.py
@@ -0,0 +1,28 @@
+import time
+
+def main(request, response):
+    token = request.GET["token"]
+    response.status = 200
+    response.headers.append("Content-Type", "text/html")
+    if "verify-token" in request.GET:
+      if request.server.stash.take(token):
+        return 'TOKEN_SET'
+      return 'TOKEN_NOT_SET'
+
+    if "finish-delay" not in request.GET:
+      # <a download>
+      request.server.stash.put(token, True)
+      return
+
+    # navigation to download
+    response.headers.append("Content-Disposition", "attachment")
+    response.write_status_headers()
+    finish_delay = float(request.GET["finish-delay"]) / 1E3
+    count = 10
+    single_delay = finish_delay / count
+    for i in range(count): # pylint: disable=unused-variable
+        time.sleep(single_delay)
+        response.writer.write_content("\n")
+        if not response.writer.flush():
+          return
+    request.server.stash.put(token, True)
new file mode 100644
--- /dev/null
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/support/iframe_sandbox_download_helper.js
@@ -0,0 +1,37 @@
+function StreamDownloadFinishDelay() {
+    return 1000;
+}
+
+function DownloadVerifyDelay() {
+    return 1000;
+}
+
+function VerifyDownload(test_obj, token, timeout, expect_download) {
+    var verify_token = test_obj.step_func(function () {
+        var xhr = new XMLHttpRequest();
+        xhr.open('GET', 'support/download_stash.py?verify-token&token=' + token);
+        xhr.onload = test_obj.step_func(function(e) {
+            if (expect_download) {
+              if (xhr.response != "TOKEN_SET") {
+                // Always retry, and rely on the test timeout to conclude that
+                // download didn't happen and to fail the test.
+                test_obj.step_timeout(verify_token, DownloadVerifyDelay());
+                return;
+              }
+            } else {
+              assert_equals(xhr.response, "TOKEN_NOT_SET", "Expect no download to happen, but got one.");
+            }
+            test_obj.done();
+        });
+        xhr.send();
+    });
+    test_obj.step_timeout(verify_token, timeout);
+}
+
+function AssertDownloadSuccess(test_obj, token, timeout) {
+    VerifyDownload(test_obj, token, timeout, true);
+}
+
+function AssertDownloadFailure(test_obj, token, timeout) {
+    VerifyDownload(test_obj, token, timeout, false);
+}