summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/cross-origin-embedder-policy/credentialless/resources/common.js
blob: ce21c766f6c30fcb87147611ae1a6af9aa54ce0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
const executor_path = '/common/dispatcher/executor.html?pipe=';
const executor_worker_path = '/common/dispatcher/executor-worker.js?pipe=';
const executor_service_worker_path = '/common/dispatcher/executor-service-worker.js?pipe=';

// COEP
const coep_none =
    '|header(Cross-Origin-Embedder-Policy,none)';
const coep_credentialless =
    '|header(Cross-Origin-Embedder-Policy,credentialless)';
const coep_require_corp =
    '|header(Cross-Origin-Embedder-Policy,require-corp)';

// COEP-Report-Only
const coep_report_only_credentialless =
    '|header(Cross-Origin-Embedder-Policy-Report-Only,credentialless)';

// COOP
const coop_same_origin =
    '|header(Cross-Origin-Opener-Policy,same-origin)';

// CORP
const corp_cross_origin =
    '|header(Cross-Origin-Resource-Policy,cross-origin)';

const cookie_same_site_none = ';SameSite=None;Secure';

// Test using the modern async/await primitives are easier to read/write.
// However they run sequentially, contrary to async_test. This is the parallel
// version, to avoid timing out.
let promise_test_parallel = (promise, description) => {
  async_test(test => {
    promise(test)
      .then(() => test.done())
      .catch(test.step_func(error => { throw error; }));
  }, description);
};

// Add a cookie |cookie_key|=|cookie_value| on an |origin|.
// Note: cookies visibility depends on the path of the document. Those are set
// from a document from: /html/cross-origin-embedder-policy/credentialless/. So
// the cookie is visible to every path underneath.
const setCookie = async (origin, cookie_key, cookie_value) => {
  const popup_token = token();
  const popup_url = origin + executor_path + `&uuid=${popup_token}`;
  const popup = window.open(popup_url);

  const reply_token = token();
  send(popup_token, `
    document.cookie = "${cookie_key}=${cookie_value}";
    send("${reply_token}", "done");
  `);
  assert_equals(await receive(reply_token), "done");
  popup.close();
}

let parseCookies = function(headers_json) {
  if (!headers_json["cookie"])
    return {};

  return headers_json["cookie"]
    .split(';')
    .map(v => v.split('='))
    .reduce((acc, v) => {
      acc[v[0].trim()] = v[1].trim();
      return acc;
    }, {});
}

// Open a new window with a given |origin|, loaded with COEP:credentialless. The
// new document will execute any scripts sent toward the token it returns.
const newCredentiallessWindow = (origin) => {
  const main_document_token = token();
  const url = origin + executor_path + coep_credentialless +
    `&uuid=${main_document_token}`;
  const context = window.open(url);
  add_completion_callback(() => w.close());
  return main_document_token;
};

// Create a new iframe, loaded with COEP:credentialless.
// The new document will execute any scripts sent toward the token it returns.
const newCredentiallessIframe = (parent_token, child_origin) => {
  const sub_document_token = token();
  const iframe_url = child_origin + executor_path + coep_credentialless +
    `&uuid=${sub_document_token}`;
  send(parent_token, `
    let iframe = document.createElement("iframe");
    iframe.src = "${iframe_url}";
    document.body.appendChild(iframe);
  `)
  return sub_document_token;
};

// A common interface for building the 4 type of execution contexts:
// It outputs: [
//   - The token to communicate with the environment.
//   - A promise resolved when the environment encounters an error.
// ]
const environments = {
  document: headers => {
    const tok = token();
    const url = window.origin + executor_path + headers + `&uuid=${tok}`;
    const context = window.open(url);
    add_completion_callback(() => context.close());
    return [tok, new Promise(resolve => {})];
  },

  dedicated_worker: headers => {
    const tok = token();
    const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`;
    const context = new Worker(url);
    return [tok, new Promise(resolve => context.onerror = resolve)];
  },

  shared_worker: headers => {
    const tok = token();
    const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`;
    const context = new SharedWorker(url);
    return [tok, new Promise(resolve => context.onerror = resolve)];
  },

  service_worker: headers => {
    const tok = token();
    const url = window.origin + executor_worker_path + headers + `&uuid=${tok}`;
    const scope = url; // Generate a one-time scope for service worker.
    const error = new Promise(resolve => {
      navigator.serviceWorker.register(url, {scope: scope})
        .then(registration => {
          add_completion_callback(() => registration.unregister());
        }, /* catch */ resolve);
    });
    return [tok, error];
  },
};