From 43a97878ce14b72f0981164f87f2e35e14151312 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 11:22:09 +0200 Subject: Adding upstream version 110.0.1. Signed-off-by: Daniel Baumann --- .../resource-timing/304-response-recorded.html | 53 +++ .../tests/resource-timing/CodingConventions.md | 77 +++ .../web-platform/tests/resource-timing/META.yml | 6 + .../SO-XO-SO-redirect-chain-tao.https.html | 64 +++ .../tests/resource-timing/SyntheticResponse.py | 50 ++ .../tests/resource-timing/TAO-match.html | 82 ++++ .../TAO-port-mismatch-means-crossorigin.html | 46 ++ .../web-platform/tests/resource-timing/__init__.py | 0 .../buffer-full-add-after-full-event.html | 27 ++ ...full-add-entries-during-callback-that-drop.html | 29 ++ .../buffer-full-add-entries-during-callback.html | 28 ++ .../buffer-full-add-then-clear.html | 31 ++ ...uffer-full-decrease-buffer-during-callback.html | 26 ++ .../resource-timing/buffer-full-eventually.html | 31 ++ ...uffer-full-increase-buffer-during-callback.html | 26 ++ ...buffer-full-inspect-buffer-during-callback.html | 30 ++ .../buffer-full-set-to-current-buffer.html | 34 ++ ...uffer-full-store-and-clear-during-callback.html | 36 ++ .../buffer-full-then-decreased.html | 29 ++ .../buffer-full-then-increased.html | 28 ++ .../buffer-full-when-populate-entries.html | 30 ++ .../tests/resource-timing/buffered-flag.any.js | 18 + .../cached-image-gets-single-entry.html | 67 +++ .../resource-timing/clear-resource-timings.html | 22 + .../tests/resource-timing/connection-reuse.html | 56 +++ .../resource-timing/connection-reuse.https.html | 25 + .../resource-timing/content-type-parsing.html | 76 +++ .../tests/resource-timing/content-type.html | 117 +++++ .../tests/resource-timing/cors-preflight.any.js | 49 ++ .../tests/resource-timing/cross-origin-iframe.html | 33 ++ .../resource-timing/cross-origin-redirects.html | 102 ++++ ...cross-origin-start-end-time-with-redirects.html | 32 ++ .../resource-timing/cross-origin-status-codes.html | 70 +++ .../resource-timing/delivery-type.tentative.any.js | 90 ++++ .../document-domain-no-impact-opener.html | 16 + .../entries-for-network-errors.sub.https.html | 35 ++ .../tests/resource-timing/entry-attributes.html | 39 ++ .../tests/resource-timing/event-source-timing.html | 32 ++ .../fetch-cross-origin-redirect.https.html | 33 ++ .../tests/resource-timing/font-timestamps.html | 62 +++ .../tests/resource-timing/frameset-timing.html | 6 + .../tests/resource-timing/idlharness.any.js | 24 + .../resource-timing/iframe-failed-commit.html | 108 +++++ .../tests/resource-timing/iframe-non-html.html | 23 + .../iframe-redirect-without-location.html | 17 + .../resource-timing/iframe-sequence-of-events.html | 12 + .../resource-timing/iframe-with-download.html | 24 + .../resource-timing/image-sequence-of-events.html | 29 ++ .../resource-timing/initiator-type-for-script.html | 67 +++ .../resource-timing/initiator-type/audio.html | 34 ++ .../initiator-type/dynamic-insertion.html | 41 ++ .../resource-timing/initiator-type/embed.html | 20 + .../resource-timing/initiator-type/frameset.html | 22 + .../resource-timing/initiator-type/iframe.html | 19 + .../resource-timing/initiator-type/img-srcset.html | 21 + .../tests/resource-timing/initiator-type/img.html | 19 + .../resource-timing/initiator-type/input.html | 19 + .../tests/resource-timing/initiator-type/link.html | 35 ++ .../tests/resource-timing/initiator-type/misc.html | 31 ++ .../resource-timing/initiator-type/picture.html | 39 ++ .../resources/initiator-type-test.js | 15 + .../resource-timing/initiator-type/script.html | 26 ++ .../resource-timing/initiator-type/style.html | 45 ++ .../tests/resource-timing/initiator-type/svg.html | 23 + .../resource-timing/initiator-type/video.html | 32 ++ .../resource-timing/initiator-type/workers.html | 23 + .../resource-timing/input-sequence-of-events.html | 21 + .../resource-timing/link-sequence-of-events.html | 30 ++ .../load-from-mem-cache-transfer-size.html | 65 +++ .../nested-context-navigations-embed.html | 36 ++ .../nested-context-navigations-iframe.html | 32 ++ .../nested-context-navigations-object.html | 37 ++ .../nextHopProtocol-is-tao-protected.https.html | 49 ++ ...-cross-origin-css-fetched-memory-cache.sub.html | 38 ++ ...o-entries-for-cross-origin-css-fetched.sub.html | 39 ++ .../object-not-found-adds-entry.html | 37 ++ ...-not-found-after-TAO-cross-origin-redirect.html | 47 ++ ...ject-not-found-after-cross-origin-redirect.html | 36 ++ .../tests/resource-timing/opaque-origin.html | 46 ++ .../tests/resource-timing/ping-rt-entries.html | 29 ++ .../tests/resource-timing/redirects.html | 61 +++ .../render-blocking-status-link.html | 222 +++++++++ .../render-blocking-status-script.html | 196 ++++++++ .../resource-timing/resource-ignore-data-url.html | 39 ++ .../tests/resource-timing/resource-reload-TAO.html | 18 + .../resource-timing/resource-timing-level1.js | 517 +++++++++++++++++++++ .../resource-timing-level1.sub.html | 19 + .../resource_connection_reuse_mixed_content.html | 55 +++ ...ce_connection_reuse_mixed_content_redirect.html | 55 +++ .../resource-timing/resource_dedicated_worker.html | 28 ++ .../resource_nested_dedicated_worker.worker.js | 17 + .../resource-timing/resource_reparenting.html | 53 +++ .../resource_subframe_self_navigation.html | 53 +++ .../resource-timing/resource_timing.worker.js | 64 +++ .../resource_timing_content_length.html | 35 ++ .../tests/resource-timing/resources/200.https.asis | 5 + .../tests/resource-timing/resources/200_empty.asis | 3 + .../tests/resource-timing/resources/204_empty.asis | 3 + .../tests/resource-timing/resources/205_empty.asis | 3 + .../tests/resource-timing/resources/TAOResponse.py | 64 +++ .../resource-timing/resources/blank-with-tao.html | 10 + .../resources/blank-with-tao.html.headers | 1 + .../resource-timing/resources/blue-with-tao.png | Bin 0 -> 1010 bytes .../resources/blue-with-tao.png.headers | 1 + .../tests/resource-timing/resources/blue.png | Bin 0 -> 1010 bytes .../resources/buffer-full-utilities.js | 75 +++ .../resources/cacheable-and-validated.py | 30 ++ .../tests/resource-timing/resources/close.html | 1 + .../resources/connection-reuse-test.js | 63 +++ .../resource-timing/resources/content-type.py | 5 + .../tests/resource-timing/resources/cors-ahem.py | 19 + .../resources/csp-default-none.html | 3 + .../resources/csp-default-none.html.headers | 2 + .../tests/resource-timing/resources/delay-css.py | 6 + .../resources/document-domain-no-impact.html | 28 ++ .../resources/document-navigated.html | 12 + .../resources/document-refreshed.html | 12 + .../resources/document-that-navigates.html | 11 + .../resources/document-that-refreshes.html | 9 + .../tests/resource-timing/resources/download.asis | 6 + .../resources/embed-navigate-back.html | 18 + .../resource-timing/resources/embed-navigate.html | 18 + .../resource-timing/resources/embed-refresh.html | 18 + .../tests/resource-timing/resources/empty.js | 1 + .../tests/resource-timing/resources/empty.py | 3 + .../resource-timing/resources/empty_script.js | 0 .../resource-timing/resources/empty_style.css | 1 + .../resource-timing/resources/entry-invariants.js | 511 ++++++++++++++++++++ .../tests/resource-timing/resources/eventsource.py | 3 + .../resource-timing/resources/fake_responses.html | 19 + .../resource-timing/resources/fake_responses.py | 41 ++ .../resources/fake_responses_https.sub.html | 18 + .../fake_responses_https_redirect.sub.html | 20 + .../resource-timing/resources/frame-timing.js | 48 ++ .../resources/frameset-timing-frame.html | 8 + .../resource-timing/resources/green-frame.html | 7 + .../tests/resource-timing/resources/green.html | 10 + .../resource-timing/resources/green.html.headers | 1 + .../tests/resource-timing/resources/gzip_xml.py | 23 + .../resources/iframe-TAO-crossorigin-port.sub.html | 31 ++ .../iframe-load-from-mem-cache-transfer-size.html | 24 + .../resources/iframe-navigate-back.html | 18 + .../resource-timing/resources/iframe-navigate.html | 18 + .../resource-timing/resources/iframe-refresh.html | 18 + .../resources/iframe-reload-TAO.html | 25 + .../resources/iframe-setdomain.sub.html | 14 + .../resources/iframe-with-delay.sub.html | 3 + .../resources/iframe_TAO_match_origin.html | 21 + .../tests/resource-timing/resources/import.sub.css | 1 + .../tests/resource-timing/resources/importer.css | 1 + .../tests/resource-timing/resources/importer.js | 2 + .../resource-timing/resources/importer_async.js | 2 + .../resource-timing/resources/importer_dynamic.css | 1 + .../resource-timing/resources/importer_print.css | 1 + .../resources/inject_resource_test.html | 7 + .../tests/resource-timing/resources/invalid.jpg | 1 + .../tests/resource-timing/resources/manifest.json | 4 + .../resource-timing/resources/multi_redirect.py | 59 +++ .../resource-timing/resources/navigate_back.html | 7 + .../resource-timing/resources/nested-contexts.js | 110 +++++ .../tests/resource-timing/resources/nested.css | 10 + ...origin-css-fetched-memory-cache-iframe.sub.html | 8 + .../resource-timing/resources/notify_parent.html | 4 + .../resources/object-navigate-back.html | 18 + .../resource-timing/resources/object-navigate.html | 18 + .../resource-timing/resources/object-refresh.html | 18 + .../resource-timing/resources/observe-entry.js | 25 + .../tests/resource-timing/resources/preflight.py | 9 + .../resource-timing/resources/redirect-cors.py | 22 + .../resources/redirect-without-location.py | 2 + .../resource-timing/resources/resource-loaders.js | 168 +++++++ .../resources/resource-timing-content-length.py | 19 + .../resources/resource_timing_test0.css | 4 + .../resources/resource_timing_test0.html | 15 + .../resources/resource_timing_test0.js | 3 + .../resources/resource_timing_test0.js.headers | 2 + .../resources/resource_timing_test0.png | Bin 0 -> 249 bytes .../resources/resource_timing_test0.xml | 6 + .../resource-timing/resources/self_navigation.html | 1 + .../resource-timing/resources/shared-worker.js | 3 + .../resource-timing/resources/sizes-helper.js | 16 + .../tests/resource-timing/resources/status-code.py | 8 + .../resource-timing/resources/sw-install.html | 58 +++ .../tests/resource-timing/resources/sw.js | 3 + .../resource-timing/resources/tao-response.js | 13 + .../resources/webperftestharness.js | 166 +++++++ .../resources/webperftestharnessextension.js | 188 ++++++++ .../resources/worker_with_images.js | 22 + .../resource-timing/response-status-code.html | 157 +++++++ .../same-origin-from-cross-origin-redirect.html | 31 ++ .../tests/resource-timing/script-rt-entries.html | 37 ++ .../secure-iframe-in-insecure-context.html | 32 ++ .../resource-timing/shared-worker-rt-entry.html | 26 ++ .../tests/resource-timing/sizes-cache.any.js | 55 +++ .../tests/resource-timing/sizes-redirect-img.html | 57 +++ .../tests/resource-timing/sizes-redirect.any.js | 62 +++ .../web-platform/tests/resource-timing/sleep.py | 13 + .../resource-timing/status-codes-create-entry.html | 40 ++ .../resource-timing/supported_resource_type.any.js | 24 + .../resource-timing/test_resource_timing.html | 24 + .../test_resource_timing.https.html | 24 + .../tests/resource-timing/test_resource_timing.js | 228 +++++++++ .../web-platform/tests/resource-timing/tojson.html | 71 +++ .../workerStart-tao-protected.https.html | 76 +++ .../resource-timing/worklet-rt-entries.https.html | 19 + .../tests/resource-timing/xhr-resource-timing.html | 29 ++ 206 files changed, 7827 insertions(+) create mode 100644 testing/web-platform/tests/resource-timing/304-response-recorded.html create mode 100644 testing/web-platform/tests/resource-timing/CodingConventions.md create mode 100644 testing/web-platform/tests/resource-timing/META.yml create mode 100644 testing/web-platform/tests/resource-timing/SO-XO-SO-redirect-chain-tao.https.html create mode 100644 testing/web-platform/tests/resource-timing/SyntheticResponse.py create mode 100644 testing/web-platform/tests/resource-timing/TAO-match.html create mode 100644 testing/web-platform/tests/resource-timing/TAO-port-mismatch-means-crossorigin.html create mode 100644 testing/web-platform/tests/resource-timing/__init__.py create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-add-after-full-event.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback-that-drop.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-add-then-clear.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-decrease-buffer-during-callback.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-eventually.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-increase-buffer-during-callback.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-inspect-buffer-during-callback.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-set-to-current-buffer.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-store-and-clear-during-callback.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-then-decreased.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-then-increased.html create mode 100644 testing/web-platform/tests/resource-timing/buffer-full-when-populate-entries.html create mode 100644 testing/web-platform/tests/resource-timing/buffered-flag.any.js create mode 100644 testing/web-platform/tests/resource-timing/cached-image-gets-single-entry.html create mode 100644 testing/web-platform/tests/resource-timing/clear-resource-timings.html create mode 100644 testing/web-platform/tests/resource-timing/connection-reuse.html create mode 100644 testing/web-platform/tests/resource-timing/connection-reuse.https.html create mode 100644 testing/web-platform/tests/resource-timing/content-type-parsing.html create mode 100644 testing/web-platform/tests/resource-timing/content-type.html create mode 100644 testing/web-platform/tests/resource-timing/cors-preflight.any.js create mode 100644 testing/web-platform/tests/resource-timing/cross-origin-iframe.html create mode 100644 testing/web-platform/tests/resource-timing/cross-origin-redirects.html create mode 100644 testing/web-platform/tests/resource-timing/cross-origin-start-end-time-with-redirects.html create mode 100644 testing/web-platform/tests/resource-timing/cross-origin-status-codes.html create mode 100644 testing/web-platform/tests/resource-timing/delivery-type.tentative.any.js create mode 100644 testing/web-platform/tests/resource-timing/document-domain-no-impact-opener.html create mode 100644 testing/web-platform/tests/resource-timing/entries-for-network-errors.sub.https.html create mode 100644 testing/web-platform/tests/resource-timing/entry-attributes.html create mode 100644 testing/web-platform/tests/resource-timing/event-source-timing.html create mode 100644 testing/web-platform/tests/resource-timing/fetch-cross-origin-redirect.https.html create mode 100644 testing/web-platform/tests/resource-timing/font-timestamps.html create mode 100644 testing/web-platform/tests/resource-timing/frameset-timing.html create mode 100644 testing/web-platform/tests/resource-timing/idlharness.any.js create mode 100644 testing/web-platform/tests/resource-timing/iframe-failed-commit.html create mode 100644 testing/web-platform/tests/resource-timing/iframe-non-html.html create mode 100644 testing/web-platform/tests/resource-timing/iframe-redirect-without-location.html create mode 100644 testing/web-platform/tests/resource-timing/iframe-sequence-of-events.html create mode 100644 testing/web-platform/tests/resource-timing/iframe-with-download.html create mode 100644 testing/web-platform/tests/resource-timing/image-sequence-of-events.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type-for-script.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/audio.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/dynamic-insertion.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/embed.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/frameset.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/iframe.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/img-srcset.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/img.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/input.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/link.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/misc.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/picture.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/resources/initiator-type-test.js create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/script.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/style.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/svg.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/video.html create mode 100644 testing/web-platform/tests/resource-timing/initiator-type/workers.html create mode 100644 testing/web-platform/tests/resource-timing/input-sequence-of-events.html create mode 100644 testing/web-platform/tests/resource-timing/link-sequence-of-events.html create mode 100644 testing/web-platform/tests/resource-timing/load-from-mem-cache-transfer-size.html create mode 100644 testing/web-platform/tests/resource-timing/nested-context-navigations-embed.html create mode 100644 testing/web-platform/tests/resource-timing/nested-context-navigations-iframe.html create mode 100644 testing/web-platform/tests/resource-timing/nested-context-navigations-object.html create mode 100644 testing/web-platform/tests/resource-timing/nextHopProtocol-is-tao-protected.https.html create mode 100644 testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html create mode 100644 testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched.sub.html create mode 100644 testing/web-platform/tests/resource-timing/object-not-found-adds-entry.html create mode 100644 testing/web-platform/tests/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html create mode 100644 testing/web-platform/tests/resource-timing/object-not-found-after-cross-origin-redirect.html create mode 100644 testing/web-platform/tests/resource-timing/opaque-origin.html create mode 100644 testing/web-platform/tests/resource-timing/ping-rt-entries.html create mode 100644 testing/web-platform/tests/resource-timing/redirects.html create mode 100644 testing/web-platform/tests/resource-timing/render-blocking-status-link.html create mode 100644 testing/web-platform/tests/resource-timing/render-blocking-status-script.html create mode 100644 testing/web-platform/tests/resource-timing/resource-ignore-data-url.html create mode 100644 testing/web-platform/tests/resource-timing/resource-reload-TAO.html create mode 100644 testing/web-platform/tests/resource-timing/resource-timing-level1.js create mode 100644 testing/web-platform/tests/resource-timing/resource-timing-level1.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resource_connection_reuse_mixed_content.html create mode 100644 testing/web-platform/tests/resource-timing/resource_connection_reuse_mixed_content_redirect.html create mode 100644 testing/web-platform/tests/resource-timing/resource_dedicated_worker.html create mode 100644 testing/web-platform/tests/resource-timing/resource_nested_dedicated_worker.worker.js create mode 100644 testing/web-platform/tests/resource-timing/resource_reparenting.html create mode 100644 testing/web-platform/tests/resource-timing/resource_subframe_self_navigation.html create mode 100644 testing/web-platform/tests/resource-timing/resource_timing.worker.js create mode 100644 testing/web-platform/tests/resource-timing/resource_timing_content_length.html create mode 100644 testing/web-platform/tests/resource-timing/resources/200.https.asis create mode 100644 testing/web-platform/tests/resource-timing/resources/200_empty.asis create mode 100644 testing/web-platform/tests/resource-timing/resources/204_empty.asis create mode 100644 testing/web-platform/tests/resource-timing/resources/205_empty.asis create mode 100644 testing/web-platform/tests/resource-timing/resources/TAOResponse.py create mode 100644 testing/web-platform/tests/resource-timing/resources/blank-with-tao.html create mode 100644 testing/web-platform/tests/resource-timing/resources/blank-with-tao.html.headers create mode 100644 testing/web-platform/tests/resource-timing/resources/blue-with-tao.png create mode 100644 testing/web-platform/tests/resource-timing/resources/blue-with-tao.png.headers create mode 100644 testing/web-platform/tests/resource-timing/resources/blue.png create mode 100644 testing/web-platform/tests/resource-timing/resources/buffer-full-utilities.js create mode 100644 testing/web-platform/tests/resource-timing/resources/cacheable-and-validated.py create mode 100644 testing/web-platform/tests/resource-timing/resources/close.html create mode 100644 testing/web-platform/tests/resource-timing/resources/connection-reuse-test.js create mode 100644 testing/web-platform/tests/resource-timing/resources/content-type.py create mode 100644 testing/web-platform/tests/resource-timing/resources/cors-ahem.py create mode 100644 testing/web-platform/tests/resource-timing/resources/csp-default-none.html create mode 100644 testing/web-platform/tests/resource-timing/resources/csp-default-none.html.headers create mode 100644 testing/web-platform/tests/resource-timing/resources/delay-css.py create mode 100644 testing/web-platform/tests/resource-timing/resources/document-domain-no-impact.html create mode 100644 testing/web-platform/tests/resource-timing/resources/document-navigated.html create mode 100644 testing/web-platform/tests/resource-timing/resources/document-refreshed.html create mode 100644 testing/web-platform/tests/resource-timing/resources/document-that-navigates.html create mode 100644 testing/web-platform/tests/resource-timing/resources/document-that-refreshes.html create mode 100644 testing/web-platform/tests/resource-timing/resources/download.asis create mode 100644 testing/web-platform/tests/resource-timing/resources/embed-navigate-back.html create mode 100644 testing/web-platform/tests/resource-timing/resources/embed-navigate.html create mode 100644 testing/web-platform/tests/resource-timing/resources/embed-refresh.html create mode 100644 testing/web-platform/tests/resource-timing/resources/empty.js create mode 100644 testing/web-platform/tests/resource-timing/resources/empty.py create mode 100644 testing/web-platform/tests/resource-timing/resources/empty_script.js create mode 100644 testing/web-platform/tests/resource-timing/resources/empty_style.css create mode 100644 testing/web-platform/tests/resource-timing/resources/entry-invariants.js create mode 100644 testing/web-platform/tests/resource-timing/resources/eventsource.py create mode 100644 testing/web-platform/tests/resource-timing/resources/fake_responses.html create mode 100644 testing/web-platform/tests/resource-timing/resources/fake_responses.py create mode 100644 testing/web-platform/tests/resource-timing/resources/fake_responses_https.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/fake_responses_https_redirect.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/frame-timing.js create mode 100644 testing/web-platform/tests/resource-timing/resources/frameset-timing-frame.html create mode 100644 testing/web-platform/tests/resource-timing/resources/green-frame.html create mode 100644 testing/web-platform/tests/resource-timing/resources/green.html create mode 100644 testing/web-platform/tests/resource-timing/resources/green.html.headers create mode 100644 testing/web-platform/tests/resource-timing/resources/gzip_xml.py create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-load-from-mem-cache-transfer-size.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-navigate-back.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-navigate.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-refresh.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-reload-TAO.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-setdomain.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe-with-delay.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html create mode 100644 testing/web-platform/tests/resource-timing/resources/import.sub.css create mode 100644 testing/web-platform/tests/resource-timing/resources/importer.css create mode 100644 testing/web-platform/tests/resource-timing/resources/importer.js create mode 100644 testing/web-platform/tests/resource-timing/resources/importer_async.js create mode 100644 testing/web-platform/tests/resource-timing/resources/importer_dynamic.css create mode 100644 testing/web-platform/tests/resource-timing/resources/importer_print.css create mode 100644 testing/web-platform/tests/resource-timing/resources/inject_resource_test.html create mode 100644 testing/web-platform/tests/resource-timing/resources/invalid.jpg create mode 100644 testing/web-platform/tests/resource-timing/resources/manifest.json create mode 100644 testing/web-platform/tests/resource-timing/resources/multi_redirect.py create mode 100644 testing/web-platform/tests/resource-timing/resources/navigate_back.html create mode 100644 testing/web-platform/tests/resource-timing/resources/nested-contexts.js create mode 100644 testing/web-platform/tests/resource-timing/resources/nested.css create mode 100644 testing/web-platform/tests/resource-timing/resources/no-entries-for-cross-origin-css-fetched-memory-cache-iframe.sub.html create mode 100644 testing/web-platform/tests/resource-timing/resources/notify_parent.html create mode 100644 testing/web-platform/tests/resource-timing/resources/object-navigate-back.html create mode 100644 testing/web-platform/tests/resource-timing/resources/object-navigate.html create mode 100644 testing/web-platform/tests/resource-timing/resources/object-refresh.html create mode 100644 testing/web-platform/tests/resource-timing/resources/observe-entry.js create mode 100644 testing/web-platform/tests/resource-timing/resources/preflight.py create mode 100644 testing/web-platform/tests/resource-timing/resources/redirect-cors.py create mode 100644 testing/web-platform/tests/resource-timing/resources/redirect-without-location.py create mode 100644 testing/web-platform/tests/resource-timing/resources/resource-loaders.js create mode 100644 testing/web-platform/tests/resource-timing/resources/resource-timing-content-length.py create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.css create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.html create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js.headers create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.png create mode 100644 testing/web-platform/tests/resource-timing/resources/resource_timing_test0.xml create mode 100644 testing/web-platform/tests/resource-timing/resources/self_navigation.html create mode 100644 testing/web-platform/tests/resource-timing/resources/shared-worker.js create mode 100644 testing/web-platform/tests/resource-timing/resources/sizes-helper.js create mode 100644 testing/web-platform/tests/resource-timing/resources/status-code.py create mode 100644 testing/web-platform/tests/resource-timing/resources/sw-install.html create mode 100644 testing/web-platform/tests/resource-timing/resources/sw.js create mode 100644 testing/web-platform/tests/resource-timing/resources/tao-response.js create mode 100644 testing/web-platform/tests/resource-timing/resources/webperftestharness.js create mode 100644 testing/web-platform/tests/resource-timing/resources/webperftestharnessextension.js create mode 100644 testing/web-platform/tests/resource-timing/resources/worker_with_images.js create mode 100644 testing/web-platform/tests/resource-timing/response-status-code.html create mode 100644 testing/web-platform/tests/resource-timing/same-origin-from-cross-origin-redirect.html create mode 100644 testing/web-platform/tests/resource-timing/script-rt-entries.html create mode 100644 testing/web-platform/tests/resource-timing/secure-iframe-in-insecure-context.html create mode 100644 testing/web-platform/tests/resource-timing/shared-worker-rt-entry.html create mode 100644 testing/web-platform/tests/resource-timing/sizes-cache.any.js create mode 100644 testing/web-platform/tests/resource-timing/sizes-redirect-img.html create mode 100644 testing/web-platform/tests/resource-timing/sizes-redirect.any.js create mode 100644 testing/web-platform/tests/resource-timing/sleep.py create mode 100644 testing/web-platform/tests/resource-timing/status-codes-create-entry.html create mode 100644 testing/web-platform/tests/resource-timing/supported_resource_type.any.js create mode 100644 testing/web-platform/tests/resource-timing/test_resource_timing.html create mode 100644 testing/web-platform/tests/resource-timing/test_resource_timing.https.html create mode 100644 testing/web-platform/tests/resource-timing/test_resource_timing.js create mode 100644 testing/web-platform/tests/resource-timing/tojson.html create mode 100644 testing/web-platform/tests/resource-timing/workerStart-tao-protected.https.html create mode 100644 testing/web-platform/tests/resource-timing/worklet-rt-entries.https.html create mode 100644 testing/web-platform/tests/resource-timing/xhr-resource-timing.html (limited to 'testing/web-platform/tests/resource-timing') diff --git a/testing/web-platform/tests/resource-timing/304-response-recorded.html b/testing/web-platform/tests/resource-timing/304-response-recorded.html new file mode 100644 index 0000000000..9e1bb3045c --- /dev/null +++ b/testing/web-platform/tests/resource-timing/304-response-recorded.html @@ -0,0 +1,53 @@ + + + + +Resource Timing - cached resources generate performance entries + + + + + + + + +

Description

+

This test validates that a 304 Not Modified resource appears in the +Performance Timeline.

+ + + diff --git a/testing/web-platform/tests/resource-timing/CodingConventions.md b/testing/web-platform/tests/resource-timing/CodingConventions.md new file mode 100644 index 0000000000..39b8d13435 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/CodingConventions.md @@ -0,0 +1,77 @@ +For [Resource Timing][1] tests, we want to have a consistent and clear coding +style. The goals of this style are to: +* Make it easier for new contributors to find their way around +* Help improve readability and maintainability +* Help us understand which parts of the spec are tested or not +Lots of the following rules are arbitrary but the value is realized in +consistency instead of adhering to the 'perfect' style. + +We want the test suite to be navigable. Developers should be able to easily +find the file or test that is relevant to their work. +* Tests should be arranged in files according to which piece of the spec they + test +* Files should be named using a consistent pattern +* HTML files should include useful meta tags + * `` for controlling labels in results pages + * `<link rel="help">` to point at the relevant piece of the spec + +We want the test suite to run consistently. Flaky tests are counterproductive. +* Prefer `promise_test` to `async_test` + * Note that there’s [still potential for some concurrency][2]; use + `add_cleanup()` if needed + +We want the tests to be readable. Tests should be written in a modern style +with recurring patterns. +* 80 character line limits where we can +* Consistent use of anonymous functions + * prefer + ``` + const func1 = param1 => { + body(); + } + const func2 = (param1, param2) => { + body(); + } + fn(param => { + body(); + }); + ``` + + over + + ``` + function func1(param1) { + body(); + } + function func2(param1, param2) { + body(); + } + fn(function(param) { + body(); + }); + ``` + +* Prefer `const` (or, if needed, `let`) to `var` +* Contain use of ‘.sub’ in filenames to known helper utilities where possible + * E.g. prefer use of get-host-info.sub.js to `{{host}}` or `{{ports[0]}}` + expressions +* Avoid use of webperftestharness[extension].js as it’s a layer of cognitive + overhead between test content and test intent + * Helper .js files are still encouraged where it makes sense but we want + to avoid a testing framework that is specific to Resource Timing (or + web performance APIs, in general). +* Prefer [`fetch_tests_from_window`][3] to collect test results from embedded + iframes instead of hand-rolled `postMessage` approaches +* Use the [`assert_*`][4] family of functions to check conformance to the spec + but throw exceptions explicitly when the test itself is broken. + * A failed assert indicates "the implementation doesn't conform to the + spec" + * Other uncaught exceptions indicate "the test case itself has a bug" +* Where possible, we want tests to be scalable - adding another test case + should be as simple as calling the tests with new parameters, rather than + copying an existing test and modifying it. + +[1]: https://www.w3.org/TR/resource-timing-2/ +[2]: https://web-platform-tests.org/writing-tests/testharness-api.html#promise-tests +[3]: https://web-platform-tests.org/writing-tests/testharness-api.html#consolidating-tests-from-other-documents +[4]: https://web-platform-tests.org/writing-tests/testharness-api.html#list-of-assertions diff --git a/testing/web-platform/tests/resource-timing/META.yml b/testing/web-platform/tests/resource-timing/META.yml new file mode 100644 index 0000000000..662c42cb66 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/META.yml @@ -0,0 +1,6 @@ +spec: https://w3c.github.io/resource-timing/ +suggested_reviewers: + - plehegar + - zqzhang + - igrigorik + - yoavweiss diff --git a/testing/web-platform/tests/resource-timing/SO-XO-SO-redirect-chain-tao.https.html b/testing/web-platform/tests/resource-timing/SO-XO-SO-redirect-chain-tao.https.html new file mode 100644 index 0000000000..e6568910e4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/SO-XO-SO-redirect-chain-tao.https.html @@ -0,0 +1,64 @@ +<!DOCTYPE HTML> +<html> +<head> +<meta charset="utf-8" /> +<title>This test validates resource timing information for a same-origin=>cross-origin=>same-origin redirect chain without Timing-Allow-Origin. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/SyntheticResponse.py b/testing/web-platform/tests/resource-timing/SyntheticResponse.py new file mode 100644 index 0000000000..6f888f3789 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/SyntheticResponse.py @@ -0,0 +1,50 @@ +from urllib.parse import unquote + +from wptserve.utils import isomorphic_decode, isomorphic_encode + +import importlib +sleep = importlib.import_module("resource-timing.sleep") + +def main(request, response): + index = isomorphic_encode(request.request_path).index(b"?") + args = isomorphic_encode(request.request_path[index+1:]).split(b"&") + headers = [] + statusSent = False + headersSent = False + for arg in args: + if arg.startswith(b"ignored"): + continue + elif arg.endswith(b"ms"): + sleep.sleep_at_least(float(arg[0:-2])) + elif arg.startswith(b"redirect:"): + return (302, u"WEBPERF MARKETING"), [(b"Location", unquote(isomorphic_decode(arg[9:])))], u"TEST" + + elif arg.startswith(b"mime:"): + headers.append((b"Content-Type", unquote(isomorphic_decode(arg[5:])))) + + elif arg.startswith(b"send:"): + text = unquote(isomorphic_decode(arg[5:])) + + if not statusSent: + # Default to a 200 status code. + response.writer.write_status(200) + statusSent = True + if not headersSent: + for key, value in headers: + response.writer.write_header(key, value) + response.writer.end_headers() + headersSent = True + + response.writer.write_content(text) + elif arg.startswith(b"status:"): + code = int(unquote(isomorphic_decode(arg[7:]))) + response.writer.write_status(code) + if code // 100 == 1: + # Terminate informational 1XX responses with an empty line. + response.writer.end_headers() + else: + statusSent = True + +# else: +# error " INVALID ARGUMENT %s" % arg + diff --git a/testing/web-platform/tests/resource-timing/TAO-match.html b/testing/web-platform/tests/resource-timing/TAO-match.html new file mode 100644 index 0000000000..dc0e2f7443 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/TAO-match.html @@ -0,0 +1,82 @@ + + + + +Resource Timing TAO tests + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/TAO-port-mismatch-means-crossorigin.html b/testing/web-platform/tests/resource-timing/TAO-port-mismatch-means-crossorigin.html new file mode 100644 index 0000000000..f1218d17a0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/TAO-port-mismatch-means-crossorigin.html @@ -0,0 +1,46 @@ + + + + +TAO - port mismatch must fail the check + + + + + + + + + +

Description

+

This test validates that for a cross origin resource with different ports, +the timing allow check algorithm will fail when the value of +Timing-Allow-Origin value has the right host but the wrong port in it.

+ + diff --git a/testing/web-platform/tests/resource-timing/__init__.py b/testing/web-platform/tests/resource-timing/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/web-platform/tests/resource-timing/buffer-full-add-after-full-event.html b/testing/web-platform/tests/resource-timing/buffer-full-add-after-full-event.html new file mode 100644 index 0000000000..43dc3d84fd --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-add-after-full-event.html @@ -0,0 +1,27 @@ + + + + + + +This test validates that setResourceTimingBufferFull behaves appropriately when set to the current buffer level. + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback-that-drop.html b/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback-that-drop.html new file mode 100644 index 0000000000..b00185c5b6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback-that-drop.html @@ -0,0 +1,29 @@ + + + + +This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback.html b/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback.html new file mode 100644 index 0000000000..d5883d33d5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-add-entries-during-callback.html @@ -0,0 +1,28 @@ + + + + +This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-add-then-clear.html b/testing/web-platform/tests/resource-timing/buffer-full-add-then-clear.html new file mode 100644 index 0000000000..5617c30b88 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-add-then-clear.html @@ -0,0 +1,31 @@ + + + + +This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-decrease-buffer-during-callback.html b/testing/web-platform/tests/resource-timing/buffer-full-decrease-buffer-during-callback.html new file mode 100644 index 0000000000..3091fcf426 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-decrease-buffer-during-callback.html @@ -0,0 +1,26 @@ + + + + +This test validates that decreasing the buffer size in onresourcetimingbufferfull callback does not result in extra entries being dropped. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-eventually.html b/testing/web-platform/tests/resource-timing/buffer-full-eventually.html new file mode 100644 index 0000000000..6e9d5db483 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-eventually.html @@ -0,0 +1,31 @@ + + + + + +This test validates that resource timing implementations have a finite + number of entries in their buffer. + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-increase-buffer-during-callback.html b/testing/web-platform/tests/resource-timing/buffer-full-increase-buffer-during-callback.html new file mode 100644 index 0000000000..dd12dd7afa --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-increase-buffer-during-callback.html @@ -0,0 +1,26 @@ + + + + +This test validates increasing the buffer size in onresourcetimingbufferfull callback of resource timing. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-inspect-buffer-during-callback.html b/testing/web-platform/tests/resource-timing/buffer-full-inspect-buffer-during-callback.html new file mode 100644 index 0000000000..d5cc8e6ecd --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-inspect-buffer-during-callback.html @@ -0,0 +1,30 @@ + + + + +This test validates the buffer doesn't contain more entries than it should inside onresourcetimingbufferfull callback. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-set-to-current-buffer.html b/testing/web-platform/tests/resource-timing/buffer-full-set-to-current-buffer.html new file mode 100644 index 0000000000..dc527b9a32 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-set-to-current-buffer.html @@ -0,0 +1,34 @@ + + + + +This test validates that setResourceTimingBufferFull behaves appropriately when set to the current buffer level. + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-store-and-clear-during-callback.html b/testing/web-platform/tests/resource-timing/buffer-full-store-and-clear-during-callback.html new file mode 100644 index 0000000000..3ea0577256 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-store-and-clear-during-callback.html @@ -0,0 +1,36 @@ + + + + +This test validates the behavior of read and clear operation in onresourcetimingbufferfull callback of resource timing. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-then-decreased.html b/testing/web-platform/tests/resource-timing/buffer-full-then-decreased.html new file mode 100644 index 0000000000..21912d978b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-then-decreased.html @@ -0,0 +1,29 @@ + + + + +This test validates that reducing the buffer size after entries were + queued does not drop those entries, nor does it call the + resourcetimingbufferfull event callback. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-then-increased.html b/testing/web-platform/tests/resource-timing/buffer-full-then-increased.html new file mode 100644 index 0000000000..de517bf405 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-then-increased.html @@ -0,0 +1,28 @@ + + + + +This test validates that synchronously adding entries in onresourcetimingbufferfull callback results in these entries being properly handled. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffer-full-when-populate-entries.html b/testing/web-platform/tests/resource-timing/buffer-full-when-populate-entries.html new file mode 100644 index 0000000000..f4b1a2e7e7 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffer-full-when-populate-entries.html @@ -0,0 +1,30 @@ + + + + +This test validates the functionality of onresourcetimingbufferfull in resource timing. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/buffered-flag.any.js b/testing/web-platform/tests/resource-timing/buffered-flag.any.js new file mode 100644 index 0000000000..b46fd00e69 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/buffered-flag.any.js @@ -0,0 +1,18 @@ +async_test(t => { + performance.clearResourceTimings(); + // First observer creates second in callback to ensure the entry has been dispatched by the time + // the second observer begins observing. + new PerformanceObserver(() => { + // Second observer requires 'buffered: true' to see an entry. + new PerformanceObserver(t.step_func_done(list => { + const entries = list.getEntries(); + assert_equals(entries.length, 1, 'There should be 1 resource entry.'); + assert_equals(entries[0].entryType, 'resource'); + assert_greater_than(entries[0].startTime, 0); + assert_greater_than(entries[0].responseEnd, entries[0].startTime); + assert_greater_than(entries[0].duration, 0); + assert_true(entries[0].name.endsWith('resources/empty.js')); + })).observe({'type': 'resource', buffered: true}); + }).observe({'entryTypes': ['resource']}); + fetch('resources/empty.js'); +}, 'PerformanceObserver with buffered flag sees previous resource entries.'); diff --git a/testing/web-platform/tests/resource-timing/cached-image-gets-single-entry.html b/testing/web-platform/tests/resource-timing/cached-image-gets-single-entry.html new file mode 100644 index 0000000000..2d8c4e2e83 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cached-image-gets-single-entry.html @@ -0,0 +1,67 @@ + + + + +Resource Timing: test behavior for cached resources + + + + + + + +

Description

+

Test that a reused resource only appears in the buffer once.

+ + + diff --git a/testing/web-platform/tests/resource-timing/clear-resource-timings.html b/testing/web-platform/tests/resource-timing/clear-resource-timings.html new file mode 100644 index 0000000000..7508f8432e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/clear-resource-timings.html @@ -0,0 +1,22 @@ + + + + +This test validates the functionality of clearResourceTimings method +in resource timing. + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/connection-reuse.html b/testing/web-platform/tests/resource-timing/connection-reuse.html new file mode 100644 index 0000000000..a1bc927cfd --- /dev/null +++ b/testing/web-platform/tests/resource-timing/connection-reuse.html @@ -0,0 +1,56 @@ + + + + +Resource Timing connection reuse + + + + + + + + + + +

Description

+

See the included test + script

+ + diff --git a/testing/web-platform/tests/resource-timing/connection-reuse.https.html b/testing/web-platform/tests/resource-timing/connection-reuse.https.html new file mode 100644 index 0000000000..3461eed472 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/connection-reuse.https.html @@ -0,0 +1,25 @@ + + + + +Resource Timing connection reuse + + + + + + + + + +

Description

+

See the included test + script

+ + diff --git a/testing/web-platform/tests/resource-timing/content-type-parsing.html b/testing/web-platform/tests/resource-timing/content-type-parsing.html new file mode 100644 index 0000000000..c0081eb413 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/content-type-parsing.html @@ -0,0 +1,76 @@ + + + +This test validates the parsing of content-type of resources. + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/content-type.html b/testing/web-platform/tests/resource-timing/content-type.html new file mode 100644 index 0000000000..f6b1db7d9f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/content-type.html @@ -0,0 +1,117 @@ + + + +This test validates the content-type of resources. + + + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/cors-preflight.any.js b/testing/web-platform/tests/resource-timing/cors-preflight.any.js new file mode 100644 index 0000000000..4b980e7d0a --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cors-preflight.any.js @@ -0,0 +1,49 @@ +// META: script=/common/utils.js +// META: script=/common/get-host-info.sub.js + +// Because apache decrements the Keep-Alive max value on each request, the +// transferSize will vary slightly between requests for the same resource. +const fuzzFactor = 3; // bytes + +const {HTTP_REMOTE_ORIGIN} = get_host_info(); +const url = new URL('/resource-timing/resources/preflight.py', + HTTP_REMOTE_ORIGIN).href; + +// The header bytes are expected to be > |minHeaderSize| and +// < |maxHeaderSize|. If they are outside this range the test will fail. +const minHeaderSize = 100; +const maxHeaderSize = 1024; + +promise_test(async () => { + const checkCorsAllowed = response => response.arrayBuffer(); + const requirePreflight = {headers: {'X-Require-Preflight' : '1'}}; + const collectEntries = new Promise(resolve => { + let entriesSeen = []; + new PerformanceObserver(entryList => { + entriesSeen = entriesSeen.concat(entryList.getEntries()); + if (entriesSeen.length > 2) { + throw new Error(`Saw too many PerformanceResourceTiming entries ` + + `(${entriesSeen.length})`); + } + if (entriesSeen.length == 2) { + resolve(entriesSeen); + } + }).observe({"type": "resource"}); + }); + + // Although this fetch doesn't send a pre-flight request, the server response + // will allow cross-origin requests explicitly with the + // Access-Control-Allow-Origin header. + await fetch(url).then(checkCorsAllowed); + + // This fetch will send a pre-flight request to do the CORS handshake + // explicitly. + await fetch(url, requirePreflight).then(checkCorsAllowed); + + const entries = await collectEntries; + assert_greater_than(entries[0].transferSize, 0, 'No-preflight transferSize'); + const lowerBound = entries[0].transferSize - fuzzFactor; + const upperBound = entries[0].transferSize + fuzzFactor; + assert_between_exclusive(entries[1].transferSize, lowerBound, upperBound, + 'Preflighted transferSize'); +}, 'PerformanceResourceTiming sizes fetch with preflight test'); diff --git a/testing/web-platform/tests/resource-timing/cross-origin-iframe.html b/testing/web-platform/tests/resource-timing/cross-origin-iframe.html new file mode 100644 index 0000000000..69daebffaf --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cross-origin-iframe.html @@ -0,0 +1,33 @@ + + +Test ResourceTiming reporting for cross-origin iframe. + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/cross-origin-redirects.html b/testing/web-platform/tests/resource-timing/cross-origin-redirects.html new file mode 100644 index 0000000000..0bdc0547e5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cross-origin-redirects.html @@ -0,0 +1,102 @@ + + + + +This test validates the values in resource timing for cross-origin +redirects. + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/cross-origin-start-end-time-with-redirects.html b/testing/web-platform/tests/resource-timing/cross-origin-start-end-time-with-redirects.html new file mode 100644 index 0000000000..1b107d3aef --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cross-origin-start-end-time-with-redirects.html @@ -0,0 +1,32 @@ + + + + +This test validates the values in resource timing for cross-origin +redirects. + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/cross-origin-status-codes.html b/testing/web-platform/tests/resource-timing/cross-origin-status-codes.html new file mode 100644 index 0000000000..197a766339 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/cross-origin-status-codes.html @@ -0,0 +1,70 @@ + + + +Resource Timing: PerformanceResourceTiming attributes shouldn't change + if the HTTP status code changes + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/delivery-type.tentative.any.js b/testing/web-platform/tests/resource-timing/delivery-type.tentative.any.js new file mode 100644 index 0000000000..e2b408fdd7 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/delivery-type.tentative.any.js @@ -0,0 +1,90 @@ +// META: global=window,worker +// META: script=/common/get-host-info.sub.js +// META: script=/resource-timing/resources/resource-loaders.js + +// TODO(crbug/1358591): Rename this file from "tentative" once +// `w3c/resource-timing#343` is merged. + +const {REMOTE_ORIGIN, ORIGIN} = get_host_info(); + +const redirectBase = new URL( + '/resource-timing/resources/redirect-cors.py', REMOTE_ORIGIN).href; +const cacheAndValidatedBase = new URL( + '/resource-timing/resources/cacheable-and-validated.py?content=content', + ORIGIN).href; + +const mustRevalidate = {headers: {'Cache-Control': 'max-age=0'}}; + +const fetchAndEatBody = (url, fetchOption) => { + return fetch(url, fetchOption).then(response => response.arrayBuffer()); +}; + +const accumulateEntries = () => { + return new Promise(resolve => { + const po = new PerformanceObserver(list => { + resolve(list); + }); + po.observe({type: "resource", buffered: true}); + }); +}; + +const checkDeliveryTypeBase = + (list, lookupURL, deliveryTypeForCachedResources) => { + const entries = list.getEntriesByName(lookupURL); + assert_equals(entries.length, 3, 'Wrong number of entries'); + + // 200 response (`cacheMode` is an empty string) + assert_equals(entries[0].deliveryType, "", + "Expect empty deliveryType for 200 response."); + // Cached response (`cacheMode` is "local") or 304 response (`cacheMode` is + // "validated"). + assert_equals(entries[1].deliveryType, deliveryTypeForCachedResources, + `Expect "${deliveryTypeForCachedResources}" deliveryType for a + cached response.`); + assert_equals(entries[2].deliveryType, deliveryTypeForCachedResources, + `Expect "${deliveryTypeForCachedResources}" deliveryType for a + revalidated response.`); +}; + +promise_test(() => { + // Use a different URL every time so that the cache behaviour does not depend + // on execution order. + const initialURL = load.cache_bust(cacheAndValidatedBase); + const checkDeliveryType = + list => checkDeliveryTypeBase(list, initialURL, "cache"); + return fetchAndEatBody(initialURL, {}) // 200. + .then(() => fetchAndEatBody(initialURL, {})) // Cached. + .then(() => fetchAndEatBody(initialURL, mustRevalidate)) // 304. + .then(accumulateEntries) + .then(checkDeliveryType); +}, 'PerformanceResourceTiming deliveryType test, same origin.'); + +promise_test(() => { + const cacheAndValidatedURL = load.cache_bust( + cacheAndValidatedBase + '&timing_allow_origin=*'); + const redirectURL = redirectBase + + "?timing_allow_origin=*" + + `&allow_origin=${encodeURIComponent(ORIGIN)}` + + `&location=${encodeURIComponent(cacheAndValidatedURL)}`; + const checkDeliveryType = + list => checkDeliveryTypeBase(list, redirectURL, "cache"); + return fetchAndEatBody(redirectURL, {}) // 200. + .then(() => fetchAndEatBody(redirectURL, {})) // Cached. + .then(() => fetchAndEatBody(redirectURL, mustRevalidate)) // 304. + .then(accumulateEntries) + .then(checkDeliveryType); +}, 'PerformanceResourceTiming deliveryType test, cross origin, TAO passes.'); + +promise_test(() => { + const cacheAndValidatedURL = load.cache_bust(cacheAndValidatedBase); + const redirectURL = redirectBase + + `?allow_origin=${encodeURIComponent(ORIGIN)}` + + `&location=${encodeURIComponent(cacheAndValidatedURL)}`; + const checkDeliveryType = + list => checkDeliveryTypeBase(list, redirectURL, ""); + return fetchAndEatBody(redirectURL, {}) // 200. + .then(() => fetchAndEatBody(redirectURL, {})) // Cached. + .then(() => fetchAndEatBody(redirectURL, mustRevalidate)) // 304. + .then(accumulateEntries) + .then(checkDeliveryType); +}, 'PerformanceResourceTiming deliveryType test, cross origin, TAO fails.'); diff --git a/testing/web-platform/tests/resource-timing/document-domain-no-impact-opener.html b/testing/web-platform/tests/resource-timing/document-domain-no-impact-opener.html new file mode 100644 index 0000000000..69df2f27fa --- /dev/null +++ b/testing/web-platform/tests/resource-timing/document-domain-no-impact-opener.html @@ -0,0 +1,16 @@ + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/entries-for-network-errors.sub.https.html b/testing/web-platform/tests/resource-timing/entries-for-network-errors.sub.https.html new file mode 100644 index 0000000000..95849d2826 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/entries-for-network-errors.sub.https.html @@ -0,0 +1,35 @@ + + + + +This test validates that a failed cross-origin fetch creates an opaque network timing entry. + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/entry-attributes.html b/testing/web-platform/tests/resource-timing/entry-attributes.html new file mode 100644 index 0000000000..94f219f229 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/entry-attributes.html @@ -0,0 +1,39 @@ + + + + +Resource Timing: PerformanceResourceTiming attributes + + + + + + + + + +

Description

+

This test validates that PerformanceResourceTiming entries' attributes are +populated with the correct values.

+ + diff --git a/testing/web-platform/tests/resource-timing/event-source-timing.html b/testing/web-platform/tests/resource-timing/event-source-timing.html new file mode 100644 index 0000000000..917e7c3495 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/event-source-timing.html @@ -0,0 +1,32 @@ + + + + + +Resource Timing: EventSource timing behavior + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/fetch-cross-origin-redirect.https.html b/testing/web-platform/tests/resource-timing/fetch-cross-origin-redirect.https.html new file mode 100644 index 0000000000..4193422653 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/fetch-cross-origin-redirect.https.html @@ -0,0 +1,33 @@ + + +Test cross-origin fetch redirects have the right values. + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/font-timestamps.html b/testing/web-platform/tests/resource-timing/font-timestamps.html new file mode 100644 index 0000000000..56ecb5c4bf --- /dev/null +++ b/testing/web-platform/tests/resource-timing/font-timestamps.html @@ -0,0 +1,62 @@ + + +Test cross-origin fetch redirects have the right values. + + + + + diff --git a/testing/web-platform/tests/resource-timing/frameset-timing.html b/testing/web-platform/tests/resource-timing/frameset-timing.html new file mode 100644 index 0000000000..1a6facbfc4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/frameset-timing.html @@ -0,0 +1,6 @@ + + +Test the sequence of events when reporting timing for frames. + + + diff --git a/testing/web-platform/tests/resource-timing/idlharness.any.js b/testing/web-platform/tests/resource-timing/idlharness.any.js new file mode 100644 index 0000000000..aa860d3dd1 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/idlharness.any.js @@ -0,0 +1,24 @@ +// META: script=/resources/WebIDLParser.js +// META: script=/resources/idlharness.js +// META: timeout=long + +'use strict'; + +// https://w3c.github.io/resource-timing/ + +idl_test( + ['resource-timing'], + ['performance-timeline', 'hr-time', 'dom', 'html'], + idl_array => { + try { + self.resource = performance.getEntriesByType('resource')[0]; + } catch (e) { + // Will be surfaced when resource is undefined below. + } + + idl_array.add_objects({ + Performance: ['performance'], + PerformanceResourceTiming: ['resource'] + }); + } +); diff --git a/testing/web-platform/tests/resource-timing/iframe-failed-commit.html b/testing/web-platform/tests/resource-timing/iframe-failed-commit.html new file mode 100644 index 0000000000..1da207d2fb --- /dev/null +++ b/testing/web-platform/tests/resource-timing/iframe-failed-commit.html @@ -0,0 +1,108 @@ + + + + +Resource Timing - test that unsuccessful iframes create entries + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/iframe-non-html.html b/testing/web-platform/tests/resource-timing/iframe-non-html.html new file mode 100644 index 0000000000..a5df3b0348 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/iframe-non-html.html @@ -0,0 +1,23 @@ + + +Test the sequence of events when reporting iframe timing. + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/iframe-redirect-without-location.html b/testing/web-platform/tests/resource-timing/iframe-redirect-without-location.html new file mode 100644 index 0000000000..bae5f3112f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/iframe-redirect-without-location.html @@ -0,0 +1,17 @@ + + +Test the sequence of events when reporting iframe timing. + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/iframe-sequence-of-events.html b/testing/web-platform/tests/resource-timing/iframe-sequence-of-events.html new file mode 100644 index 0000000000..5f99a5cab2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/iframe-sequence-of-events.html @@ -0,0 +1,12 @@ + + +Test the sequence of events when reporting iframe timing. + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/iframe-with-download.html b/testing/web-platform/tests/resource-timing/iframe-with-download.html new file mode 100644 index 0000000000..9583024dd8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/iframe-with-download.html @@ -0,0 +1,24 @@ + + +Test the sequence of events when reporting iframe timing. + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/image-sequence-of-events.html b/testing/web-platform/tests/resource-timing/image-sequence-of-events.html new file mode 100644 index 0000000000..630fed78c9 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/image-sequence-of-events.html @@ -0,0 +1,29 @@ + + +Test the sequence of events when reporting image timing. + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type-for-script.html b/testing/web-platform/tests/resource-timing/initiator-type-for-script.html new file mode 100644 index 0000000000..72173398d5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type-for-script.html @@ -0,0 +1,67 @@ + + + + +This test validates that the initiatorType information for various +Resource Timing entries is accurate for scripts. + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/audio.html b/testing/web-platform/tests/resource-timing/initiator-type/audio.html new file mode 100644 index 0000000000..f09fc61847 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/audio.html @@ -0,0 +1,34 @@ + + + + +Resource Timing initiator type: audio + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/dynamic-insertion.html b/testing/web-platform/tests/resource-timing/initiator-type/dynamic-insertion.html new file mode 100644 index 0000000000..8ce05b3cfe --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/dynamic-insertion.html @@ -0,0 +1,41 @@ + + + + +Resource Timing - initiatorType with dynamic insertion + + + + + + + + + +

Description

+

This test validates that the initiatorType field is correct even when an +element is dynamically inserted.

+ + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/embed.html b/testing/web-platform/tests/resource-timing/initiator-type/embed.html new file mode 100644 index 0000000000..c7a505afac --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/embed.html @@ -0,0 +1,20 @@ + + + + +Resource Timing initiator type: embed + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/frameset.html b/testing/web-platform/tests/resource-timing/initiator-type/frameset.html new file mode 100644 index 0000000000..697549a14d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/frameset.html @@ -0,0 +1,22 @@ + + + + +Resource Timing initiator type: frameset + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/iframe.html b/testing/web-platform/tests/resource-timing/initiator-type/iframe.html new file mode 100644 index 0000000000..0becd86894 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/iframe.html @@ -0,0 +1,19 @@ + + + + +Resource Timing initiator type: iframe + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/img-srcset.html b/testing/web-platform/tests/resource-timing/initiator-type/img-srcset.html new file mode 100644 index 0000000000..b8c81fbb25 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/img-srcset.html @@ -0,0 +1,21 @@ + + + + +Resource Timing initiator type: img with srcset attribute + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/img.html b/testing/web-platform/tests/resource-timing/initiator-type/img.html new file mode 100644 index 0000000000..8e2d305048 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/img.html @@ -0,0 +1,19 @@ + + + + +Resource Timing initiator type: img + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/input.html b/testing/web-platform/tests/resource-timing/initiator-type/input.html new file mode 100644 index 0000000000..a46d416671 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/input.html @@ -0,0 +1,19 @@ + + + + +Resource Timing initiator type: input + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/link.html b/testing/web-platform/tests/resource-timing/initiator-type/link.html new file mode 100644 index 0000000000..43367ac3d5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/link.html @@ -0,0 +1,35 @@ + + + + + + Resource Timing initiator type: link + + + + + + + + + + + + + + + +
    This content forces a font to get fetched
+ + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/misc.html b/testing/web-platform/tests/resource-timing/initiator-type/misc.html new file mode 100644 index 0000000000..02d01a1633 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/misc.html @@ -0,0 +1,31 @@ + + + + +Resource Timing initiator type: miscellaneous elements + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/picture.html b/testing/web-platform/tests/resource-timing/initiator-type/picture.html new file mode 100644 index 0000000000..e384b9e97d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/picture.html @@ -0,0 +1,39 @@ + + + + +Resource Timing initiator type: picture + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/resources/initiator-type-test.js b/testing/web-platform/tests/resource-timing/initiator-type/resources/initiator-type-test.js new file mode 100644 index 0000000000..2b1f844376 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/resources/initiator-type-test.js @@ -0,0 +1,15 @@ + +if (observe_entry === undefined) { + throw new Error("You must include resource-timing/resources/observe-entry.js " + + "before including this script."); +} + +// Asserts that, for the given name, there is/will-be a +// PerformanceResourceTiming entry that has the given 'initiatorType'. The test +// is labeled according to the given descriptor. +const initiator_type_test = (entry_name, expected_initiator, descriptor) => { + promise_test(async () => { + const entry = await observe_entry(entry_name); + assert_equals(entry.initiatorType, expected_initiator); + }, `The initiator type for ${descriptor} must be '${expected_initiator}'`); +}; diff --git a/testing/web-platform/tests/resource-timing/initiator-type/script.html b/testing/web-platform/tests/resource-timing/initiator-type/script.html new file mode 100644 index 0000000000..dbd6a131de --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/script.html @@ -0,0 +1,26 @@ + + + + +Resource Timing initiator type: script + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/style.html b/testing/web-platform/tests/resource-timing/initiator-type/style.html new file mode 100644 index 0000000000..051496b766 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/style.html @@ -0,0 +1,45 @@ + + + + +Resource Timing initiator type: style + + + + + + + + + + + +
This content forces the '@font-face' resource to be fetched.
+ + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/svg.html b/testing/web-platform/tests/resource-timing/initiator-type/svg.html new file mode 100644 index 0000000000..d92f5935d8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/svg.html @@ -0,0 +1,23 @@ + + + + +Resource Timing initiator type: svg + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/video.html b/testing/web-platform/tests/resource-timing/initiator-type/video.html new file mode 100644 index 0000000000..16f3b3dea5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/video.html @@ -0,0 +1,32 @@ + + + + +Resource Timing initiator type: video + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/initiator-type/workers.html b/testing/web-platform/tests/resource-timing/initiator-type/workers.html new file mode 100644 index 0000000000..3a23ad71a3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/initiator-type/workers.html @@ -0,0 +1,23 @@ + + + + +Resource Timing initiatorType: worker resources + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/input-sequence-of-events.html b/testing/web-platform/tests/resource-timing/input-sequence-of-events.html new file mode 100644 index 0000000000..446e24a0bc --- /dev/null +++ b/testing/web-platform/tests/resource-timing/input-sequence-of-events.html @@ -0,0 +1,21 @@ + + +Test the sequence of events when reporting input timing. + + + + diff --git a/testing/web-platform/tests/resource-timing/link-sequence-of-events.html b/testing/web-platform/tests/resource-timing/link-sequence-of-events.html new file mode 100644 index 0000000000..be9db32cd9 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/link-sequence-of-events.html @@ -0,0 +1,30 @@ + + +Test the sequence of events when reporting link timing. + + + + + diff --git a/testing/web-platform/tests/resource-timing/load-from-mem-cache-transfer-size.html b/testing/web-platform/tests/resource-timing/load-from-mem-cache-transfer-size.html new file mode 100644 index 0000000000..3d2d32d6e6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/load-from-mem-cache-transfer-size.html @@ -0,0 +1,65 @@ + + + + + + This tests transfer size of resource timing when loaded from memory cache. + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/nested-context-navigations-embed.html b/testing/web-platform/tests/resource-timing/nested-context-navigations-embed.html new file mode 100644 index 0000000000..f804adbb8a --- /dev/null +++ b/testing/web-platform/tests/resource-timing/nested-context-navigations-embed.html @@ -0,0 +1,36 @@ + + + + + +Resource Timing embed navigate - back button navigation + + + + + + diff --git a/testing/web-platform/tests/resource-timing/nested-context-navigations-iframe.html b/testing/web-platform/tests/resource-timing/nested-context-navigations-iframe.html new file mode 100644 index 0000000000..32ab21633c --- /dev/null +++ b/testing/web-platform/tests/resource-timing/nested-context-navigations-iframe.html @@ -0,0 +1,32 @@ + + + + + +Resource Timing embed navigate - back button navigation + + + + + + diff --git a/testing/web-platform/tests/resource-timing/nested-context-navigations-object.html b/testing/web-platform/tests/resource-timing/nested-context-navigations-object.html new file mode 100644 index 0000000000..1508d8829f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/nested-context-navigations-object.html @@ -0,0 +1,37 @@ + + + + + +Resource Timing embed navigate - back button navigation + + + + + + diff --git a/testing/web-platform/tests/resource-timing/nextHopProtocol-is-tao-protected.https.html b/testing/web-platform/tests/resource-timing/nextHopProtocol-is-tao-protected.https.html new file mode 100644 index 0000000000..b16ff7af75 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/nextHopProtocol-is-tao-protected.https.html @@ -0,0 +1,49 @@ + + + + +Resource Timing - Check that nextHopProtocol is TAO protected + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html b/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html new file mode 100644 index 0000000000..2cfcfc7d68 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched-memory-cache.sub.html @@ -0,0 +1,38 @@ + + +Make sure that resources fetched by cross origin CSS are not in the timeline. + + + + + + + +
    Some content
+ diff --git a/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched.sub.html b/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched.sub.html new file mode 100644 index 0000000000..63f9e06e19 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/no-entries-for-cross-origin-css-fetched.sub.html @@ -0,0 +1,39 @@ + + +Make sure that resources fetched by cross origin CSS are not in the timeline. + + + + + + +
    Some content
+ + diff --git a/testing/web-platform/tests/resource-timing/object-not-found-adds-entry.html b/testing/web-platform/tests/resource-timing/object-not-found-adds-entry.html new file mode 100644 index 0000000000..d11823dd9d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/object-not-found-adds-entry.html @@ -0,0 +1,37 @@ + + + + +This test validates that object resource emit resource timing entries. + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html b/testing/web-platform/tests/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html new file mode 100644 index 0000000000..d0dad9381b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/object-not-found-after-TAO-cross-origin-redirect.html @@ -0,0 +1,47 @@ + + + + +This test validates resource timing information for a timing allowed cross-origin redirect chain. + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/object-not-found-after-cross-origin-redirect.html b/testing/web-platform/tests/resource-timing/object-not-found-after-cross-origin-redirect.html new file mode 100644 index 0000000000..4d5d121fe3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/object-not-found-after-cross-origin-redirect.html @@ -0,0 +1,36 @@ + + + + +This test validates the values in resource timing for cross-origin +redirects. + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/opaque-origin.html b/testing/web-platform/tests/resource-timing/opaque-origin.html new file mode 100644 index 0000000000..598ee50a59 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/opaque-origin.html @@ -0,0 +1,46 @@ + + + + +Resource Timing TAO - "null" and opaque origin + + + + + + + +

Description

+

This test validates that, for a cross origin resource, the timing allow +check algorithm will correctly distinguish between 'null' and 'Null' values in +the Timing-Allow-Origin header. An opaque origin's serialization is the string +"null" and the timing allow origin check needs to do a case-sensitive comparison +to the Timing-Allow-Origin header. +

+ + + + diff --git a/testing/web-platform/tests/resource-timing/ping-rt-entries.html b/testing/web-platform/tests/resource-timing/ping-rt-entries.html new file mode 100644 index 0000000000..34dad10b9f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/ping-rt-entries.html @@ -0,0 +1,29 @@ + + + + +Resource Timing Entry For hyperlink audit (ping) + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/redirects.html b/testing/web-platform/tests/resource-timing/redirects.html new file mode 100644 index 0000000000..ba69907a5f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/redirects.html @@ -0,0 +1,61 @@ + + + + +Resource Timing: resources fetched through same-origin redirects + + + + + + + + + + +

Description

+

This test validates that, when a fetching resources that encounter +same-origin redirects, attributes of the PerformanceResourceTiming entry +conform to the specification.

+ + diff --git a/testing/web-platform/tests/resource-timing/render-blocking-status-link.html b/testing/web-platform/tests/resource-timing/render-blocking-status-link.html new file mode 100644 index 0000000000..8c6544db48 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/render-blocking-status-link.html @@ -0,0 +1,222 @@ + + + +This test validates the render blocking status of resources. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/render-blocking-status-script.html b/testing/web-platform/tests/resource-timing/render-blocking-status-script.html new file mode 100644 index 0000000000..bcd55b8994 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/render-blocking-status-script.html @@ -0,0 +1,196 @@ + + + +This test validates the render blocking status of resources. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resource-ignore-data-url.html b/testing/web-platform/tests/resource-timing/resource-ignore-data-url.html new file mode 100644 index 0000000000..a7056a8080 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource-ignore-data-url.html @@ -0,0 +1,39 @@ + + + + +Resource Timing ignores resources with data: URIs + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resource-reload-TAO.html b/testing/web-platform/tests/resource-timing/resource-reload-TAO.html new file mode 100644 index 0000000000..83a1e921bb --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource-reload-TAO.html @@ -0,0 +1,18 @@ + + + + +Resource Timing - TAO on reload + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resource-timing-level1.js b/testing/web-platform/tests/resource-timing/resource-timing-level1.js new file mode 100644 index 0000000000..95b5cdfb1e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource-timing-level1.js @@ -0,0 +1,517 @@ +"use strict"; + +window.onload = + function () { + setup({ explicit_timeout: true }); + + /** Number of milliseconds to delay when the server injects pauses into the response. + + This should be large enough that we can distinguish it from noise with high confidence, + but small enough that tests complete quickly. */ + var serverStepDelay = 250; + + var mimeHtml = "text/html"; + var mimeText = "text/plain"; + var mimePng = "image/png"; + var mimeScript = "application/javascript"; + var mimeCss = "text/css"; + + /** Hex encoding of a a 150x50px green PNG. */ + var greenPng = "0x89504E470D0A1A0A0000000D494844520000006400000032010300000090FBECFD00000003504C544500FF00345EC0A80000000F49444154281563601805A36068020002BC00011BDDE3900000000049454E44AE426082"; + + /** Array containing test cases to run. Initially, it contains the one-off 'about:blank" test, + but additional cases are pushed below by expanding templates. */ + var testCases = [ + { + description: "No timeline entry for about:blank", + test: + function (test) { + // Insert an empty IFrame. + var frame = document.createElement("iframe"); + + // Wait for the IFrame to load and ensure there is no resource entry for it on the timeline. + // + // We use the 'createOnloadCallbackFn()' helper which is normally invoked by 'initiateFetch()' + // to avoid setting the IFrame's src. It registers a test step for us, finds our entry on the + // resource timeline, and wraps our callback function to automatically vet invariants. + frame.onload = createOnloadCallbackFn(test, frame, "about:blank", + function (initiator, entry) { + assert_equals(entry, undefined, "Inserting an IFrame with a src of 'about:blank' must not add an entry to the timeline."); + assertInvariants( + test, + function () { + test.done(); + }); + }); + + document.body.appendChild(frame); + + // Paranoid check that the new IFrame has loaded about:blank. + assert_equals( + frame.contentWindow.location.href, + "about:blank", + "'Src' of new + + diff --git a/testing/web-platform/tests/resource-timing/resource_connection_reuse_mixed_content_redirect.html b/testing/web-platform/tests/resource-timing/resource_connection_reuse_mixed_content_redirect.html new file mode 100644 index 0000000000..a46d14c9f1 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_connection_reuse_mixed_content_redirect.html @@ -0,0 +1,55 @@ + + + + +Resource Timing connection reuse + + + + + + + + +

Description

+

This test validates that connectStart and connectEnd are the same when a connection is reused (e.g. when a persistent connection is used).

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_dedicated_worker.html b/testing/web-platform/tests/resource-timing/resource_dedicated_worker.html new file mode 100644 index 0000000000..6d27245ab9 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_dedicated_worker.html @@ -0,0 +1,28 @@ + + + + +Resource Timing in dedicated workers + + + + + + + + + + +

Description

+

This test validates that resources requested by dedicated workers don't appear in the main document.

+ + diff --git a/testing/web-platform/tests/resource-timing/resource_nested_dedicated_worker.worker.js b/testing/web-platform/tests/resource-timing/resource_nested_dedicated_worker.worker.js new file mode 100644 index 0000000000..2c9f5f9542 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_nested_dedicated_worker.worker.js @@ -0,0 +1,17 @@ +importScripts("/resources/testharness.js"); + +async_test(function() { + const worker = new Worker('resources/worker_with_images.js'); + worker.onmessage = this.step_func_done((event) => { + const childNumEntries = event.data; + assert_equals(2, childNumEntries, + "There should be two resource timing entries: 2 image XHRs"); + + const parentNumEntries = performance.getEntries().length; + assert_equals(2, parentNumEntries, + "There should be two resource timing entries: " + + "one is for importScripts() and the another is for a nested worker"); + worker.terminate(); + }); +}, "Resource timing for nested dedicated workers"); +done(); diff --git a/testing/web-platform/tests/resource-timing/resource_reparenting.html b/testing/web-platform/tests/resource-timing/resource_reparenting.html new file mode 100644 index 0000000000..7d4947fa77 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_reparenting.html @@ -0,0 +1,53 @@ + + + + +Resource Timing reparenting elements + + + + + + + + + +

Description

+

This test validates that reparenting an element doesn't change the initiator document.

+
+ + + diff --git a/testing/web-platform/tests/resource-timing/resource_subframe_self_navigation.html b/testing/web-platform/tests/resource-timing/resource_subframe_self_navigation.html new file mode 100644 index 0000000000..5843f88307 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_subframe_self_navigation.html @@ -0,0 +1,53 @@ + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resource_timing.worker.js b/testing/web-platform/tests/resource-timing/resource_timing.worker.js new file mode 100644 index 0000000000..dafd2e9af6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_timing.worker.js @@ -0,0 +1,64 @@ +importScripts("/resources/testharness.js"); + +function check(initiatorType, protocol) { + let entries = performance.getEntries(); + assert_equals(entries.length, 1); + + assert_true(entries[0] instanceof PerformanceEntry); + assert_equals(entries[0].entryType, "resource"); + assert_true(entries[0].startTime > 0); + assert_true(entries[0].duration > 0); + + assert_true(entries[0] instanceof PerformanceResourceTiming); + assert_equals(entries[0].initiatorType, initiatorType); + assert_equals(entries[0].nextHopProtocol, protocol); +} + +async_test(t => { + performance.clearResourceTimings(); + + // Fetch + fetch("resources/empty.js") + .then(r => r.blob()) + .then(blob => { + check("fetch", "http/1.1"); + }) + + // XMLHttpRequest + .then(() => { + return new Promise(resolve => { + performance.clearResourceTimings(); + let xhr = new XMLHttpRequest(); + xhr.onload = () => { + check("xmlhttprequest", "http/1.1"); + resolve(); + }; + xhr.open("GET", "resources/empty.js"); + xhr.send(); + }); + }) + + // Sync XMLHttpREquest + .then(() => { + performance.clearResourceTimings(); + let xhr = new XMLHttpRequest(); + xhr.open("GET", "resources/empty.js", false); + xhr.send(); + + check("xmlhttprequest", "http/1.1"); + }) + + // ImportScripts + .then(() => { + performance.clearResourceTimings(); + importScripts(["resources/empty.js"]); + check("other", "http/1.1"); + }) + + // All done. + .then(() => { + t.done(); + }); +}, "Performance Resource Entries in workers"); + +done(); diff --git a/testing/web-platform/tests/resource-timing/resource_timing_content_length.html b/testing/web-platform/tests/resource-timing/resource_timing_content_length.html new file mode 100644 index 0000000000..32bd8a97e0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resource_timing_content_length.html @@ -0,0 +1,35 @@ + + + + +This test validates the value of encodedBodySize in certain situations. + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/200.https.asis b/testing/web-platform/tests/resource-timing/resources/200.https.asis new file mode 100644 index 0000000000..5b7c25f4ca --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/200.https.asis @@ -0,0 +1,5 @@ +HTTP/1.0 200 OK +Content-Length: 0 +Timing-Allow-Origin: * + + diff --git a/testing/web-platform/tests/resource-timing/resources/200_empty.asis b/testing/web-platform/tests/resource-timing/resources/200_empty.asis new file mode 100644 index 0000000000..b5d10bda32 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/200_empty.asis @@ -0,0 +1,3 @@ +HTTP/1.0 200 OK +Content-Length: 0 + diff --git a/testing/web-platform/tests/resource-timing/resources/204_empty.asis b/testing/web-platform/tests/resource-timing/resources/204_empty.asis new file mode 100644 index 0000000000..3d9151326b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/204_empty.asis @@ -0,0 +1,3 @@ +HTTP/1.0 204 OK +Content-Length: 0 + diff --git a/testing/web-platform/tests/resource-timing/resources/205_empty.asis b/testing/web-platform/tests/resource-timing/resources/205_empty.asis new file mode 100644 index 0000000000..2c06998c1e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/205_empty.asis @@ -0,0 +1,3 @@ +HTTP/1.0 205 OK +Content-Length: 0 + diff --git a/testing/web-platform/tests/resource-timing/resources/TAOResponse.py b/testing/web-platform/tests/resource-timing/resources/TAOResponse.py new file mode 100644 index 0000000000..60392b8e10 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/TAOResponse.py @@ -0,0 +1,64 @@ +import os + +def main(request, response): + if b'origin' in request.headers: + origin = request.headers[b'origin'] + response.headers.set(b'Access-Control-Allow-Origin', origin) + + tao = request.GET.first(b'tao') + img = request.GET.first(b'img') if b'img' in request.GET else None + + if tao == b'zero': + # zero TAO value, fail + pass + elif tao == b'wildcard': + # wildcard, pass + response.headers.set(b'Timing-Allow-Origin', b'*') + elif tao == b'null': + # null, fail unless it's an opaque origin + response.headers.set(b'Timing-Allow-Origin', b'null') + elif tao == b'Null': + # case-insensitive null, fail + response.headers.set(b'Timing-Allow-Origin', b'Null') + elif tao == b'origin': + # case-sensitive match for origin, pass + response.headers.set(b'Timing-Allow-Origin', origin) + elif tao.startswith(b'origin_port'): + # case-sensitive match for origin and port, pass + origin_parts = origin.split(b':') + host = origin_parts[0] + b':' + origin_parts[1] + port = tao.split(b'origin_port_')[1] + response.headers.set(b'Timing-Allow-Origin', host + b':' + port) + elif tao == b'space': + # space separated list of origin and wildcard, fail + response.headers.set(b'Timing-Allow-Origin', (origin + b' *')) + elif tao == b'multi': + # more than one TAO values, separated by comma, pass + response.headers.set(b'Timing-Allow-Origin', origin) + response.headers.append(b'Timing-Allow-Origin', b'*') + elif tao == b'multi_wildcard': + # multiple wildcards, separated by comma, pass + response.headers.set(b'Timing-Allow-Origin', b'*') + response.headers.append(b'Timing-Allow-Origin', b'*') + elif tao == b'match_origin': + # contains a match of origin, separated by comma, pass + response.headers.set(b'Timing-Allow-Origin', origin) + response.headers.append(b'Timing-Allow-Origin', b"fake") + elif tao == b'match_wildcard': + # contains a wildcard, separated by comma, pass + response.headers.set(b'Timing-Allow-Origin', b"fake") + response.headers.append(b'Timing-Allow-Origin', b'*') + elif tao == b'uppercase': + # non-case-sensitive match for origin, fail + response.headers.set(b'Timing-Allow-Origin', origin.upper()) + else: + pass + response.status = 200 + if img: + response.headers.set(b"Content-Type", b"image/png") + with open(request.doc_root + "/resource-timing/resources/blue.png", "rb") as f: + response.content = f.read() + f.close() + else: + response.headers.set(b"Content-Type", b"text/plain") + response.content = "TEST" diff --git a/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html b/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html new file mode 100644 index 0000000000..b8a1947b77 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html @@ -0,0 +1,10 @@ + + + + + Green Test Page + + +

Placeholder

+ + diff --git a/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html.headers b/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html.headers new file mode 100644 index 0000000000..7296361df3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/blank-with-tao.html.headers @@ -0,0 +1 @@ +Timing-Allow-Origin: * diff --git a/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png b/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png new file mode 100644 index 0000000000..820f8cace2 Binary files /dev/null and b/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png differ diff --git a/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png.headers b/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png.headers new file mode 100644 index 0000000000..7296361df3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/blue-with-tao.png.headers @@ -0,0 +1 @@ +Timing-Allow-Origin: * diff --git a/testing/web-platform/tests/resource-timing/resources/blue.png b/testing/web-platform/tests/resource-timing/resources/blue.png new file mode 100644 index 0000000000..820f8cace2 Binary files /dev/null and b/testing/web-platform/tests/resource-timing/resources/blue.png differ diff --git a/testing/web-platform/tests/resource-timing/resources/buffer-full-utilities.js b/testing/web-platform/tests/resource-timing/resources/buffer-full-utilities.js new file mode 100644 index 0000000000..6cb1753b2e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/buffer-full-utilities.js @@ -0,0 +1,75 @@ +// This script relies on resources/resource-loaders.js. Include it before in order for the below +// methods to work properly. + +// The resources used to trigger new entries. +const scriptResources = [ + 'resources/empty.js', + 'resources/empty_script.js', + 'resources/empty.js?id' +]; + +const waitForNextTask = () => { + return new Promise(resolve => { + step_timeout(resolve, 0); + }); +}; + +const clearBufferAndSetSize = size => { + performance.clearResourceTimings(); + performance.setResourceTimingBufferSize(size); +} + +const forceBufferFullEvent = async () => { + clearBufferAndSetSize(1); + return new Promise(async resolve => { + performance.addEventListener('resourcetimingbufferfull', resolve); + // Load 2 resources to ensure onresourcetimingbufferfull is fired. + // Load them in order in order to get the entries in that order! + await load.script(scriptResources[0]); + await load.script(scriptResources[1]); + }); +}; + +const fillUpTheBufferWithSingleResource = async (src = scriptResources[0]) => { + clearBufferAndSetSize(1); + await load.script(src); +}; + +const fillUpTheBufferWithTwoResources = async () => { + clearBufferAndSetSize(2); + // Load them in order in order to get the entries in that order! + await load.script(scriptResources[0]); + await load.script(scriptResources[1]); +}; + +const addAssertUnreachedBufferFull = t => { + performance.addEventListener('resourcetimingbufferfull', t.step_func(() => { + assert_unreached("resourcetimingbufferfull should not fire") + })); +}; + +const checkEntries = numEntries => { + const entries = performance.getEntriesByType('resource'); + assert_equals(entries.length, numEntries, + 'Number of entries does not match the expected value.'); + assert_true(entries[0].name.includes(scriptResources[0]), + scriptResources[0] + " is in the entries buffer"); + if (entries.length > 1) { + assert_true(entries[1].name.includes(scriptResources[1]), + scriptResources[1] + " is in the entries buffer"); + } + if (entries.length > 2) { + assert_true(entries[2].name.includes(scriptResources[2]), + scriptResources[2] + " is in the entries buffer"); + } +} + +const bufferFullFirePromise = new Promise(resolve => { + performance.addEventListener('resourcetimingbufferfull', async () => { + // Wait for the next task just to ensure that all bufferfull events have fired, and to ensure + // that the secondary buffer is copied (as this is an event, there may be microtask checkpoints + // right after running an event handler). + await waitForNextTask(); + resolve(); + }); +}); diff --git a/testing/web-platform/tests/resource-timing/resources/cacheable-and-validated.py b/testing/web-platform/tests/resource-timing/resources/cacheable-and-validated.py new file mode 100644 index 0000000000..97de866277 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/cacheable-and-validated.py @@ -0,0 +1,30 @@ +def main(request, response): + # Headers need to be set before `response.writer` writes out the response. + tao = request.GET.get(b'timing_allow_origin') + if tao: + response.headers.set(b"Timing-Allow-Origin", tao) + + if b'origin' in request.headers: + origin = request.headers[b'origin'] + response.headers.set(b'Access-Control-Allow-Origin', origin) + + content = request.GET.first(b'content') + response.headers.set(b'Cache-Control', b'max-age=60') + response.headers.set(b'ETag', b'assdfsdfe') + + # Handle CORS-preflights of non-simple requests. + if request.method == 'OPTIONS': + response.status = 204 + requested_method = request.headers.get(b"Access-Control-Request-Method") + if requested_method: + response.headers.set(b"Access-Control-Allow-Methods", requested_method) + requested_headers = request.headers.get(b"Access-Control-Request-Headers") + if requested_headers: + response.headers.set(b"Access-Control-Allow-Headers", requested_headers) + else: + if 'Cache-Control' in request.headers: + response.status = (304, b'NotModified') + else: + response.status = (200, b'OK') + response.write_status_headers() + response.writer.write(content) diff --git a/testing/web-platform/tests/resource-timing/resources/close.html b/testing/web-platform/tests/resource-timing/resources/close.html new file mode 100644 index 0000000000..02c275f37b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/close.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/connection-reuse-test.js b/testing/web-platform/tests/resource-timing/resources/connection-reuse-test.js new file mode 100644 index 0000000000..453fbd3405 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/connection-reuse-test.js @@ -0,0 +1,63 @@ +// This script is loaded in HTTP and HTTPS contexts to validate +// PerformanceResourceTiming entries' attributes when reusing connections. +// +// Note: to ensure that we reuse the connection to fetch multiple resources, we +// use the same XMLHttpRequest object throughout an individual test. Although +// it doesn't seem to be specified, each browser tested by WPT will reuse the +// underlying TCP connection with this approach. Pre-establishing the XHR's +// connection helps us to test connection reuse also in browsers that may key +// their connections on the related request's credentials mode. + +const connection_reuse_test = (path, follow_on_assertions, test_label) => { + const {on_200, on_304} = follow_on_assertions; + + // Make the first request before calling 'attribute_test' so that only the + // second request's PerformanceResourceTiming entry will be interrogated. We + // don't check the first request's PerformanceResourceTiming entry because + // that's not what this test is trying to validate. + const client = new XMLHttpRequest(); + const identifier = Math.random(); + path = `${path}?tag=${identifier}`; + client.open("GET", path, false); + client.send(); + + attribute_test( + async () => { + client.open("GET", path + "&same_resource=false", false); + client.send(); + + // We expect to get a 200 Ok response because we've requested a different + // resource than previous requests. + if (client.status != 200) { + throw new Error(`Got something other than a 200 response. ` + + `client.status: ${client.status}`); + } + }, path, entry => { + invariants.assert_connection_reused(entry); + on_200(entry); + }, + `PerformanceResrouceTiming entries need to conform to the spec when a ` + + `distinct resource is fetched over a persistent connection ` + + `(${test_label})`); + + attribute_test( + async () => { + client.open("GET", path, false); + client.setRequestHeader("If-None-Match", identifier); + client.send(); + + // We expect to get a 304 Not Modified response because we've used a + // matching 'identifier' for the If-None-Match header. + if (client.status != 304) { + throw new Error(`Got something other than a 304 response. ` + + `client.status: ${client.status}, response: ` + + `'${client.responseText}'`); + } + }, path, entry => { + invariants.assert_connection_reused(entry); + on_304(entry); + }, + `PerformanceResrouceTiming entries need to conform to the spec when the ` + + `resource is cache-revalidated over a persistent connection ` + + `(${test_label})`); +} diff --git a/testing/web-platform/tests/resource-timing/resources/content-type.py b/testing/web-platform/tests/resource-timing/resources/content-type.py new file mode 100644 index 0000000000..23a4f0dbc6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/content-type.py @@ -0,0 +1,5 @@ +def main(request, response): + if b'content_type' in request.GET: + response.headers.set(b'content-type', request.GET.first(b'content_type')) + if b'allow_origin' in request.GET: + response.headers.set(b'access-control-allow-origin', request.GET.first(b'allow_origin')) \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/cors-ahem.py b/testing/web-platform/tests/resource-timing/resources/cors-ahem.py new file mode 100644 index 0000000000..dee5b62f00 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/cors-ahem.py @@ -0,0 +1,19 @@ +import os.path + +from wptserve.utils import isomorphic_decode + +def main(request, response): + etag = b"123abc" + if etag == request.headers.get(b"If-None-Match", None): + response.headers.set(b"X-HTTP-STATUS", 304) + response.status = (304, b"Not Modified") + return u"" + + response.headers.set(b"Cache-Control", b"public, max-age=86400") + response.headers.set(b"Content-Type", b"font/truetype") + response.headers.set(b"Access-Control-Allow-Origin", b"*") + response.headers.set(b"Timing-Allow-Origin", b"*") + response.headers.set(b"ETag", etag) + font = u"../../fonts/Ahem.ttf" + path = os.path.join(os.path.dirname(isomorphic_decode(__file__)), font) + response.content = open(path, u"rb").read() diff --git a/testing/web-platform/tests/resource-timing/resources/csp-default-none.html b/testing/web-platform/tests/resource-timing/resources/csp-default-none.html new file mode 100644 index 0000000000..1f59d8c225 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/csp-default-none.html @@ -0,0 +1,3 @@ + + +empty page diff --git a/testing/web-platform/tests/resource-timing/resources/csp-default-none.html.headers b/testing/web-platform/tests/resource-timing/resources/csp-default-none.html.headers new file mode 100644 index 0000000000..d66f886dd2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/csp-default-none.html.headers @@ -0,0 +1,2 @@ +Content-Security-Policy: default-src 'none' + diff --git a/testing/web-platform/tests/resource-timing/resources/delay-css.py b/testing/web-platform/tests/resource-timing/resources/delay-css.py new file mode 100644 index 0000000000..9a905960ee --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/delay-css.py @@ -0,0 +1,6 @@ +import time + +def main(request, response): + time.sleep(float(request.GET.first(b"delay", 1000)) / 1000) + response.headers.set('Content-Type', 'text/css') + return "/* */" diff --git a/testing/web-platform/tests/resource-timing/resources/document-domain-no-impact.html b/testing/web-platform/tests/resource-timing/resources/document-domain-no-impact.html new file mode 100644 index 0000000000..64cdd8a870 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/document-domain-no-impact.html @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/document-navigated.html b/testing/web-platform/tests/resource-timing/resources/document-navigated.html new file mode 100644 index 0000000000..bedae77082 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/document-navigated.html @@ -0,0 +1,12 @@ + + + + + + + Navigated document! + + + diff --git a/testing/web-platform/tests/resource-timing/resources/document-refreshed.html b/testing/web-platform/tests/resource-timing/resources/document-refreshed.html new file mode 100644 index 0000000000..568f7f27c7 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/document-refreshed.html @@ -0,0 +1,12 @@ + + + + + + + Refreshed document! + + + diff --git a/testing/web-platform/tests/resource-timing/resources/document-that-navigates.html b/testing/web-platform/tests/resource-timing/resources/document-that-navigates.html new file mode 100644 index 0000000000..a59e9f3ab2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/document-that-navigates.html @@ -0,0 +1,11 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/document-that-refreshes.html b/testing/web-platform/tests/resource-timing/resources/document-that-refreshes.html new file mode 100644 index 0000000000..659513a642 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/document-that-refreshes.html @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/download.asis b/testing/web-platform/tests/resource-timing/resources/download.asis new file mode 100644 index 0000000000..167386d7a5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/download.asis @@ -0,0 +1,6 @@ +HTTP/1.0 200 OK +Content-Type: application/octet-stream + +12312313 + + diff --git a/testing/web-platform/tests/resource-timing/resources/embed-navigate-back.html b/testing/web-platform/tests/resource-timing/resources/embed-navigate-back.html new file mode 100644 index 0000000000..c9c7340f53 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/embed-navigate-back.html @@ -0,0 +1,18 @@ + + + + +Resource Timing embed navigate - back button navigation + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/embed-navigate.html b/testing/web-platform/tests/resource-timing/resources/embed-navigate.html new file mode 100644 index 0000000000..24c9d3c462 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/embed-navigate.html @@ -0,0 +1,18 @@ + + + + +Resource Timing embed navigate + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/embed-refresh.html b/testing/web-platform/tests/resource-timing/resources/embed-refresh.html new file mode 100644 index 0000000000..bd4b5a14de --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/embed-refresh.html @@ -0,0 +1,18 @@ + + + + +Resource Timing embed refresh + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/empty.js b/testing/web-platform/tests/resource-timing/resources/empty.js new file mode 100644 index 0000000000..3b44754e30 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/empty.js @@ -0,0 +1 @@ +/* Nothing here */ diff --git a/testing/web-platform/tests/resource-timing/resources/empty.py b/testing/web-platform/tests/resource-timing/resources/empty.py new file mode 100644 index 0000000000..cae83c146e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/empty.py @@ -0,0 +1,3 @@ +def main(request, response): + response.headers.set(b"Content-Type", b"text/plain") + return u"" diff --git a/testing/web-platform/tests/resource-timing/resources/empty_script.js b/testing/web-platform/tests/resource-timing/resources/empty_script.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/web-platform/tests/resource-timing/resources/empty_style.css b/testing/web-platform/tests/resource-timing/resources/empty_style.css new file mode 100644 index 0000000000..eb90b432e8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/empty_style.css @@ -0,0 +1 @@ +/*Nothing here*/ diff --git a/testing/web-platform/tests/resource-timing/resources/entry-invariants.js b/testing/web-platform/tests/resource-timing/resources/entry-invariants.js new file mode 100644 index 0000000000..e35ea289ce --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/entry-invariants.js @@ -0,0 +1,511 @@ +// Asserts that the given attributes are present in 'entry' and hold equal +// values. +const assert_all_equal_ = (entry, attributes) => { + let first = attributes[0]; + attributes.slice(1).forEach(other => { + assert_equals(entry[first], entry[other], + `${first} should be equal to ${other}`); + }); +} + +// Asserts that the given attributes are present in 'entry' and hold values +// that are sorted in the same order as given in 'attributes'. +const assert_ordered_ = (entry, attributes) => { + let before = attributes[0]; + attributes.slice(1).forEach(after => { + assert_greater_than_equal(entry[after], entry[before], + `${after} should be greater than ${before}`); + before = after; + }); +} + +// Asserts that the given attributes are present in 'entry' and hold a value of +// 0. +const assert_zeroed_ = (entry, attributes) => { + attributes.forEach(attribute => { + assert_equals(entry[attribute], 0, `${attribute} should be 0`); + }); +} + +// Asserts that the given attributes are present in 'entry' and hold a value of +// 0 or more. +const assert_not_negative_ = (entry, attributes) => { + attributes.forEach(attribute => { + assert_greater_than_equal(entry[attribute], 0, + `${attribute} should be greater than or equal to 0`); + }); +} + +// Asserts that the given attributes are present in 'entry' and hold a value +// greater than 0. +const assert_positive_ = (entry, attributes) => { + attributes.forEach(attribute => { + assert_greater_than(entry[attribute], 0, + `${attribute} should be greater than 0`); + }); +} + +const invariants = { + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates for any resource fetched over HTTP without + // redirects but passing the Timing-Allow-Origin checks. + assert_tao_pass_no_redirect_http: entry => { + assert_ordered_(entry, [ + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + "secureConnectionStart", + "redirectStart", + "redirectEnd", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + "encodedBodySize", + "decodedBodySize", + ]); + }, + + // Like assert_tao_pass_no_redirect_http but for empty response bodies. + assert_tao_pass_no_redirect_http_empty: entry => { + assert_ordered_(entry, [ + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + "secureConnectionStart", + "redirectStart", + "redirectEnd", + "encodedBodySize", + "decodedBodySize", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + ]); + }, + + // Like assert_tao_pass_no_redirect_http but for resources fetched over HTTPS + assert_tao_pass_no_redirect_https: entry => { + assert_ordered_(entry, [ + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "secureConnectionStart", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + "redirectStart", + "redirectEnd", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + "encodedBodySize", + "decodedBodySize", + ]); + }, + + // Like assert_tao_pass_no_redirect_https but for resources that did encounter + // at least one HTTP redirect. + assert_tao_pass_with_redirect_https: entry => { + assert_ordered_(entry, [ + "fetchStart", + "redirectStart", + "redirectEnd", + "domainLookupStart", + "domainLookupEnd", + "secureConnectionStart", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + "encodedBodySize", + "decodedBodySize", + ]); + }, + + // Like assert_tao_pass_no_redirect_http but, since the resource's bytes + // won't be retransmitted, the encoded and decoded sizes must be zero. + assert_tao_pass_304_not_modified_http: entry => { + assert_ordered_(entry, [ + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + "secureConnectionStart", + "redirectStart", + "redirectEnd", + "encodedBodySize", + "decodedBodySize", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + ]); + }, + + // Like assert_tao_pass_304_not_modified_http but for resources fetched over + // HTTPS. + assert_tao_pass_304_not_modified_https: entry => { + assert_ordered_(entry, [ + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "secureConnectionStart", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + + assert_zeroed_(entry, [ + "workerStart", + "redirectStart", + "redirectEnd", + "encodedBodySize", + "decodedBodySize", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_positive_(entry, [ + "fetchStart", + "transferSize", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates for any resource subsequently fetched over a + // persistent connection. When this happens, we expect that certain + // attributes describing transport layer behaviour will be equal. + assert_connection_reused: entry => { + assert_all_equal_(entry, [ + "fetchStart", + "connectStart", + "connectEnd", + "domainLookupStart", + "domainLookupEnd", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates for any resource fetched over HTTP through an HTTP + // redirect. + assert_same_origin_redirected_resource: entry => { + assert_positive_(entry, [ + "redirectStart", + ]); + + assert_equals(entry.redirectStart, entry.startTime, + "redirectStart should be equal to startTime"); + + assert_ordered_(entry, [ + "redirectStart", + "redirectEnd", + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates for any resource fetched over HTTPS through a + // cross-origin redirect. + // (e.g. GET http://remote.com/foo => 302 Location: https://remote.com/foo) + assert_cross_origin_redirected_resource: entry => { + assert_zeroed_(entry, [ + "redirectStart", + "redirectEnd", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "secureConnectionStart", + "requestStart", + "responseStart", + ]); + + assert_positive_(entry, [ + "fetchStart", + "responseEnd", + ]); + + assert_ordered_(entry, [ + "fetchStart", + "responseEnd", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates when + // 1. An HTTP request is made for a same-origin resource. + // 2. The response to 1 is an HTTP redirect (like a 302). + // 3. The location from 2 is a cross-origin HTTPS URL. + // 4. The response to fetching the URL from 3 does not set a matching TAO header. + assert_http_to_cross_origin_redirected_resource: entry => { + assert_zeroed_(entry, [ + "redirectStart", + "redirectEnd", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "secureConnectionStart", + "requestStart", + "responseStart", + ]); + + assert_positive_(entry, [ + "fetchStart", + "responseEnd", + ]); + + assert_ordered_(entry, [ + "fetchStart", + "responseEnd", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates when + // 1. An HTTPS request is made for a same-origin resource. + // 2. The response to 1 is an HTTP redirect (like a 302). + // 3. The location from 2 is a cross-origin HTTPS URL. + // 4. The response to fetching the URL from 3 sets a matching TAO header. + assert_tao_enabled_cross_origin_redirected_resource: entry => { + assert_positive_(entry, [ + "redirectStart", + ]); + assert_ordered_(entry, [ + "redirectStart", + "redirectEnd", + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "secureConnectionStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + }, + + // Asserts that attributes of the given PerformanceResourceTiming entry match + // what the spec dictates when + // 1. An HTTP request is made for a same-origin resource + // 2. The response to 1 is an HTTP redirect (like a 302). + // 3. The location from 2 is a cross-origin HTTPS URL. + // 4. The response to fetching the URL from 3 sets a matching TAO header. + assert_http_to_tao_enabled_cross_origin_https_redirected_resource: entry => { + assert_zeroed_(entry, [ + // Note that, according to the spec, the secureConnectionStart attribute + // should describe the connection for the first resource request when + // there are redirects. Since the initial request is over HTTP, + // secureConnectionStart must be 0. + "secureConnectionStart", + ]); + assert_positive_(entry, [ + "redirectStart", + ]); + assert_ordered_(entry, [ + "redirectStart", + "redirectEnd", + "fetchStart", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "requestStart", + "responseStart", + "responseEnd", + ]); + }, + + assert_same_origin_redirected_from_cross_origin_resource: entry => { + assert_zeroed_(entry, [ + "workerStart", + "redirectStart", + "redirectEnd", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "secureConnectionStart", + "requestStart", + "responseStart", + "transferSize", + "encodedBodySize", + "decodedBodySize", + ]); + + assert_ordered_(entry, [ + "fetchStart", + "responseEnd", + ]); + + assert_equals(entry.fetchStart, entry.startTime, + "fetchStart must equal startTime"); + }, + + assert_tao_failure_resource: entry => { + assert_equals(entry.entryType, "resource", "entryType must always be 'resource'"); + + assert_positive_(entry, [ + "startTime", + ]); + + assert_not_negative_(entry, [ + "duration", + ]); + + assert_zeroed_(entry, [ + "redirectStart", + "redirectEnd", + "domainLookupStart", + "domainLookupEnd", + "connectStart", + "connectEnd", + "secureConnectionStart", + "requestStart", + "responseStart", + "transferSize", + "encodedBodySize", + "decodedBodySize", + ]); + } + +}; + +const attribute_test_internal = (loader, path, validator, run_test, test_label) => { + promise_test( + async () => { + let loaded_entry = new Promise((resolve, reject) => { + new PerformanceObserver((entry_list, self) => { + try { + const name_matches = entry_list.getEntries().forEach(entry => { + if (entry.name.includes(path)) { + resolve(entry); + } + }); + } catch(e) { + // By surfacing exceptions through the Promise interface, tests can + // fail fast with a useful message instead of timing out. + reject(e); + } + }).observe({"type": "resource"}); + }); + + await loader(path, validator); + const timeout = new Promise(r => step_timeout(() => { + console.log("Timeout was reached before entry fired"); + r(); + }, 2000)); + const entry = await Promise.race([loaded_entry, timeout]); + run_test(entry); + }, test_label); +}; + +// Given a resource-loader, a path (a relative path or absolute URL), and a +// PerformanceResourceTiming test, applies the loader to the resource path +// and tests the resulting PerformanceResourceTiming entry. +const attribute_test = (loader, path, run_test, test_label) => { + attribute_test_internal(loader, path, () => {}, run_test, test_label); +}; + +// Similar to attribute test, but on top of that, validates the added element, +// to ensure the test does what it intends to do. +const attribute_test_with_validator = (loader, path, validator, run_test, test_label) => { + attribute_test_internal(loader, path, validator, run_test, test_label); +}; + +const network_error_entry_test = (originalURL, args, label) => { + const url = new URL(originalURL, location.href); + const search = new URLSearchParams(url.search.substr(1)); + const timeBefore = performance.now(); + loader = () => new Promise(resolve => fetch(url, args).catch(resolve)); + + attribute_test( + loader, url, + () => { + const timeAfter = performance.now(); + const names = performance.getEntriesByType('resource').filter(e => e.initiatorType === 'fetch').map(e => e.name); + const entries = performance.getEntriesByName(url.toString()); + assert_equals(entries.length, 1, 'resource timing entry for network error'); + const entry = entries[0] + assert_equals(entry.startTime, entry.fetchStart, 'startTime and fetchStart should be equal'); + assert_greater_than_equal(entry.startTime, timeBefore, 'startTime and fetchStart should be greater than the time before fetching'); + assert_greater_than_equal(timeAfter, entry.responseEnd, 'endTime should be less than the time right after returning from the fetch'); + invariants.assert_tao_failure_resource(entry); + }, `A ResourceTiming entry should be created for network error of type ${label}`); +} diff --git a/testing/web-platform/tests/resource-timing/resources/eventsource.py b/testing/web-platform/tests/resource-timing/resources/eventsource.py new file mode 100644 index 0000000000..e3a2355730 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/eventsource.py @@ -0,0 +1,3 @@ +def main(request, response): + response.headers.set(b"Content-Type", b"text/event-stream") + return u"" diff --git a/testing/web-platform/tests/resource-timing/resources/fake_responses.html b/testing/web-platform/tests/resource-timing/resources/fake_responses.html new file mode 100644 index 0000000000..52cad6c415 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/fake_responses.html @@ -0,0 +1,19 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/fake_responses.py b/testing/web-platform/tests/resource-timing/resources/fake_responses.py new file mode 100644 index 0000000000..66b17be154 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/fake_responses.py @@ -0,0 +1,41 @@ +# /xhr/resources/conditional.py -- to fake a 304 response + +def main(request, response): + if request.method == "OPTIONS": + # Assume this is a CORS preflight + response.headers.set(b"Access-Control-Allow-Headers", "*") + response.headers.set(b"Access-Control-Allow-Origin", "*") + response.status = (204, "No Content") + return b"" + tag = request.GET.first(b"tag", None) + redirect = request.GET.first(b"redirect", None) + match = request.headers.get(b"If-None-Match", None) + date = request.GET.first(b"date", b"") + modified = request.headers.get(b"If-Modified-Since", None) + url = request.GET.first(b"url", None) + response.headers.set(b"Access-Control-Allow-Origin", b"*"); + response.headers.set(b"Timing-Allow-Origin", b"*"); + if tag: + response.headers.set(b"ETag", b'"%s"' % tag) + elif date: + response.headers.set(b"Last-Modified", date) + if redirect: + response.headers.set(b"Location", redirect) + response.status = (302, b"Moved") + return b"" + + if url: + filename = url.decode('utf-8').split("?")[0] + filepath = "./resource-timing/resources/{}".format(filename) + response.headers.set(b"Content-Type", b"text/javascript") + with open(filepath, 'rb') as f: + filedata = f.read() + return filedata + + if ((match is not None and match == tag) or + (modified is not None and modified == date)): + response.status = (304, b"SUPERCOOL") + return b"" + else: + response.headers.set(b"Content-Type", b"text/plain") + return b"MAYBE NOT" diff --git a/testing/web-platform/tests/resource-timing/resources/fake_responses_https.sub.html b/testing/web-platform/tests/resource-timing/resources/fake_responses_https.sub.html new file mode 100644 index 0000000000..21f1f02a67 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/fake_responses_https.sub.html @@ -0,0 +1,18 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/fake_responses_https_redirect.sub.html b/testing/web-platform/tests/resource-timing/resources/fake_responses_https_redirect.sub.html new file mode 100644 index 0000000000..2ee92b2a55 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/fake_responses_https_redirect.sub.html @@ -0,0 +1,20 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/frame-timing.js b/testing/web-platform/tests/resource-timing/resources/frame-timing.js new file mode 100644 index 0000000000..e0c364e9b2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/frame-timing.js @@ -0,0 +1,48 @@ +function test_frame_timing_before_load_event(type) { + promise_test(async t => { + const {document, performance} = type === 'frame' ? window.parent : window; + const delay = 500; + const frame = document.createElement(type); + t.add_cleanup(() => frame.remove()); + await new Promise(resolve => { + frame.addEventListener('load', resolve); + frame.src = `resources/iframe-with-delay.sub.html?delay=${delay}`; + (type === 'frame' ? document.querySelector('frameset') : document.body).appendChild(frame); + }); + + const entries = performance.getEntriesByName(frame.src); + const navigationEntry = frame.contentWindow.performance.getEntriesByType('navigation')[0]; + assert_equals(entries.length, 1); + assert_equals(entries[0].initiatorType, type); + assert_greater_than(performance.now(), entries[0].responseEnd + delay); + const domContentLoadedEventAbsoluteTime = navigationEntry.domContentLoadedEventStart + frame.contentWindow.performance.timeOrigin; + const frameResponseEndAbsoluteTime = entries[0].responseEnd + performance.timeOrigin; + assert_greater_than(domContentLoadedEventAbsoluteTime, frameResponseEndAbsoluteTime); + }, `A ${type} should report its RT entry when the response is done and before it is completely loaded`); +} + + +function test_frame_timing_change_src(type) { + promise_test(async t => { + const {document, performance} = type === 'frame' ? window.parent : window; + const frame = document.createElement(type); + t.add_cleanup(() => frame.remove()); + await new Promise(resolve => { + const done = () => { + resolve(); + frame.removeEventListener('load', done); + } + frame.addEventListener('load', done); + frame.src = 'resources/green.html?1'; + (type === 'frame' ? document.querySelector('frameset') : document.body).appendChild(frame); + }); + + await new Promise(resolve => { + frame.addEventListener('load', resolve); + frame.src = 'resources/green.html?2'; + }); + + const entries = performance.getEntries().filter(e => e.name.includes('green.html')); + assert_equals(entries.length, 2); + }, `A ${type} should report separate RT entries if its src changed from the outside`); +} \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/frameset-timing-frame.html b/testing/web-platform/tests/resource-timing/resources/frameset-timing-frame.html new file mode 100644 index 0000000000..e260f57526 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/frameset-timing-frame.html @@ -0,0 +1,8 @@ + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/green-frame.html b/testing/web-platform/tests/resource-timing/resources/green-frame.html new file mode 100644 index 0000000000..9613240ae3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/green-frame.html @@ -0,0 +1,7 @@ + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/green.html b/testing/web-platform/tests/resource-timing/resources/green.html new file mode 100644 index 0000000000..b8a1947b77 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/green.html @@ -0,0 +1,10 @@ + + + + + Green Test Page + + +

Placeholder

+ + diff --git a/testing/web-platform/tests/resource-timing/resources/green.html.headers b/testing/web-platform/tests/resource-timing/resources/green.html.headers new file mode 100644 index 0000000000..cb762eff80 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/green.html.headers @@ -0,0 +1 @@ +Access-Control-Allow-Origin: * diff --git a/testing/web-platform/tests/resource-timing/resources/gzip_xml.py b/testing/web-platform/tests/resource-timing/resources/gzip_xml.py new file mode 100644 index 0000000000..7debc9ce3f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/gzip_xml.py @@ -0,0 +1,23 @@ +import gzip as gzip_module +import os + +from io import BytesIO + +from wptserve.utils import isomorphic_decode + +def main(request, response): + dir_path = os.path.dirname(os.path.realpath(isomorphic_decode(__file__))) + file_path = os.path.join(dir_path, u'resource_timing_test0.xml') + f = open(file_path, u'rb') + output = f.read() + + out = BytesIO() + with gzip_module.GzipFile(fileobj=out, mode="w") as f: + f.write(output) + output = out.getvalue() + + headers = [(b"Content-type", b"text/plain"), + (b"Content-Encoding", b"gzip"), + (b"Content-Length", len(output))] + + return headers, output diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html b/testing/web-platform/tests/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html new file mode 100644 index 0000000000..97d77fcc58 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-TAO-crossorigin-port.sub.html @@ -0,0 +1,31 @@ + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-load-from-mem-cache-transfer-size.html b/testing/web-platform/tests/resource-timing/resources/iframe-load-from-mem-cache-transfer-size.html new file mode 100644 index 0000000000..6f37a33e8c --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-load-from-mem-cache-transfer-size.html @@ -0,0 +1,24 @@ + + + + + + transfer size of resource timing when loaded from memory cache. + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-navigate-back.html b/testing/web-platform/tests/resource-timing/resources/iframe-navigate-back.html new file mode 100644 index 0000000000..f944b633e2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-navigate-back.html @@ -0,0 +1,18 @@ + + + + +Resource Timing iframe navigate - back button navigation + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-navigate.html b/testing/web-platform/tests/resource-timing/resources/iframe-navigate.html new file mode 100644 index 0000000000..0286884021 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-navigate.html @@ -0,0 +1,18 @@ + + + + +Resource Timing iframe navigate + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-refresh.html b/testing/web-platform/tests/resource-timing/resources/iframe-refresh.html new file mode 100644 index 0000000000..862b96da9d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-refresh.html @@ -0,0 +1,18 @@ + + + + +Resource Timing iframe refresh + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-reload-TAO.html b/testing/web-platform/tests/resource-timing/resources/iframe-reload-TAO.html new file mode 100644 index 0000000000..461f43bf8e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-reload-TAO.html @@ -0,0 +1,25 @@ + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-setdomain.sub.html b/testing/web-platform/tests/resource-timing/resources/iframe-setdomain.sub.html new file mode 100644 index 0000000000..4a2f609aa4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-setdomain.sub.html @@ -0,0 +1,14 @@ + + + + domain: {{domains[]}} + + + + The resource-timings-level1.sub.html test loads this document into an IFrame to vet that setting + 'document.domain' does not effect the timing allowed. + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe-with-delay.sub.html b/testing/web-platform/tests/resource-timing/resources/iframe-with-delay.sub.html new file mode 100644 index 0000000000..fe50aa7e47 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe-with-delay.sub.html @@ -0,0 +1,3 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html new file mode 100644 index 0000000000..cf68aade79 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/iframe_TAO_match_origin.html @@ -0,0 +1,21 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/import.sub.css b/testing/web-platform/tests/resource-timing/resources/import.sub.css new file mode 100644 index 0000000000..618c568d2a --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/import.sub.css @@ -0,0 +1 @@ +@import "delay-css.py?delay={{GET[delay]}}" \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/importer.css b/testing/web-platform/tests/resource-timing/resources/importer.css new file mode 100644 index 0000000000..771204cdd1 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/importer.css @@ -0,0 +1 @@ +@import 'empty_style.css?stylesheet-imported' \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/importer.js b/testing/web-platform/tests/resource-timing/resources/importer.js new file mode 100644 index 0000000000..e73d45da29 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/importer.js @@ -0,0 +1,2 @@ +import './fake_responses.py?url=empty_script.js?script-head-import-defer'; +import('./fake_responses.py?url=empty_script.js?script-head-import-defer-dynamic').then(module => {}); \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/importer_async.js b/testing/web-platform/tests/resource-timing/resources/importer_async.js new file mode 100644 index 0000000000..4b1cd4ddae --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/importer_async.js @@ -0,0 +1,2 @@ +import './fake_responses.py?url=empty_script.js?script-head-import-async'; +import('./fake_responses.py?url=empty_script.js?script-head-import-async-dynamic').then(module => {}); \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/importer_dynamic.css b/testing/web-platform/tests/resource-timing/resources/importer_dynamic.css new file mode 100644 index 0000000000..f0ba069f0c --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/importer_dynamic.css @@ -0,0 +1 @@ +@import 'empty_style.css?stylesheet-imported-dynamic' \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/importer_print.css b/testing/web-platform/tests/resource-timing/resources/importer_print.css new file mode 100644 index 0000000000..aac191635e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/importer_print.css @@ -0,0 +1 @@ +@import 'empty_style.css?stylesheet-imported-print' \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/inject_resource_test.html b/testing/web-platform/tests/resource-timing/resources/inject_resource_test.html new file mode 100644 index 0000000000..44d09675d3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/inject_resource_test.html @@ -0,0 +1,7 @@ + + + diff --git a/testing/web-platform/tests/resource-timing/resources/invalid.jpg b/testing/web-platform/tests/resource-timing/resources/invalid.jpg new file mode 100644 index 0000000000..81c545efeb --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/invalid.jpg @@ -0,0 +1 @@ +1234 diff --git a/testing/web-platform/tests/resource-timing/resources/manifest.json b/testing/web-platform/tests/resource-timing/resources/manifest.json new file mode 100644 index 0000000000..e107c044d5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/manifest.json @@ -0,0 +1,4 @@ +{ + "name": "Dummy manifest", + "start_url": "/start.html" +} diff --git a/testing/web-platform/tests/resource-timing/resources/multi_redirect.py b/testing/web-platform/tests/resource-timing/resources/multi_redirect.py new file mode 100644 index 0000000000..a5fc5db4ac --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/multi_redirect.py @@ -0,0 +1,59 @@ +import urllib.parse +from wptserve.utils import isomorphic_encode + +def main(request, response): + """Handler that causes multiple redirections. Redirect chain is as follows: + 1. Initial URL containing multi-redirect.py + 2. Redirect to cross-origin URL + 3. Redirect to same-origin URL + 4. Final URL containing the final same-origin resource. + Mandatory parameters: + page_origin - The page origin, used for redirection and to set TAO. This is a mandatory parameter. + cross_origin - The cross origin used to make this a cross-origin redirect. This is a mandatory parameter. + final_resource - Path of the final resource, without origin. This is a mandatory parameter. + Optional parameters: + tao_steps - Number of redirects for which the TAO header will be present (a number 0 - 3 makes the most sense). Default value is 0. + tao_value - The value of the TAO header, when present. Default value is "*". + Note that |step| is a parameter used internally for the multi-redirect. It's the step we're at in the redirect chain. + """ + step = 1 + if b"step" in request.GET: + try: + step = int(request.GET.first(b"step")) + except ValueError: + pass + + page_origin = request.GET.first(b"page_origin") + cross_origin = request.GET.first(b"cross_origin") + final_resource = request.GET.first(b"final_resource") + + tao_value = b"*" + if b"tao_value" in request.GET: + tao_value = request.GET.first(b"tao_value") + tao_steps = 0 + if b"tao_steps" in request.GET: + tao_steps = int(request.GET.first(b"tao_steps")) + + next_tao_steps = tao_steps - 1 + redirect_url_path = b"/resource-timing/resources/multi_redirect.py?" + redirect_url_path += b"page_origin=" + page_origin + redirect_url_path += b"&cross_origin=" + cross_origin + redirect_url_path += b"&final_resource=" + urllib.parse.quote(final_resource).encode('ascii') + redirect_url_path += b"&tao_value=" + tao_value + redirect_url_path += b"&tao_steps=" + isomorphic_encode(str(next_tao_steps)) + redirect_url_path += b"&step=" + if tao_steps > 0: + response.headers.set(b"timing-allow-origin", tao_value) + + if step == 1: + # On the first request, redirect to a cross origin URL + redirect_url = cross_origin + redirect_url_path + b"2" + elif step == 2: + # On the second request, redirect to a same origin URL + redirect_url = page_origin + redirect_url_path + b"3" + else: + # On the third request, redirect to a static response + redirect_url = page_origin + final_resource + + response.status = 302 + response.headers.set(b"Location", redirect_url) diff --git a/testing/web-platform/tests/resource-timing/resources/navigate_back.html b/testing/web-platform/tests/resource-timing/resources/navigate_back.html new file mode 100644 index 0000000000..345eee1fcc --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/navigate_back.html @@ -0,0 +1,7 @@ + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/nested-contexts.js b/testing/web-platform/tests/resource-timing/resources/nested-contexts.js new file mode 100644 index 0000000000..c0822943e8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/nested-contexts.js @@ -0,0 +1,110 @@ +let destination = location; + +if (location.search == "?cross-site") { + const https = destination.protocol.startsWith("https"); + destination = get_host_info()[https ? 'HTTPS_NOTSAMESITE_ORIGIN' : 'HTTP_NOTSAMESITE_ORIGIN']; +} else if (location.search == "?crossorigin") { + destination = get_host_info().REMOTE_ORIGIN; +} + +const pre_navigate_url = + new URL("/resource-timing/resources/document-that-navigates.html", + destination).href; +const post_navigate_url = + new URL("/resource-timing/resources/document-navigated.html", + destination).href; +const pre_refresh_url = + new URL("/resource-timing/resources/document-that-refreshes.html", + destination).href; +const post_refresh_url = + new URL("/resource-timing/resources/document-refreshed.html", + destination).href; + +const setup_navigate_or_refresh = (type, pre, post) => { + const verify_document_navigate_not_observable = () => { + const entries = performance.getEntriesByType("resource"); + let found_first_document = false; + for (entry of entries) { + if (entry.name == pre) { + found_first_document = true; + } + if (entry.name == post) { + opener.postMessage(`FAIL - ${type} document should not be observable`, + `*`); + return; + } + } + if (!found_first_document) { + opener.postMessage("FAIL - initial document should be observable", "*"); + return; + } + opener.postMessage("PASS", "*"); + } + window.addEventListener("message", e => { + if (e.data == type) { + verify_document_navigate_not_observable(); + } + }); +} + +const setup_navigate_test = () => { + setup_navigate_or_refresh("navigated", pre_navigate_url, post_navigate_url); +} + +const setup_refresh_test = () => { + setup_navigate_or_refresh("refreshed", pre_refresh_url, post_refresh_url); +} + +const setup_back_navigation = pushed_url => { + const verify_document_navigate_not_observable = navigated_back => { + const entries = performance.getEntriesByType("resource"); + let found_first_document = false; + for (entry of entries) { + if (entry.name == pre_navigate_url) { + found_first_document = true; + } + if (entry.name == post_navigate_url) { + opener.postMessage("FAIL - navigated document exposed", "*"); + return; + } + } + if (!found_first_document) { + opener.postMessage(`FAIL - first document not exposed. navigated_back ` + + `is ${navigated_back}`, "*"); + return; + } + if (navigated_back) { + opener.postMessage("PASS", "*"); + } + } + window.addEventListener("message", e => { + if (e.data == "navigated") { + verify_document_navigate_not_observable(sessionStorage.navigated); + if (sessionStorage.navigated) { + delete sessionStorage.navigated; + } else { + sessionStorage.navigated = true; + setTimeout(() => { + history.pushState({}, "", pushed_url); + location.href="navigate_back.html"; + }, 0); + } + } + }); +} + +const open_test_window = (url, message) => { + promise_test(() => { + return new Promise((resolve, reject) => { + const openee = window.open(url); + addEventListener("message", e => { + openee.close(); + if (e.data == "PASS") { + resolve(); + } else { + reject(e.data); + } + }); + }); + }, message); +} diff --git a/testing/web-platform/tests/resource-timing/resources/nested.css b/testing/web-platform/tests/resource-timing/resources/nested.css new file mode 100644 index 0000000000..90d61b04ac --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/nested.css @@ -0,0 +1,10 @@ +@import "resource_timing_test0.css?id=n1"; + +@font-face { + font-family: remoteFont; + src: url('/fonts/Ahem.ttf?id=n1'); +} +ol { + font-family: remoteFont; + list-style-image: url('blue.png?id=n1'); +} diff --git a/testing/web-platform/tests/resource-timing/resources/no-entries-for-cross-origin-css-fetched-memory-cache-iframe.sub.html b/testing/web-platform/tests/resource-timing/resources/no-entries-for-cross-origin-css-fetched-memory-cache-iframe.sub.html new file mode 100644 index 0000000000..f47913468b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/no-entries-for-cross-origin-css-fetched-memory-cache-iframe.sub.html @@ -0,0 +1,8 @@ + + + + + + +
    Some content
+ diff --git a/testing/web-platform/tests/resource-timing/resources/notify_parent.html b/testing/web-platform/tests/resource-timing/resources/notify_parent.html new file mode 100644 index 0000000000..c104f3c8f0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/notify_parent.html @@ -0,0 +1,4 @@ + + diff --git a/testing/web-platform/tests/resource-timing/resources/object-navigate-back.html b/testing/web-platform/tests/resource-timing/resources/object-navigate-back.html new file mode 100644 index 0000000000..a746947818 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/object-navigate-back.html @@ -0,0 +1,18 @@ + + + + +Resource Timing object navigate - back button navigation + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/object-navigate.html b/testing/web-platform/tests/resource-timing/resources/object-navigate.html new file mode 100644 index 0000000000..6b4bb3128e --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/object-navigate.html @@ -0,0 +1,18 @@ + + + + +Resource Timing object navigate + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/object-refresh.html b/testing/web-platform/tests/resource-timing/resources/object-refresh.html new file mode 100644 index 0000000000..5c5f60fb06 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/object-refresh.html @@ -0,0 +1,18 @@ + + + + +Resource Timing object refresh + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/resources/observe-entry.js b/testing/web-platform/tests/resource-timing/resources/observe-entry.js new file mode 100644 index 0000000000..260b5929a5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/observe-entry.js @@ -0,0 +1,25 @@ +// Given a resource name, returns a promise that will resolve to the +// corresponding PerformanceResourceTiming entry. The promise will reject, +// however, if the PerformanceResourceTiming entry isn't observed within ~2 +// seconds (scaled according to WPT timeout scaling). +const observe_entry = entry_name => { + const entry = new Promise(resolve => { + new PerformanceObserver((entry_list, observer) => { + for (const entry of entry_list.getEntries()) { + if (entry.name.endsWith(entry_name)) { + resolve(entry); + observer.disconnect(); + return; + } + } + }).observe({"type": "resource", "buffered": true}); + }); + const timeout = new Promise((resolve, reject) => { + step_timeout(() => { + reject(new Error("observe_entry: timeout")); + }, 2000); + }); + // If the entry isn't observed within 2 seconds, assume it will never show + // up. + return Promise.race([entry, timeout]); +}; diff --git a/testing/web-platform/tests/resource-timing/resources/preflight.py b/testing/web-platform/tests/resource-timing/resources/preflight.py new file mode 100644 index 0000000000..f0f6017b47 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/preflight.py @@ -0,0 +1,9 @@ +def main(request, response): + response.headers.set(b"Access-Control-Allow-Origin", b"*") + response.headers.set(b"Access-Control-Max-Age", b"0") + response.headers.set(b"Timing-Allow-Origin", b"*") + # If this script is accessed with the header X-Require-Preflight then the + # browser will send a preflight request. Otherwise it won't. + if request.method == u'OPTIONS': + response.headers.set(b"Access-Control-Allow-Headers", + b"X-Require-Preflight") diff --git a/testing/web-platform/tests/resource-timing/resources/redirect-cors.py b/testing/web-platform/tests/resource-timing/resources/redirect-cors.py new file mode 100644 index 0000000000..655b862fcd --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/redirect-cors.py @@ -0,0 +1,22 @@ +def main(request, response): + if b"allow_origin" in request.GET: + response.headers.set(b"Access-Control-Allow-Origin", + request.GET.first(b"allow_origin")) + + if b"timing_allow_origin" in request.GET: + response.headers.set(b"Timing-Allow-Origin", + request.GET.first(b"timing_allow_origin")) + + # Handle CORS-preflights of non-simple requests. + if request.method == 'OPTIONS': + response.status = 204 + requested_method = request.headers.get(b"Access-Control-Request-Method") + if requested_method: + response.headers.set(b"Access-Control-Allow-Methods", requested_method) + requested_headers = request.headers.get(b"Access-Control-Request-Headers") + if requested_headers: + response.headers.set(b"Access-Control-Allow-Headers", requested_headers) + else: + location = request.GET.first(b"location") + response.status = 302 + response.headers.set(b"Location", location) diff --git a/testing/web-platform/tests/resource-timing/resources/redirect-without-location.py b/testing/web-platform/tests/resource-timing/resources/redirect-without-location.py new file mode 100644 index 0000000000..eef1df858b --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/redirect-without-location.py @@ -0,0 +1,2 @@ +def main(request, response): + response.status = 302 diff --git a/testing/web-platform/tests/resource-timing/resources/resource-loaders.js b/testing/web-platform/tests/resource-timing/resources/resource-loaders.js new file mode 100644 index 0000000000..5a859eb02d --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource-loaders.js @@ -0,0 +1,168 @@ +const load = { + + cache_bust: path => { + let url = new URL(path, location.origin); + url.href += (url.href.includes("?")) ? '&' : '?'; + // The `Number` type in Javascript, when interpreted as an integer, can only + // safely represent [-2^53 + 1, 2^53 - 1] without the loss of precision [1]. + // We do not generate a global value and increment from it, as the increment + // might not have enough precision to be reflected. + // + // [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + url.href += "unique=" + Math.random().toString().substring(2); + return url.href; + }, + + image_with_attrs: async (path, attribute_map) => { + return new Promise(resolve => { + const img = new Image(); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + img[key] = value; + } + } + img.onload = img.onerror = resolve; + img.src = load.cache_bust(path); + }); + }, + + // Returns a promise that settles once the given path has been fetched as an + // image resource. + image: path => { + return load.image_with_attrs(path, undefined); + }, + + // Returns a promise that settles once the given path has been fetched as a + // font resource. + font: path => { + const div = document.createElement('div'); + div.innerHTML = ` + +
This fetches ahem font.
+ `; + document.body.appendChild(div); + return document.fonts.ready.then(() => { + document.body.removeChild(div); + }); + }, + + stylesheet_with_attrs: async (path, attribute_map) => { + const link = document.createElement("link"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + link[key] = value; + } + } + link.rel = "stylesheet"; + link.type = "text/css"; + link.href = load.cache_bust(path); + + const loaded = new Promise(resolve => { + link.onload = link.onerror = resolve; + }); + + document.head.appendChild(link); + await loaded; + document.head.removeChild(link); + }, + + // Returns a promise that settles once the given path has been fetched as a + // stylesheet resource. + stylesheet: async path => { + return load.stylesheet_with_attrs(path, undefined); + }, + + iframe_with_attrs: async (path, attribute_map, validator) => { + const frame = document.createElement("iframe"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + frame[key] = value; + } + } + const loaded = new Promise(resolve => { + frame.onload = frame.onerror = resolve; + }); + frame.src = load.cache_bust(path); + document.body.appendChild(frame); + await loaded; + if (validator instanceof Function) { + validator(frame); + } + document.body.removeChild(frame); + }, + + // Returns a promise that settles once the given path has been fetched as an + // iframe. + iframe: async (path, validator) => { + return load.iframe_with_attrs(path, undefined, validator); + }, + + script_with_attrs: async (path, attribute_map) => { + const script = document.createElement("script"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + script[key] = value; + } + } + const loaded = new Promise(resolve => { + script.onload = script.onerror = resolve; + }); + script.src = load.cache_bust(path); + document.body.appendChild(script); + await loaded; + document.body.removeChild(script); + }, + + // Returns a promise that settles once the given path has been fetched as a + // script. + script: async path => { + return load.script_with_attrs(path, undefined); + }, + + // Returns a promise that settles once the given path has been fetched as an + // object. + object: async (path, type) => { + const object = document.createElement("object"); + const loaded = new Promise(resolve => { + object.onload = object.onerror = resolve; + }); + object.data = load.cache_bust(path); + if (type) { + object.type = type; + } + document.body.appendChild(object); + const timeout = new Promise(r => step_timeout(() => { + console.log("Timeout was reached before load or error events fired"); + r(); + }, 2000)); + await Promise.race([loaded, timeout]); + document.body.removeChild(object); + }, + + // Returns a promise that settles once the given path has been fetched + // through a synchronous XMLHttpRequest. + xhr_sync: async (path, headers) => { + const xhr = new XMLHttpRequest; + xhr.open("GET", path, /* async = */ false); + if (headers instanceof Object) { + for (const [key, value] of Object.entries(headers)) { + xhr.setRequestHeader(key, value); + } + } + xhr.send(); + }, + + xhr_async: path => { + const xhr = new XMLHttpRequest(); + xhr.open("GET", path) + xhr.send(); + return new Promise(resolve => { + xhr.onload = xhr.onerror = resolve; + }); + } +}; diff --git a/testing/web-platform/tests/resource-timing/resources/resource-timing-content-length.py b/testing/web-platform/tests/resource-timing/resources/resource-timing-content-length.py new file mode 100644 index 0000000000..6dbce047b7 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource-timing-content-length.py @@ -0,0 +1,19 @@ +def main(request, response): + content = request.GET.first(b"content") + length = request.GET.first(b"length").decode("ascii") + response.add_required_headers = False + + output = b"HTTP/1.1 200 OK\r\n" + output += b"Content-Type: text/plain;charset=UTF-8\r\n" + if length == b"auto" : + output += b"Content-Length:" + output += "{0}".format(len(content)).encode("ascii") + output += b"\r\n" + elif length != b"none" : + output += b"Content-Length:" + output += "{0}".format(length).encode("ascii") + output += b"\r\n" + output += b"\r\n" + output += content + response.writer.write(output) + response.close_connection = True diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.css b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.css new file mode 100644 index 0000000000..8bc8326ba6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.css @@ -0,0 +1,4 @@ +div#resource_link_css +{ + color:hotpink; +} \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.html b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.html new file mode 100644 index 0000000000..167c65c5c4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.html @@ -0,0 +1,15 @@ + + + + + Child Frame + + + + +

+ Child Document +

+ + + \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js new file mode 100644 index 0000000000..cf1c1df392 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js @@ -0,0 +1,3 @@ +// This is a test script for purposes of testing the +// script initiator type in the Resource Timing feature +var testDummyValue = 0; diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js.headers b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js.headers new file mode 100644 index 0000000000..308bee94d0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.js.headers @@ -0,0 +1,2 @@ +Content-Type: text/javascript +Cache-Control: max-age=36000 diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.png b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.png new file mode 100644 index 0000000000..be211bc377 Binary files /dev/null and b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.png differ diff --git a/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.xml b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.xml new file mode 100644 index 0000000000..91cd676be6 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource_timing_test0.xml @@ -0,0 +1,6 @@ + + + + Test XML Data + + diff --git a/testing/web-platform/tests/resource-timing/resources/self_navigation.html b/testing/web-platform/tests/resource-timing/resources/self_navigation.html new file mode 100644 index 0000000000..beb12f5da5 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/self_navigation.html @@ -0,0 +1 @@ + diff --git a/testing/web-platform/tests/resource-timing/resources/shared-worker.js b/testing/web-platform/tests/resource-timing/resources/shared-worker.js new file mode 100644 index 0000000000..f3ef3feb96 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/shared-worker.js @@ -0,0 +1,3 @@ +self.onconnect = e => { + e.ports[0].postMessage(performance.timeOrigin); +} \ No newline at end of file diff --git a/testing/web-platform/tests/resource-timing/resources/sizes-helper.js b/testing/web-platform/tests/resource-timing/resources/sizes-helper.js new file mode 100644 index 0000000000..86336686b3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/sizes-helper.js @@ -0,0 +1,16 @@ +// Header size is a fixed constant. +// https://w3c.github.io/resource-timing/#dom-performanceresourcetiming-transfersize +const headerSize = 300; + +const cacheBustUrl = url => { + return url + '&unique=' + Math.random().toString().substring(2); +} + +const checkSizeFields = (entry, bodySize, transferSize) => { + assert_equals(entry.decodedBodySize, bodySize, + 'decodedBodySize'); + assert_equals(entry.encodedBodySize, bodySize, + 'encodedBodySize'); + assert_equals(entry.transferSize, transferSize, + 'transferSize'); +} diff --git a/testing/web-platform/tests/resource-timing/resources/status-code.py b/testing/web-platform/tests/resource-timing/resources/status-code.py new file mode 100644 index 0000000000..1c6a021633 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/status-code.py @@ -0,0 +1,8 @@ +def main(request, response): + status = request.GET.first(b'status') + response.status = (status, b""); + if b'tao_value' in request.GET: + response.headers.set(b'timing-allow-origin', request.GET.first(b'tao_value')) + if b'allow_origin' in request.GET: + response.headers.set(b'access-control-allow-origin', request.GET.first(b'allow_origin')) + diff --git a/testing/web-platform/tests/resource-timing/resources/sw-install.html b/testing/web-platform/tests/resource-timing/resources/sw-install.html new file mode 100644 index 0000000000..3d1407e831 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/sw-install.html @@ -0,0 +1,58 @@ + + diff --git a/testing/web-platform/tests/resource-timing/resources/sw.js b/testing/web-platform/tests/resource-timing/resources/sw.js new file mode 100644 index 0000000000..4e4fe1e1f0 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/sw.js @@ -0,0 +1,3 @@ +self.addEventListener('fetch', function(event) { + event.respondWith(fetch(event.request)); +}); diff --git a/testing/web-platform/tests/resource-timing/resources/tao-response.js b/testing/web-platform/tests/resource-timing/resources/tao-response.js new file mode 100644 index 0000000000..2194c5d43a --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/tao-response.js @@ -0,0 +1,13 @@ +const tao_response = (tao_value, base_url) => { + const payload = { + 'headers': { + 'Timing-Allow-Origin': tao_value + } + }; + return custom_cors_response(payload, base_url); +}; + +const remote_tao_response = tao_value => { + const {REMOTE_ORIGIN} = get_host_info(); + return tao_response(tao_value, REMOTE_ORIGIN); +}; diff --git a/testing/web-platform/tests/resource-timing/resources/webperftestharness.js b/testing/web-platform/tests/resource-timing/resources/webperftestharness.js new file mode 100644 index 0000000000..869ef3d74f --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/webperftestharness.js @@ -0,0 +1,166 @@ +/* +author: W3C http://www.w3.org/ +help: http://www.w3.org/TR/navigation-timing/#sec-window.performance-attribute +*/ +// +// Helper Functions for ResourceTiming W3C tests +// + +var performanceNamespace = window.performance; +var timingAttributes = [ + 'connectEnd', + 'connectStart', + 'domComplete', + 'domContentLoadedEventEnd', + 'domContentLoadedEventStart', + 'domInteractive', + 'domLoading', + 'domainLookupEnd', + 'domainLookupStart', + 'fetchStart', + 'loadEventEnd', + 'loadEventStart', + 'navigationStart', + 'redirectEnd', + 'redirectStart', + 'requestStart', + 'responseEnd', + 'responseStart', + 'unloadEventEnd', + 'unloadEventStart' +]; + +var namespace_check = false; + +// +// All test() functions in the WebPerf test suite should use wp_test() instead. +// +// wp_test() validates the window.performance namespace exists prior to running tests and +// immediately shows a single failure if it does not. +// + +function wp_test(func, msg, properties) +{ + // only run the namespace check once + if (!namespace_check) + { + namespace_check = true; + + if (performanceNamespace === undefined || performanceNamespace == null) + { + // show a single error that window.performance is undefined + // The window.performance attribute provides a hosting area for performance related attributes. + test(function() { assert_true(performanceNamespace !== undefined && performanceNamespace != null, "window.performance is defined and not null"); }, "window.performance is defined and not null."); + } + } + + test(func, msg, properties); +} + +function test_namespace(child_name, skip_root) +{ + if (skip_root === undefined) { + var msg = 'window.performance is defined'; + // The window.performance attribute provides a hosting area for performance related attributes. + wp_test(function () { assert_not_equals(performanceNamespace, undefined, msg); }, msg); + } + + if (child_name !== undefined) { + var msg2 = 'window.performance.' + child_name + ' is defined'; + // The window.performance attribute provides a hosting area for performance related attributes. + wp_test(function() { assert_not_equals(performanceNamespace[child_name], undefined, msg2); }, msg2); + } +} + +function test_attribute_exists(parent_name, attribute_name, properties) +{ + var msg = 'window.performance.' + parent_name + '.' + attribute_name + ' is defined.'; + wp_test(function() { assert_not_equals(performanceNamespace[parent_name][attribute_name], undefined, msg); }, msg, properties); +} + +function test_enum(parent_name, enum_name, value, properties) +{ + var msg = 'window.performance.' + parent_name + '.' + enum_name + ' is defined.'; + wp_test(function() { assert_not_equals(performanceNamespace[parent_name][enum_name], undefined, msg); }, msg, properties); + + msg = 'window.performance.' + parent_name + '.' + enum_name + ' = ' + value; + wp_test(function() { assert_equals(performanceNamespace[parent_name][enum_name], value, msg); }, msg, properties); +} + +function test_timing_order(attribute_name, greater_than_attribute, properties) +{ + // ensure it's not 0 first + var msg = "window.performance.timing." + attribute_name + " > 0"; + wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] > 0, msg); }, msg, properties); + + // ensure it's in the right order + msg = "window.performance.timing." + attribute_name + " >= window.performance.timing." + greater_than_attribute; + wp_test(function() { assert_true(performanceNamespace.timing[attribute_name] >= performanceNamespace.timing[greater_than_attribute], msg); }, msg, properties); +} + +function test_timing_greater_than(attribute_name, greater_than, properties) +{ + var msg = "window.performance.timing." + attribute_name + " > " + greater_than; + test_greater_than(performanceNamespace.timing[attribute_name], greater_than, msg, properties); +} + +function test_timing_equals(attribute_name, equals, msg, properties) +{ + var test_msg = msg || "window.performance.timing." + attribute_name + " == " + equals; + test_equals(performanceNamespace.timing[attribute_name], equals, test_msg, properties); +} + +// +// Non-test related helper functions +// + +function sleep_milliseconds(n) +{ + var start = new Date().getTime(); + while (true) { + if ((new Date().getTime() - start) >= n) break; + } +} + +// +// Common helper functions +// + +function test_true(value, msg, properties) +{ + wp_test(function () { assert_true(value, msg); }, msg, properties); +} + +function test_equals(value, equals, msg, properties) +{ + wp_test(function () { assert_equals(value, equals, msg); }, msg, properties); +} + +function test_greater_than(value, greater_than, msg, properties) +{ + wp_test(function () { assert_true(value > greater_than, msg); }, msg, properties); +} + +function test_greater_or_equals(value, greater_than, msg, properties) +{ + wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties); +} + +function test_not_equals(value, notequals, msg, properties) +{ + wp_test(function() { assert_not_equals(value, notequals, msg); }, msg, properties); +} + +function test_tao_pass(entry) { + test_greater_than(entry.redirectStart, 0, 'redirectStart > 0 in cross-origin redirect with Timing-Allow-Origin.'); + test_greater_than(entry.redirectEnd, 0, 'redirectEnd > 0 in cross-origin redirect with Timing-Allow-Origin.'); + test_greater_than(entry.fetchStart, 0, 'fetchStart > 0 in cross-origin redirect with Timing-Allow-Origin.'); + test_greater_than(entry.fetchStart, entry.startTime, 'startTime < fetchStart in cross-origin redirect with Timing-Allow-Origin.'); +} + +function test_tao_fail(entry) { + test_equals(entry.redirectStart, 0, 'redirectStart == 0 in cross-origin redirect with failing Timing-Allow-Origin.'); + test_equals(entry.redirectEnd, 0, 'redirectEnd == 0 in cross-origin redirect with failing Timing-Allow-Origin.'); + test_greater_than(entry.fetchStart, 0, 'fetchStart > 0 in cross-origin redirect with failing Timing-Allow-Origin.'); + test_equals(entry.fetchStart, entry.startTime, 'startTime == fetchStart in cross-origin redirect with failing Timing-Allow-Origin.'); +} diff --git a/testing/web-platform/tests/resource-timing/resources/webperftestharnessextension.js b/testing/web-platform/tests/resource-timing/resources/webperftestharnessextension.js new file mode 100644 index 0000000000..dc02c075b3 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/webperftestharnessextension.js @@ -0,0 +1,188 @@ +// +// Helper functions for Resource Timing tests +// + +var mark_names = [ + '', + '1', + 'abc', +]; + +var measures = [ + [''], + ['2', 1], + ['aaa', 'navigationStart', ''], +]; + +function test_method_exists(method, method_name, properties) +{ + var msg; + if (typeof method === 'function') + msg = 'performance.' + method.name + ' is supported!'; + else + msg = 'performance.' + method_name + ' is supported!'; + wp_test(function() { assert_equals(typeof method, 'function', msg); }, msg, properties); +} + +function test_noless_than(value, greater_than, msg, properties) +{ + wp_test(function () { assert_true(value >= greater_than, msg); }, msg, properties); +} + +function test_fail(msg, properties) +{ + wp_test(function() { assert_unreached(); }, msg, properties); +} + +function test_resource_entries(entries, expected_entries) +{ + test(function() { + // This is slightly convoluted so that we can sort the output. + var actual_entries = {}; + var origin = window.location.protocol + "//" + window.location.host; + + for (var i = 0; i < entries.length; ++i) { + var entry = entries[i]; + var found = false; + for (var expected_entry in expected_entries) { + if (entry.name == origin + expected_entry) { + found = true; + if (expected_entry in actual_entries) { + assert_unreached(expected_entry + ' is not expected to have duplicate entries'); + } + actual_entries[expected_entry] = entry; + break; + } + } + if (!found) { + assert_unreached(entries[i].name + ' is not expected to be in the Resource Timing buffer'); + } + } + + sorted_urls = []; + for (var i in actual_entries) { + sorted_urls.push(i); + } + sorted_urls.sort(); + for (var i in sorted_urls) { + var url = sorted_urls[i]; + assert_equals(actual_entries[url].initiatorType, + expected_entries[url], + origin + url + ' is expected to have initiatorType ' + expected_entries[url]); + } + for (var j in expected_entries) { + if (!(j in actual_entries)) { + assert_unreached(origin + j + ' is expected to be in the Resource Timing buffer'); + } + } + }, "Testing resource entries"); +} + +function performance_entrylist_checker(type) +{ + var entryType = type; + + function entry_check(entry, expectedNames) + { + var msg = 'Entry \"' + entry.name + '\" should be one that we have set.'; + wp_test(function() { assert_in_array(entry.name, expectedNames, msg); }, msg); + test_equals(entry.entryType, entryType, 'entryType should be \"' + entryType + '\".'); + if (type === "measure") { + test_true(isFinite(entry.startTime), 'startTime should be a number.'); + test_true(isFinite(entry.duration), 'duration should be a number.'); + } else if (type === "mark") { + test_greater_than(entry.startTime, 0, 'startTime should greater than 0.'); + test_equals(entry.duration, 0, 'duration of mark should be 0.'); + } + } + + function entrylist_order_check(entryList) + { + var inOrder = true; + for (var i = 0; i < entryList.length - 1; ++i) + { + if (entryList[i + 1].startTime < entryList[i].startTime) { + inOrder = false; + break; + } + } + return inOrder; + } + + function entrylist_check(entryList, expectedLength, expectedNames) + { + test_equals(entryList.length, expectedLength, 'There should be ' + expectedLength + ' entries.'); + test_true(entrylist_order_check(entryList), 'Entries in entrylist should be in order.'); + for (var i = 0; i < entryList.length; ++i) + { + entry_check(entryList[i], expectedNames); + } + } + + return{"entrylist_check":entrylist_check}; +} + +function PerformanceContext(context) +{ + this.performanceContext = context; +} + +PerformanceContext.prototype = { + initialMeasures: function(item, index, array) + { + this.performanceContext.measure.apply(this.performanceContext, item); + }, + + mark: function() + { + this.performanceContext.mark.apply(this.performanceContext, arguments); + }, + + measure: function() + { + this.performanceContext.measure.apply(this.performanceContext, arguments); + }, + + clearMarks: function() + { + this.performanceContext.clearMarks.apply(this.performanceContext, arguments); + + }, + + clearMeasures: function() + { + this.performanceContext.clearMeasures.apply(this.performanceContext, arguments); + + }, + + getEntries: function() + { + return this.performanceContext.getEntries.apply(this.performanceContext, arguments); + }, + + getEntriesByType: function() + { + return this.performanceContext.getEntriesByType.apply(this.performanceContext, arguments); + }, + + getEntriesByName: function() + { + return this.performanceContext.getEntriesByName.apply(this.performanceContext, arguments); + }, + + setResourceTimingBufferSize: function() + { + return this.performanceContext.setResourceTimingBufferSize.apply(this.performanceContext, arguments); + }, + + registerResourceTimingBufferFullCallback: function(func) + { + this.performanceContext.onresourcetimingbufferfull = func; + }, + + clearResourceTimings: function() + { + this.performanceContext.clearResourceTimings.apply(this.performanceContext, arguments); + } + +}; diff --git a/testing/web-platform/tests/resource-timing/resources/worker_with_images.js b/testing/web-platform/tests/resource-timing/resources/worker_with_images.js new file mode 100644 index 0000000000..1fa4893201 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/worker_with_images.js @@ -0,0 +1,22 @@ +let numComplete = 0; + +function checkDone() { + ++numComplete; + if (numComplete == 2) { + const numEntries = performance.getEntries().length; + postMessage(numEntries); + } +} + +function makeRequest(request) { + var xhr = new XMLHttpRequest; + xhr.open('get', request, true); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + checkDone(); + } + } + xhr.send(); +} +makeRequest('blue.png'); +makeRequest('resource_timing_test0.png'); diff --git a/testing/web-platform/tests/resource-timing/response-status-code.html b/testing/web-platform/tests/resource-timing/response-status-code.html new file mode 100644 index 0000000000..3c606c5496 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/response-status-code.html @@ -0,0 +1,157 @@ + + + + +This test validates the response status of resources. + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/same-origin-from-cross-origin-redirect.html b/testing/web-platform/tests/resource-timing/same-origin-from-cross-origin-redirect.html new file mode 100644 index 0000000000..8740b81b13 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/same-origin-from-cross-origin-redirect.html @@ -0,0 +1,31 @@ + + + + +This test validates resource timing information for a same-origin +resource fetched through a cross-origin redirect chain. + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/script-rt-entries.html b/testing/web-platform/tests/resource-timing/script-rt-entries.html new file mode 100644 index 0000000000..cdd72bd1e2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/script-rt-entries.html @@ -0,0 +1,37 @@ + + + + +Resource Timing Entry Sequence of Events for Scripts + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/secure-iframe-in-insecure-context.html b/testing/web-platform/tests/resource-timing/secure-iframe-in-insecure-context.html new file mode 100644 index 0000000000..87f4711146 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/secure-iframe-in-insecure-context.html @@ -0,0 +1,32 @@ + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/shared-worker-rt-entry.html b/testing/web-platform/tests/resource-timing/shared-worker-rt-entry.html new file mode 100644 index 0000000000..194500a095 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/shared-worker-rt-entry.html @@ -0,0 +1,26 @@ + + + + +Resource Timing Entry for Shared Workers + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/sizes-cache.any.js b/testing/web-platform/tests/resource-timing/sizes-cache.any.js new file mode 100644 index 0000000000..af70e5a6de --- /dev/null +++ b/testing/web-platform/tests/resource-timing/sizes-cache.any.js @@ -0,0 +1,55 @@ +// META: global=window,worker +// META: script=/resource-timing/resources/sizes-helper.js +// META: script=/resource-timing/resources/resource-loaders.js + +let url = new URL( + '/resource-timing/resources/cacheable-and-validated.py' + + '?content=loremipsumblablabla', + location.href).href; +const bodySize = 19; + +const accumulateEntries = () => { + return new Promise(resolve => { + const po = new PerformanceObserver(list => { + resolve(list); + }); + po.observe({type: "resource", buffered: true}); + }); +}; + +const checkResourceSizes = list => { + const entries = list.getEntriesByName(url); + assert_equals(entries.length, 3, 'Wrong number of entries'); + let seenCount = 0; + for (let entry of entries) { + if (seenCount === 0) { + // 200 response + checkSizeFields(entry, bodySize, bodySize + headerSize); + } else if (seenCount === 1) { + // from cache + checkSizeFields(entry, bodySize, 0); + } else if (seenCount === 2) { + // 304 response + checkSizeFields(entry, bodySize, headerSize); + } else { + assert_unreached('Too many matching entries'); + } + ++seenCount; + } +}; + +promise_test(() => { + // Use a different URL every time so that the cache behaviour does not + // depend on execution order. + url = load.cache_bust(url); + const eatBody = response => response.arrayBuffer(); + const mustRevalidate = {headers: {'Cache-Control': 'max-age=0'}}; + return fetch(url) + .then(eatBody) + .then(() => fetch(url)) + .then(eatBody) + .then(() => fetch(url, mustRevalidate)) + .then(eatBody) + .then(accumulateEntries) + .then(checkResourceSizes); +}, 'PerformanceResourceTiming sizes caching test'); diff --git a/testing/web-platform/tests/resource-timing/sizes-redirect-img.html b/testing/web-platform/tests/resource-timing/sizes-redirect-img.html new file mode 100644 index 0000000000..786018d0c4 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/sizes-redirect-img.html @@ -0,0 +1,57 @@ + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/sizes-redirect.any.js b/testing/web-platform/tests/resource-timing/sizes-redirect.any.js new file mode 100644 index 0000000000..e483a4d409 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/sizes-redirect.any.js @@ -0,0 +1,62 @@ +// META: global=window,worker +// META: script=/common/get-host-info.sub.js +// META: script=/resource-timing/resources/sizes-helper.js + +const baseUrl = + new URL('/resource-timing/resources/TAOResponse.py?tao=wildcard', location.href).href; +const expectedSize = 4; + +const hostInfo = get_host_info(); +performance.clearResourceTimings(); + +const accumulateEntry = () => { + return new Promise(resolve => { + const po = new PerformanceObserver(list => { + resolve(list); + }); + po.observe({type: "resource", buffered: true}); + }); +}; + +const checkResourceSizes = () => { + const entries = performance.getEntriesByType('resource'); + for (let entry of entries) { + checkSizeFields(entry, expectedSize, expectedSize + headerSize); + } +} + +const redirectUrl = (redirectSourceOrigin, allowOrigin, targetUrl) => { + return redirectSourceOrigin + + '/resource-timing/resources/redirect-cors.py?allow_origin=' + + encodeURIComponent(allowOrigin) + + '&timing_allow_origin=*' + + '&location=' + encodeURIComponent(targetUrl); +} + +promise_test(() => { + // Use a different URL every time so that the cache behaviour does not + // depend on execution order. + const directUrl = cacheBustUrl(baseUrl); + const sameOriginRedirect = redirectUrl(hostInfo.ORIGIN, '*', directUrl); + const crossOriginRedirect = redirectUrl(hostInfo.REMOTE_ORIGIN, + hostInfo.ORIGIN, directUrl); + const mixedRedirect = redirectUrl(hostInfo.REMOTE_ORIGIN, + hostInfo.ORIGIN, sameOriginRedirect); + const complexRedirect = redirectUrl(hostInfo.ORIGIN, + hostInfo.REMOTE_ORIGIN, mixedRedirect); + let eatBody = response => response.arrayBuffer(); + return fetch(directUrl) + .then(eatBody) + .then(() => fetch(sameOriginRedirect)) + .then(eatBody) + .then(() => fetch(crossOriginRedirect)) + .then(eatBody) + .then(() => fetch(mixedRedirect)) + .then(eatBody) + .then(() => fetch(complexRedirect)) + .then(eatBody) + .then(accumulateEntry) + .then(checkResourceSizes); +}, 'PerformanceResourceTiming sizes Fetch with redirect test'); + +done(); diff --git a/testing/web-platform/tests/resource-timing/sleep.py b/testing/web-platform/tests/resource-timing/sleep.py new file mode 100644 index 0000000000..2e803b1b26 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/sleep.py @@ -0,0 +1,13 @@ +import time +import timeit + +# sleep can be lower than requested value in some platforms: https://bugs.python.org/issue31539 +# We add padding here to compensate for that. +sleep_padding = 15.0 + +def sleep_at_least(sleep_in_ms): + sleep_until = timeit.default_timer() + (sleep_in_ms / 1E3) + time.sleep((sleep_in_ms + sleep_padding) / 1E3) + # Check if the padding was sufficient; if not, sleep again. + while timeit.default_timer() < sleep_until: + time.sleep(sleep_padding / 1E3) diff --git a/testing/web-platform/tests/resource-timing/status-codes-create-entry.html b/testing/web-platform/tests/resource-timing/status-codes-create-entry.html new file mode 100644 index 0000000000..cc0cd8ccb8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/status-codes-create-entry.html @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/supported_resource_type.any.js b/testing/web-platform/tests/resource-timing/supported_resource_type.any.js new file mode 100644 index 0000000000..31e40096dd --- /dev/null +++ b/testing/web-platform/tests/resource-timing/supported_resource_type.any.js @@ -0,0 +1,24 @@ +test(() => { + if (typeof PerformanceObserver.supportedEntryTypes === "undefined") + assert_unreached("supportedEntryTypes is not supported."); + assert_true(PerformanceObserver.supportedEntryTypes.includes("resource"), + "There should be an entry 'resource' in PerformanceObserver.supportedEntryTypes"); +}, "supportedEntryTypes contains 'resource'."); + +if (typeof PerformanceObserver.supportedEntryTypes !== "undefined") { + const entryType = "resource"; + if (PerformanceObserver.supportedEntryTypes.includes(entryType)) { + promise_test(async() => { + await new Promise((resolve) => { + new PerformanceObserver(function (list, observer) { + observer.disconnect(); + resolve(); + }).observe({entryTypes: [entryType]}); + + // Force the PerformanceEntry. + // Use `self` for Workers. + fetch(self.location.href + "?" + Math.random()); + }) + }, `'${entryType}' entries should be observable.`) + } +} diff --git a/testing/web-platform/tests/resource-timing/test_resource_timing.html b/testing/web-platform/tests/resource-timing/test_resource_timing.html new file mode 100644 index 0000000000..f4e851abb2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/test_resource_timing.html @@ -0,0 +1,24 @@ + + + + + window.performance Resource Timing Entries exist + + + + + + + +

Description

+

+ NOTE: Due to caching behavior in the browser, it is possible that when revisiting this page, some resources + may not have to be fetched from the network. As a result, the performance timeline will not contain entries + for these resources. This test will fail if any entries are missing to ensure that all resources are fetched + from the network and entries for these resources exist in the Performance Timeline. If revisiting this page, + please either perform a full reload of the page or clear the cache between visits. +

+ +
+ + diff --git a/testing/web-platform/tests/resource-timing/test_resource_timing.https.html b/testing/web-platform/tests/resource-timing/test_resource_timing.https.html new file mode 100644 index 0000000000..f4e851abb2 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/test_resource_timing.https.html @@ -0,0 +1,24 @@ + + + + + window.performance Resource Timing Entries exist + + + + + + + +

Description

+

+ NOTE: Due to caching behavior in the browser, it is possible that when revisiting this page, some resources + may not have to be fetched from the network. As a result, the performance timeline will not contain entries + for these resources. This test will fail if any entries are missing to ensure that all resources are fetched + from the network and entries for these resources exist in the Performance Timeline. If revisiting this page, + please either perform a full reload of the page or clear the cache between visits. +

+ +
+ + diff --git a/testing/web-platform/tests/resource-timing/test_resource_timing.js b/testing/web-platform/tests/resource-timing/test_resource_timing.js new file mode 100644 index 0000000000..598a727bf8 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/test_resource_timing.js @@ -0,0 +1,228 @@ +var TEST_ALLOWED_TIMING_DELTA = 20; + +var waitTimer; +var expectedEntries = {}; + +var initiatorTypes = ["iframe", "img", "link", "script", "xmlhttprequest"]; + +var tests = {}; +setup(function() { + for (var i in initiatorTypes) { + var type = initiatorTypes[i]; + tests[type] = { + "entry": async_test("window.performance.getEntriesByName() and window.performance.getEntriesByNameType() return same data (" + type + ")"), + "simple_attrs": async_test("PerformanceEntry has correct name, initiatorType, startTime, and duration (" + type + ")"), + "timing_attrs": async_test("PerformanceEntry has correct order of timing attributes (" + type + ")"), + "network_attrs": async_test("PerformanceEntry has correct network transfer attributes (" + type + ")"), + "protocol": async_test("PerformanceEntry has correct protocol attribute (" + type + ")") + }; + } +}); + +function resolve(path) { + var a = document.createElement("a"); + a.href = path; + return a.href; +} + +onload = function() +{ + // check that the Performance Timeline API exists + test(function() { + assert_idl_attribute(window.performance, "getEntriesByName", + "window.performance.getEntriesByName() is defined"); + }); + test(function() { + assert_idl_attribute(window.performance, "getEntriesByType", + "window.performance.getEntriesByType() is defined"); + }); + test(function() { + assert_idl_attribute(window.performance, "getEntries", + "window.performance.getEntries() is defined"); + }); + + var expected_entry; + var url; + var type; + var startTime; + var element; + var encodedBodySize; + var decodedBodySize; + for (var i in initiatorTypes) { + startTime = window.performance.now(); + type = initiatorTypes[i]; + if (type != "xmlhttprequest") { + element = document.createElement(type); + } else { + element = null; + } + switch (type) { + case "iframe": + url = resolve("resources/resource_timing_test0.html"); + element.src = url; + encodedBodySize = 215; + decodedBodySize = 215; + break; + case "img": + url = resolve("resources/resource_timing_test0.png"); + element.src = url; + encodedBodySize = 249; + decodedBodySize = 249; + break; + case "link": + element.rel = "stylesheet"; + url = resolve("resources/resource_timing_test0.css"); + element.href = url; + encodedBodySize = 44; + decodedBodySize = 44; + break; + case "script": + element.type = "text/javascript"; + url = resolve("resources/resource_timing_test0.js"); + element.src = url; + encodedBodySize = 133; + decodedBodySize = 133; + break; + case "xmlhttprequest": + var xmlhttp = new XMLHttpRequest(); + url = resolve("resources/gzip_xml.py"); + xmlhttp.open('GET', url, true); + xmlhttp.send(); + encodedBodySize = 112; + decodedBodySize = 125; + break; + } + + expected_entry = {name:url, + startTime: startTime, + initiatorType: type, + encodedBodySize: encodedBodySize, + decodedBodySize: decodedBodySize + }; + + switch (type) { + case "link": + poll_for_stylesheet_load(expected_entry); + document.body.appendChild(element); + break; + case "xmlhttprequest": + xmlhttp.onload = (function(entry) { + return function (event) { + resource_load(entry); + }; + })(expected_entry); + break; + default: + element.onload = (function(entry) { + return function (event) { + resource_load(entry); + }; + })(expected_entry); + document.body.appendChild(element); + } + + } +}; + +function poll_for_stylesheet_load(expected_entry) { + var t = tests[expected_entry.initiatorType]; + + function inner() { + for(var i=0; i 0; + } catch(e) { + hasRules = false; + } + if (hasRules) { + t["entry"].step_timeout(function() { + resource_load(expected_entry); + }, 200); + return; + } + } + } + t["entry"].step_timeout(inner, 100); + } + inner(); +} + +function resource_load(expected) +{ + var t = tests[expected.initiatorType]; + + t["entry"].step(function() { + var entries_by_name = window.performance.getEntriesByName(expected.name); + assert_equals(entries_by_name.length, 1, "should have a single entry for each resource (without type)"); + var entries_by_name_type = window.performance.getEntriesByName(expected.name, "resource"); + assert_equals(entries_by_name_type.length, 1, "should have a single entry for each resource (with type)"); + assert_not_equals(entries_by_name, entries_by_name_type, "values should be copies"); + for (p in entries_by_name[0]) { + var assertMethod = assert_equals + if (Array.isArray(entries_by_name[0][p]) && Array.isArray(entries_by_name_type[0][p])) { + assertMethod = assert_array_equals + } + assertMethod(entries_by_name[0][p], entries_by_name_type[0][p], "Property " + p + " should match"); + } + this.done(); + }); + + t["simple_attrs"].step(function() { + var actual = window.performance.getEntriesByName(expected.name)[0]; + var expected_type = expected.initiatorType; + assert_equals(actual.name, expected.name); + assert_equals(actual.initiatorType, expected_type); + assert_equals(actual.entryType, "resource"); + assert_greater_than_equal(actual.startTime, expected.startTime, "startTime is after the script to initiate the load ran"); + assert_equals(actual.duration, (actual.responseEnd - actual.startTime)); + this.done(); + }); + + t["timing_attrs"].step(function test() { + const entries = window.performance.getEntriesByName(expected.name); + assert_equals(entries.length, 1, 'There should be a single matching entry'); + const actual = entries[0]; + if (window.location.protocol == "http:") { + assert_equals(actual.secureConnectionStart, 0, 'secureConnectionStart should be 0 in http'); + } else { + assert_greater_than(actual.secureConnectionStart, 0, 'secureConnectionStart should not be 0 in https'); + } + + assert_equals(actual.redirectStart, 0, 'redirectStart should be 0'); + assert_equals(actual.redirectEnd, 0, 'redirectEnd should be 0'); + assert_equals(actual.fetchStart, actual.startTime, 'fetchStart is equal to startTime'); + assert_greater_than_equal(actual.domainLookupStart, actual.fetchStart, 'domainLookupStart after fetchStart'); + assert_greater_than_equal(actual.domainLookupEnd, actual.domainLookupStart, 'domainLookupEnd after domainLookupStart'); + assert_greater_than_equal(actual.connectStart, actual.domainLookupEnd, 'connectStart after domainLookupEnd'); + assert_greater_than_equal(actual.connectEnd, actual.connectStart, 'connectEnd after connectStart'); + assert_true(actual.secureConnectionStart == 0 || actual.secureConnectionStart <= actual.requestStart, + "secureConnectionStart should be either 0 or smaller than/equals to requestStart") + assert_greater_than_equal(actual.requestStart, actual.connectEnd, 'requestStart after connectEnd'); + assert_greater_than_equal(actual.responseStart, actual.requestStart, 'responseStart after requestStart'); + assert_greater_than_equal(actual.responseEnd, actual.responseStart, 'responseEnd after responseStart'); + this.done(); + }); + + t["network_attrs"].step(function test() { + var actual = window.performance.getEntriesByName(expected.name)[0]; + assert_equals(actual.encodedBodySize, expected.encodedBodySize, "encodedBodySize size"); + assert_equals(actual.decodedBodySize, expected.decodedBodySize, "decodedBodySize size"); + + // Transfer size will vary from browser to browser based on default headers, etc. This + // test verifies that transferSize for uncached resources is greater than on-the-wire + // body size. + assert_greater_than(actual.transferSize, actual.encodedBodySize, "transferSize size"); + this.done(); + }); + + t["protocol"].step(function() { + var actual = window.performance.getEntriesByName(expected.name)[0]; + assert_equals(actual.nextHopProtocol, "http/1.1", "expected protocol"); + this.done(); + }); + +} diff --git a/testing/web-platform/tests/resource-timing/tojson.html b/testing/web-platform/tests/resource-timing/tojson.html new file mode 100644 index 0000000000..2564b855df --- /dev/null +++ b/testing/web-platform/tests/resource-timing/tojson.html @@ -0,0 +1,71 @@ + + + + +This test validates that PerformanceResourceTiming's toJSON method + contains all of the entry's attributes. + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/workerStart-tao-protected.https.html b/testing/web-platform/tests/resource-timing/workerStart-tao-protected.https.html new file mode 100644 index 0000000000..f54c0f2756 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/workerStart-tao-protected.https.html @@ -0,0 +1,76 @@ + + + + +Resource Timing - Check that workerStart is TAO protected + + + + + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/worklet-rt-entries.https.html b/testing/web-platform/tests/resource-timing/worklet-rt-entries.https.html new file mode 100644 index 0000000000..8ed280be17 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/worklet-rt-entries.https.html @@ -0,0 +1,19 @@ + + + + +Resource Timing Entry Sequence of Events for Worklets + + + + + + + + diff --git a/testing/web-platform/tests/resource-timing/xhr-resource-timing.html b/testing/web-platform/tests/resource-timing/xhr-resource-timing.html new file mode 100644 index 0000000000..6f8f333186 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/xhr-resource-timing.html @@ -0,0 +1,29 @@ + + + + +This test validates that a failed cross-origin fetch creates an opaque network timing entry. + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3