summaryrefslogtreecommitdiffstats
path: root/browser/components/originattributes/test/browser/browser_firstPartyIsolation_aboutPages.js
blob: 81141f2e5a6fb987c736a3e8794ff6d0341cb78f (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
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
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
if (SpecialPowers.useRemoteSubframes) {
  requestLongerTimeout(2);
}

add_setup(async function () {
  Services.prefs.setBoolPref("privacy.firstparty.isolate", true);

  registerCleanupFunction(function () {
    Services.prefs.clearUserPref("privacy.firstparty.isolate");
  });
});

/**
 * For loading the initial about:blank in e10s mode, it will be loaded with
 * NullPrincipal, and we also test if the firstPartyDomain of the origin
 * attributes is got from the origin itself.
 */
add_task(async function test_remote_window_open_aboutBlank() {
  let win = await BrowserTestUtils.openNewBrowserWindow({ remote: true });
  let browser = win.gBrowser.selectedBrowser;

  Assert.ok(browser.isRemoteBrowser, "should be a remote browser");

  await SpecialPowers.spawn(browser, [], async function () {
    Assert.ok(true, "origin " + content.document.nodePrincipal.origin);

    Assert.ok(
      content.document.nodePrincipal.isNullPrincipal,
      "The principal of remote about:blank should be a NullPrincipal."
    );

    let str = content.document.nodePrincipal.originNoSuffix;
    let expectDomain =
      str.substring("moz-nullprincipal:{".length, str.length - 1) + ".mozilla";
    Assert.equal(
      content.document.nodePrincipal.originAttributes.firstPartyDomain,
      expectDomain,
      "remote about:blank should have firstPartyDomain set to " + expectDomain
    );
  });

  win.close();
});

/**
 * For loading the initial about:blank in non-e10s mode, it will be loaded with
 * a null principal. So we test if it has correct firstPartyDomain set.
 */
add_task(async function test_nonremote_window_open_aboutBlank() {
  if (SpecialPowers.useRemoteSubframes) {
    ok(true, "We cannot test non-e10s mode in Fission. So, we skip this.");
    return;
  }

  let win = await BrowserTestUtils.openNewBrowserWindow({ remote: false });
  let browser = win.gBrowser.selectedBrowser;

  Assert.ok(!browser.isRemoteBrowser, "shouldn't be a remote browser");

  await SpecialPowers.spawn(browser, [], async function () {
    info("origin " + content.document.nodePrincipal.origin);

    Assert.ok(
      content.document.nodePrincipal.isNullPrincipal,
      "The principal of remote about:blank should be a NullPrincipal."
    );

    let str = content.document.nodePrincipal.originNoSuffix;
    let expectDomain =
      str.substring("moz-nullprincipal:{".length, str.length - 1) + ".mozilla";
    Assert.equal(
      content.document.nodePrincipal.originAttributes.firstPartyDomain,
      expectDomain,
      "non-remote about:blank should have firstPartyDomain set to " +
        expectDomain
    );
  });

  win.close();
});

/**
 * Check if data: URI inherits firstPartyDomain from about:blank correctly.
 */
add_task(async function test_remote_window_open_data_uri() {
  // allow top level data: URI navigations, otherwise
  // <a href="data:" would fail.
  await SpecialPowers.pushPrefEnv({
    set: [["security.data_uri.block_toplevel_data_uri_navigations", false]],
  });
  let win = await BrowserTestUtils.openNewBrowserWindow({ remote: true });
  let browser = win.gBrowser.selectedBrowser;

  await SpecialPowers.spawn(browser, [], () => {
    content.document.body.innerHTML = `
      <a href="data:text/plain,hello" id="test">hello</a>`;

    let element = content.document.getElementById("test");
    element.click();
  });

  await BrowserTestUtils.browserLoaded(browser, false, function (url) {
    return url == "data:text/plain,hello";
  });

  await SpecialPowers.spawn(browser, [], async function () {
    Assert.ok(true, "origin: " + content.document.nodePrincipal.origin);

    Assert.ok(
      content.document.nodePrincipal.isNullPrincipal,
      "The principal of data: document should be a NullPrincipal."
    );

    Assert.ok(
      content.document.nodePrincipal.originAttributes.firstPartyDomain != "",
      "data: URI should have firstPartyDomain set."
    );
  });

  win.close();
});

/**
 * data: document contains an iframe, and we test that iframe should inherit
 * origin attributes from the data: document.
 */
add_task(async function test_remote_window_open_data_uri2() {
  let win = await BrowserTestUtils.openNewBrowserWindow({ remote: true });
  let browser = win.gBrowser.selectedBrowser;
  const TEST_PAGE =
    "https://example.net/browser/browser/components/originattributes/test/browser/test2.html";

  // The iframe test2.html will fetch test2.js, which will have cookies.
  const DATA_URI = `data:text/html,
                    <iframe id="iframe1" src="${TEST_PAGE}"></iframe>`;
  BrowserTestUtils.loadURIString(browser, DATA_URI);
  await BrowserTestUtils.browserLoaded(browser, true, TEST_PAGE);

  await SpecialPowers.spawn(browser, [], async function () {
    Assert.ok(true, "origin " + content.document.nodePrincipal.origin);

    Assert.ok(
      content.document.nodePrincipal.isNullPrincipal,
      "The principal of data: document should be a NullPrincipal."
    );

    Assert.ok(
      content.document.nodePrincipal.originAttributes.firstPartyDomain != "",
      "data: URI should have firstPartyDomain set."
    );

    let iframe = content.document.getElementById("iframe1");
    await SpecialPowers.spawn(
      iframe,
      [content.document.nodePrincipal.originAttributes.firstPartyDomain],
      function (firstPartyDomain) {
        Assert.ok(
          true,
          "iframe principal: " + content.document.nodePrincipal.origin
        );

        Assert.equal(
          content.document.nodePrincipal.originAttributes.firstPartyDomain,
          firstPartyDomain,
          "iframe should inherit firstPartyDomain from parent document."
        );
        Assert.equal(
          content.document.cookie,
          "test2=foo",
          "iframe should have cookies"
        );
      }
    );
  });

  win.close();
});

/**
 * about: pages should have firstPartyDomain set when we enable first party isolation.
 */
add_task(async function test_aboutURL() {
  let aboutURLs = [];

  // List of about: URLs that will initiate network requests.
  let networkURLs = ["credits", "logins"];

  for (let cid in Cc) {
    let result = cid.match(
      /@mozilla.org\/network\/protocol\/about;1\?what\=(.*)$/
    );
    if (!result) {
      continue;
    }

    let aboutType = result[1];
    let contract = "@mozilla.org/network/protocol/about;1?what=" + aboutType;
    try {
      let am = Cc[contract].getService(Ci.nsIAboutModule);
      let uri = Services.io.newURI("about:" + aboutType);
      let flags = am.getURIFlags(uri);

      // We load pages with URI_SAFE_FOR_UNTRUSTED_CONTENT set, this means they
      // are not loaded with System Principal but with content principal.
      // Also we skip pages with HIDE_FROM_ABOUTABOUT, some of them may have
      // errors while loading.
      if (
        flags & Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT &&
        !(flags & Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT) &&
        !networkURLs.includes(aboutType) &&
        // handle about:newtab in browser_firstPartyIsolation_about_newtab.js
        aboutType !== "newtab" &&
        // protections kicks of async messaging as soon as it loads,
        // this test closes the tab too soon causing errors
        aboutType !== "protections"
      ) {
        aboutURLs.push(aboutType);
      }
    } catch (e) {
      // getService might have thrown if the component doesn't actually
      // implement nsIAboutModule
    }
  }

  for (let url of aboutURLs) {
    let tab = BrowserTestUtils.addTab(gBrowser, "about:" + url);
    await BrowserTestUtils.browserLoaded(tab.linkedBrowser);

    let attrs = {
      firstPartyDomain: "about.ef2a7dd5-93bc-417f-a698-142c3116864f.mozilla",
    };
    await SpecialPowers.spawn(
      tab.linkedBrowser,
      [{ attrs, url }],
      async function (args) {
        Assert.ok(
          true,
          "loading page about:" +
            args.url +
            ", origin is " +
            content.document.nodePrincipal.origin
        );
        Assert.ok(true, "principal " + content.document.nodePrincipal);
        Assert.equal(
          content.document.nodePrincipal.originAttributes.firstPartyDomain,
          args.attrs.firstPartyDomain,
          "The about page should have firstPartyDomain set"
        );
        Assert.ok(
          content.document.nodePrincipal.isContentPrincipal,
          "The principal should be a content principal."
        );
      }
    );

    gBrowser.removeTab(tab);
  }
});