Bug 1529459 [wpt PR 15179] - Add tentative WPT to verify download in sandbox, a=testonly
authorYao Xiao <yaoxia@chromium.org>
Wed, 06 Mar 2019 12:34:11 +0000
changeset 522545 496fc0a8cd1d53d2066ecf4ccadf557261dc935b
parent 522544 cd9ac71c85c6abbea6f856c576a3c261c34e6fba
child 522546 c2de5b0649719b063e0c85d084c37b99db7cc11b
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);
+}