const Host = {
  SAME_ORIGIN: "same-origin",
  CROSS_ORIGIN: "cross-origin",
};

const PolicyHeader = {
  CSP: "echo-policy.py?policy=",
  CSP_MULTIPLE: "echo-policy-multiple.py",
  REQUIRED_CSP: "echo-required-csp.py",
  ALLOW_CSP_FROM: "echo-allow-csp-from.py",
};

const IframeLoad = {
  EXPECT_BLOCK: true,
  EXPECT_LOAD: false,
};

function getOrigin() {
  var url = new URL("http://{{host}}:{{ports[http][0]}}/");
  return url.origin;
}

function getCrossOrigin() {
  var url = new URL("http://{{domains[天気の良い日]}}:{{ports[http][0]}}/");
  return url.toString();
}

function getSecureCrossOrigin() {
  // Since wptserve spins up servers on non-default port, 'self' matches
  // http://[host]:[specified-port] and https://[host]:[specified-port], but not
  // https://[host]:[https-port]. So, we use the http port for this https origin
  // in order to verify that a secure variant of a non-secure URL matches 'self'.
  var url = new URL("https://{{domains[天気の良い日]}}:{{ports[http][0]}}");
  return url.toString();
}

function generateURL(host, path, include_second_level_iframe, second_level_iframe_csp) {
  var url = new URL("http://{{host}}:{{ports[http][0]}}/content-security-policy/embedded-enforcement/support/");
  url.hostname = host == Host.SAME_ORIGIN ? "{{host}}" : "{{domains[天気の良い日]}}";
  url.pathname += path;
  if (include_second_level_iframe) {
    url.searchParams.append("include_second_level_iframe", "");
    if (second_level_iframe_csp)
      url.searchParams.append("second_level_iframe_csp", second_level_iframe_csp);
  }

  return url;
}

function generateURLString(host, path) {
  return generateURL(host, path, false, "").toString();
}

function generateURLStringWithSecondIframeParams(host, path, second_level_iframe_csp) {
  return generateURL(host, path, true, second_level_iframe_csp).toString();
}

function generateRedirect(host, target) {
  var url = new URL("http://{{host}}:{{ports[http][0]}}/common/redirect.py?location=" +
   encodeURIComponent(target));
  url.hostname = host == Host.SAME_ORIGIN ? "{{host}}" : "{{domains[天気の良い日]}}";

  return url.toString();
}

function generateUrlWithPolicies(host, policy) {
  var url = generateURL(host, PolicyHeader.CSP_MULTIPLE);
  if (policy != null)
    url.searchParams.append("policy", policy);
  return url;
}

function generateUrlWithAllowCSPFrom(host, allowCspFrom) {
  var url = generateURL(host, PolicyHeader.ALLOW_CSP_FROM);
  if (allowCspFrom != null)
    url.searchParams.append("allow_csp_from", allowCspFrom);
  return url;
}

function assert_required_csp(t, url, csp, expected) {
  var i = document.createElement('iframe');
  if(csp)
    i.csp = csp;
  i.src = url;

  window.addEventListener('message', t.step_func(e => {
    if (e.source != i.contentWindow || !('required_csp' in e.data))
      return;

    if (expected.indexOf(e.data['required_csp']) == -1)
      assert_unreached('Child iframes have unexpected csp:"' + e.data['required_csp'] + '"');

    expected.splice(expected.indexOf(e.data['required_csp']), 1);

    if (e.data['test_header_injection'] != null)
      assert_unreached('HTTP header injection was successful');

    if (expected.length == 0)
      t.done();
  }));

  document.body.appendChild(i);
}

function assert_iframe_with_csp(t, url, csp, shouldBlock, urlId, blockedURI,
                                checkImageLoaded) {
  const i = document.createElement('iframe');
  url.searchParams.append("id", urlId);
  i.src = url.toString();
  if (csp != null)
    i.csp = csp;

  var loaded = {};
  var onLoadReceived = {};
  window.addEventListener("message", function (e) {
    if (e.source != i.contentWindow)
        return;
    if (e.data["loaded"])
        loaded[e.data["id"]] = true;
  });

  if (shouldBlock) {
    // Assert iframe does not load and is inaccessible.
    window.onmessage = t.step_func(function(e) {
      if (e.source != i.contentWindow)
          return;
      assert_unreached('No message should be sent from the frame.');
    });
    i.onload = t.step_func(function () {
      // Delay the check until after the postMessage has a chance to execute.
      setTimeout(t.step_func_done(function () {
        assert_equals(loaded[urlId], undefined);
      }), 500);
      assert_throws_dom("SecurityError", () => {
        var x = i.contentWindow.location.href;
      });
    });
  } else if (blockedURI) {
    // Assert iframe loads with an expected violation.
    window.addEventListener('message', t.step_func(e => {
      if (e.source != i.contentWindow)
        return;
      if (!e.data.securitypolicyviolation)
        return;
      assert_equals(e.data["blockedURI"], blockedURI);
      t.done();
    }));
  } else {
    // Assert iframe loads.  Wait for the load event, the postMessage from the
    // script and the img load event.
    let img_loaded = !checkImageLoaded;
    window.addEventListener('message', t.step_func(e => {
      if (e.source != i.contentWindow)
        return;
      if (e.data === "img loaded")
        img_loaded = true;

      if (loaded[urlId] && onLoadReceived[urlId] && img_loaded) {
        t.done();
      }
    }));
    i.onload = t.step_func(function () {
      onLoadReceived[urlId] = true;
      if (loaded[urlId] && onLoadReceived[urlId] && img_loaded) {
        t.done();
      }
    });
  }
  document.body.appendChild(i);
}
