File: noopener-helper.js

package info (click to toggle)
thunderbird 1%3A140.4.0esr-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,609,432 kB
  • sloc: cpp: 7,672,442; javascript: 5,901,613; ansic: 3,898,954; python: 1,413,343; xml: 653,997; asm: 462,286; java: 180,927; sh: 113,489; makefile: 20,460; perl: 14,288; objc: 13,059; yacc: 4,583; pascal: 3,352; lex: 1,720; ruby: 1,222; exp: 762; sql: 715; awk: 580; php: 436; lisp: 430; sed: 70; csh: 10
file content (166 lines) | stat: -rw-r--r-- 6,167 bytes parent folder | download | duplicates (10)
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
const executor_path = '/common/dispatcher/executor.html?pipe=';
const coop_header = policy => {
  return `|header(Cross-Origin-Opener-Policy,${policy})`;
};

function getExecutorPath(uuid, origin, coop_header) {
  return origin.origin + executor_path + coop_header + `&uuid=${uuid}`;
}

// Open a same-origin popup with `opener_coop` header, then open a popup with
// `openee_coop` header. Check whether the opener can script the openee.
const test_noopener_opening_popup = (
  opener_coop,
  openee_coop,
  origin,
  opener_expectation
) => {
  promise_test(async t => {
    // Set up dispatcher communications.
    const popup_token = token();
    const reply_token = token();
    const popup_reply_token = token();
    const popup_openee_token = token();

    const popup_url = getExecutorPath(
      popup_token, SAME_ORIGIN, coop_header(opener_coop));

    // We open a popup and then ping it, it will respond after loading.
    const popup = window.open(popup_url);
    t.add_cleanup(() => send(popup_token, 'window.close()'));
    send(popup_token, `send('${reply_token}', 'Popup loaded');`);
    assert_equals(await receive(reply_token), 'Popup loaded');

    if (opener_coop == 'noopener-allow-popups') {
      // Assert that we can't script the popup.
      await t.step_wait(() => popup.closed, 'Opener popup.closed')
    }

    // Ensure that the popup has no access to its opener.
    send(popup_token, `
      let openerDOMAccessAllowed = false;
      try {
        openerDOMAccessAllowed = !!self.opener.document.URL;
      } catch(ex) {}
      const payload = {
        opener: !!self.opener,
        openerDOMAccess: openerDOMAccessAllowed
      };
      send('${reply_token}', JSON.stringify(payload));
    `);
    let payload = JSON.parse(await receive(reply_token));
    if (opener_coop == 'noopener-allow-popups') {
      assert_false(payload.opener, 'popup opener');
      assert_false(payload.openerDOMAccess, 'popup DOM access');
    }

    // Open another popup from inside the popup, and wait for it to load.
    const popup_openee_url = getExecutorPath(popup_openee_token, origin,
      coop_header(openee_coop));
    send(popup_token, `
      window.openee = open("${popup_openee_url}");
      await receive('${popup_reply_token}');
      const payload = {
        openee: !!window.openee,
        closed: window.openee.closed
      };
      send('${reply_token}', JSON.stringify(payload));
    `);
    t.add_cleanup(() => send(popup_token, 'window.openee.close()'));
    // Notify the popup that its openee was loaded.
    send(popup_openee_token, `
      send('${popup_reply_token}', 'popup openee opened');
    `);

    // Assert that the popup has access to its openee.
    payload = JSON.parse(await receive(reply_token));
    assert_true(payload.openee, 'popup openee');

    // Assert that the openee has access to its popup opener.
    send(popup_openee_token, `
      let openerDOMAccessAllowed = false;
      try {
        openerDOMAccessAllowed = !!self.opener.document.URL;
      } catch(ex) {}
      const payload = {
        opener: !!self.opener,
        openerDOMAccess: openerDOMAccessAllowed
      };
      send('${reply_token}', JSON.stringify(payload));
    `);
    payload = JSON.parse(await receive(reply_token));
    if (opener_expectation) {
      assert_true(payload.opener, 'Opener is not null');
      assert_true(payload.openerDOMAccess, 'No DOM access');
    } else {
      assert_false(payload.opener, 'Opener is null');
      assert_false(payload.openerDOMAccess, 'No DOM access');
    }
  },
  'noopener-allow-popups ensures that the opener cannot script the openee,' +
  ' but further popups with no COOP can access their opener: ' +
  opener_coop + '/' + openee_coop + ':' + origin == SAME_ORIGIN);
};

// Open a same-origin popup with `popup_coop` header, then navigate away toward
// one with `noopener-allow-popups`. Check the opener can't script the openee.
const test_noopener_navigating_away = (popup_coop) => {
  promise_test(async t => {
    // Set up dispatcher communications.
    const popup_token = token();
    const reply_token = token();
    const popup_reply_token = token();
    const popup_second_token = token();

    const popup_url =
      getExecutorPath(popup_token, SAME_ORIGIN, coop_header(popup_coop));

    // We open a popup and then ping it, it will respond after loading.
    const popup = window.open(popup_url);
    send(popup_token, `send('${reply_token}', 'Popup loaded');`);
    assert_equals(await receive(reply_token), 'Popup loaded');
    t.add_cleanup(() => send(popup_token, 'window.close()'));

    // There's an open question if we should check that popup.window is null here.
    // See https://github.com/whatwg/html/issues/10457
    // Assert that we cannot script the popup.
    assert_false(popup.closed, 'popup closed');

    // Ensure that the popup has no access to its opener.
    send(popup_token, `
      let openerDOMAccessAllowed = false;
      try {
        openerDOMAccessAllowed = !!self.opener.document.URL;
      } catch(ex) {}
      const payload = {
        opener: !!self.opener,
        openerDOMAccess: openerDOMAccessAllowed
      };
      send('${reply_token}', JSON.stringify(payload));
    `);
    let payload = JSON.parse(await receive(reply_token));
    assert_true(payload.opener, 'popup opener');
    assert_true(payload.openerDOMAccess, 'popup DOM access');

    // Navigate the popup.
    const popup_second_url = getExecutorPath(
      popup_second_token, SAME_ORIGIN,
      coop_header('noopener-allow-popups'));

    send(popup_token, `
      window.location = '${popup_second_url}';
    `);

    // Notify the popup that its openee was loaded.
    send(popup_second_token, `
      send('${reply_token}', 'popup navigated away');
    `);
    assert_equals(await receive(reply_token), 'popup navigated away');

    // There's an open question if we should check that popup.window is null here.
    // See https://github.com/whatwg/html/issues/10457
    assert_true(popup.closed, 'popup.closed');
  },
  'noopener-allow-popups ensures that the opener cannot script the openee,' +
  ' even after a navigation: ' + popup_coop);
};