| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8" /> |
| <title>This test validates the values in resource timing for cross-origin |
| redirects.</title> |
| <link rel="author" title="Intel" href="http://www.intel.com/" /> |
| <link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming"/> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/common/custom-cors-response.js"></script> |
| <script src="/common/get-host-info.sub.js"></script> |
| <script src="resources/entry-invariants.js"></script> |
| <script src="resources/resource-loaders.js"></script> |
| <script src="resources/tao-response.js"></script> |
| </head> |
| <body> |
| <script> |
| const {ORIGIN, REMOTE_ORIGIN} = get_host_info(); |
| |
| const HTTP_SO_to_XO_redirect_url = url => { |
| // Make an initial request to a same-domain resource that will return a 302 |
| // redirect to the given (possibly cross-origin) url. |
| return `/resource-timing/resources/redirect-cors.py?location=${url}`; |
| }; |
| |
| const HTTP_SO_resource = () => { |
| if (location.protocol != "http:") { |
| throw new Error("Can only make an HTTP SO request if this page was " + |
| "served over HTTP."); |
| } |
| return tao_response("*", ORIGIN); |
| }; |
| |
| const HTTP_XO_redirect = (url, tao) => { |
| const ret = new URL( |
| `${REMOTE_ORIGIN}/resource-timing/resources/redirect-cors.py`); |
| ret.searchParams.append("location", url); |
| ret.searchParams.append("allow_origin", "*"); |
| ret.searchParams.append("timing_allow_origin", tao); |
| return ret.href; |
| }; |
| |
| attribute_test( |
| load.iframe, HTTP_SO_to_XO_redirect_url(custom_cors_response({}, |
| REMOTE_ORIGIN)), |
| invariants.assert_http_to_cross_origin_redirected_resource, |
| "Verify that cross-origin resources' timings aren't exposed through HTTP " + |
| "redirects."); |
| |
| attribute_test( |
| load.iframe, HTTP_SO_to_XO_redirect_url(remote_tao_response("no-match")), |
| invariants.assert_cross_origin_redirected_resource, |
| "Verify that a redirected cross-origin resources' timings aren't exposed " + |
| "when the TAO check fails."); |
| |
| attribute_test( |
| load.iframe, HTTP_SO_to_XO_redirect_url(remote_tao_response("*")), |
| invariants.assert_http_to_tao_enabled_cross_origin_https_redirected_resource, |
| "Verify that cross-origin resources' timings are exposed when the TAO " + |
| "check succeeds. Also verify that secureConnectionStart is 0 since the " + |
| "original request was over HTTP."); |
| |
| attribute_test( |
| load.iframe, HTTP_XO_redirect(HTTP_XO_redirect(HTTP_SO_resource(), "*"), "*"), |
| invariants.assert_http_to_tao_enabled_cross_origin_https_redirected_resource, |
| "Verify that a redirect chain through cross-origin resources have their " + |
| "timings exposed when all TAO checks succeed. Also verify that " + |
| "secureConnectionStart is 0 since the original request was over HTTP."); |
| |
| const failure_permutations = [ |
| ["fail", "fail", "fail"], |
| ["fail", "fail", "*" ], |
| ["fail", "*", "fail"], |
| ["fail", "*", "*" ], |
| ["*", "fail", "fail"], |
| ["*", "fail", "*" ], |
| ["*", "*", "fail"], |
| ]; |
| const test_case = (so_tao, xo1_tao, xo2_tao) => { |
| return HTTP_XO_redirect(HTTP_XO_redirect(HTTP_SO_resource( |
| so_tao), xo2_tao), xo1_tao); |
| }; |
| const test_label = perm => { |
| return perm.map(x => { |
| if (x == "*" ) return "PASS"; |
| if (x == "fail" ) return "FAIL"; |
| throw new Error(`unexpected element ${x}`); |
| }).join(" -> "); |
| }; |
| for (const permutation of failure_permutations) { |
| attribute_test( |
| load.iframe, test_case.apply(permutation), |
| invariants.assert_tao_failure_resource, |
| `Verify that a redirect chain through cross-origin resources do not have ` + |
| `their timings exposed when any of the TAO checks fail. ` + |
| `(${test_label(permutation)})`); |
| } |
| |
| </script> |
| </body> |
| </html> |