<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<meta name="timeout" content="long">
<title>This test validates the response status of resources.</title>
<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="resources/entry-invariants.js"></script>
<script src="resources/resource-loaders.js"></script>
<script src="/common/get-host-info.sub.js"></script>
</head>
<body>
<script>
const {ORIGIN, REMOTE_ORIGIN} = get_host_info();
const SAME_ORIGIN = location.origin;
const status_codes = [
  200, 203,
  400, 401, 403, 404,
  500, 501, 502, 503,
];

const load_image_object = async path => {
  return load.object(path, "image/png");
}

const load_frame_object = async path => {
  return load.object(path, "text/html");
}

const load_null_object = async path => {
  return load.object(path, null);
}

// Response status for same origin resources is exposed.
for(const loader of [
  load.font,
  load.image,
  load.script,
  load.stylesheet,
  load.xhr_sync,
  load.xhr_async,
  load.iframe,
  load_image_object,
  load_frame_object,
  load_null_object
]) {
  for(const status of status_codes) {
    let path = (loader == load.font) ? '/fonts/pass.woff' :
                                       '/resource-timing/resources/empty.js';
    path += `?pipe=status(${status})`;
    attribute_test(
      loader, new URL(path, ORIGIN),
      entry => {
        assert_equals(entry.responseStatus, status,
          `response status for ${entry.name} should be ${status}`);
      }
    );
  }
}

// Response status is exposed for CORS requests for cross-origin resources.
for(const loader of [
  load.image_with_attrs,
  load.script_with_attrs,
  load.stylesheet_with_attrs
]) {
  for(const status of status_codes) {
    const path = `/resource-timing/resources/empty.js?pipe=status(${status})`
      + `|header(access-control-allow-origin, ${ORIGIN})`;
    loader_with_crossOrigin_attr = async url => {
      return loader(url, {"crossOrigin": "anonymous"});
    }
    attribute_test(
      loader_with_crossOrigin_attr, new URL(path, REMOTE_ORIGIN),
      entry => {
        assert_equals(entry.responseStatus, status,
          `response status for ${entry.name} should be ${status}`);
      }
    );
  }
}

// Response status is 0 when a no-cors request is made for cross origin
// fonts, images, scripts, stylesheets.
// Response status is 0 when request's mode is "navigate" and response's
// URL's origin is not same origin with request's origin. So response
// status is not exposed for cross origin iframes.
for(const loader of [
  load.font,
  load.image,
  load.script,
  load.stylesheet,
  load.iframe,
  load_image_object,
  load_frame_object,
  load_null_object
]) {
  for(const tao of [false, true]) {
    for(const status of status_codes) {
      let path = (loader == load.font) ? '/fonts/pass.woff' :
                                         '/resource-timing/resources/empty.js';
      path += `?pipe=status(${status})`;
      if (tao) {
        path += `|header(timing-allow-origin, *)`;
      }
      attribute_test(
        loader, new URL(path, REMOTE_ORIGIN),
        entry => {
          assert_equals(entry.responseStatus, 0,
            `response status for ${entry.name} should be 0`);
        }
      );
    }
  }
}

// Response status for iframes is 0 when cross origin redirects are present
// Same-Origin => Cross-Origin => Same-Origin => Same-Origin redirect chain
for(const loader of [
  load.iframe,
  load_frame_object,
  load_null_object
]) {
  for(const status of status_codes) {
    const destUrl =
      `${SAME_ORIGIN}/resource-timing/resources/multi_redirect.py` +
        `?page_origin=${SAME_ORIGIN}` +
        `&cross_origin=${REMOTE_ORIGIN}` +
        `&final_resource=` +
        `/resource-timing/resources/empty.js?pipe=status(${status})`;
    attribute_test(
      loader, new URL(destUrl),
      entry => {
        assert_equals(entry.responseStatus, 0,
          `response status should be 0 for iframes having cross origin`
          + ` redirects`);
      }
    );
  }
}

// Response status for iframes is exposed for same origin redirects
for(const loader of [
  load.iframe,
  load_frame_object,
  load_null_object
]) {
  for(const status of status_codes) {
    const destUrl = `${SAME_ORIGIN}/resource-timing/resources/redirect-cors.py`
      + `?location=${SAME_ORIGIN}/resource-timing/resources/empty.js`
      + `?pipe=status(${status})`;
    attribute_test(
      loader, new URL(destUrl),
      entry => {
        assert_equals(entry.responseStatus, status,
          `response status should be exposed for iframes having only same`
          + ` origin redirects`);
      }
    );
  }
};
</script>
</body>
</html>
