summaryrefslogtreecommitdiffstats
path: root/dom/security/test/sec-fetch/browser_navigation.js
blob: 642dcab76edcdc8142e19d90b934e2239fc6f2ef (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
"use strict";

const REQUEST_URL =
  "https://example.com/browser/dom/security/test/sec-fetch/file_no_cache.sjs";

let gTestCounter = 0;
let gExpectedHeader = {};

async function setup() {
  waitForExplicitFinish();
}

function checkSecFetchUser(subject, topic, data) {
  let channel = subject.QueryInterface(Ci.nsIHttpChannel);
  if (!channel.URI.spec.startsWith("https://example.com/")) {
    return;
  }

  info(`testing headers for load of ${channel.URI.spec}`);

  const secFetchHeaders = [
    "sec-fetch-mode",
    "sec-fetch-dest",
    "sec-fetch-user",
    "sec-fetch-site",
  ];

  secFetchHeaders.forEach(header => {
    const expectedValue = gExpectedHeader[header];
    try {
      is(
        channel.getRequestHeader(header),
        expectedValue,
        `${header} is set to ${expectedValue}`
      );
    } catch (e) {
      if (expectedValue) {
        ok(false, "required headers are set");
      } else {
        ok(true, `${header} should not be set`);
      }
    }
  });

  gTestCounter++;
}

async function testNavigations() {
  gTestCounter = 0;

  // Load initial site
  let loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  BrowserTestUtils.loadURIString(gBrowser, REQUEST_URL + "?test1");
  await loaded;

  // Load another site
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.document.notifyUserGestureActivation(); // simulate user activation
    let test2Button = content.document.getElementById("test2_button");
    test2Button.click();
    content.document.clearUserGestureActivation();
  });
  await loaded;
  // Load another site
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.document.notifyUserGestureActivation(); // simulate user activation
    let test3Button = content.document.getElementById("test3_button");
    test3Button.click();
    content.document.clearUserGestureActivation();
  });
  await loaded;

  gExpectedHeader = {
    "sec-fetch-mode": "navigate",
    "sec-fetch-dest": "document",
    "sec-fetch-site": "same-origin",
    "sec-fetch-user": "?1",
  };

  // Register the http request observer.
  // All following actions should cause requests with the sec-fetch-user header
  // set.
  Services.obs.addObserver(checkSecFetchUser, "http-on-stop-request");

  // Go back one site by clicking the back button
  info("Clicking back button");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  document.notifyUserGestureActivation(); // simulate user activation
  let backButton = document.getElementById("back-button");
  backButton.click();
  document.clearUserGestureActivation();
  await loaded;

  // Reload the site by clicking the reload button
  info("Clicking reload button");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  document.notifyUserGestureActivation(); // simulate user activation
  let reloadButton = document.getElementById("reload-button");
  await TestUtils.waitForCondition(() => {
    return !reloadButton.disabled;
  });
  reloadButton.click();
  document.clearUserGestureActivation();
  await loaded;

  // Go forward one site by clicking the forward button
  info("Clicking forward button");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  document.notifyUserGestureActivation(); // simulate user activation
  let forwardButton = document.getElementById("forward-button");
  forwardButton.click();
  document.clearUserGestureActivation();
  await loaded;

  // Testing history.back/forward...

  info("going back with history.back");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.document.notifyUserGestureActivation(); // simulate user activation
    content.history.back();
    content.document.clearUserGestureActivation();
  });
  await loaded;

  info("going forward with history.forward");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.document.notifyUserGestureActivation(); // simulate user activation
    content.history.forward();
    content.document.clearUserGestureActivation();
  });
  await loaded;

  gExpectedHeader = {
    "sec-fetch-mode": "navigate",
    "sec-fetch-dest": "document",
    "sec-fetch-site": "same-origin",
  };

  info("going back with history.back without user activation");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.history.back();
  });
  await loaded;

  info("going forward with history.forward without user activation");
  loaded = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
  await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () {
    content.history.forward();
  });
  await loaded;

  ok(gTestCounter === 7, "testing that all five actions have been tested.");

  Services.obs.removeObserver(checkSecFetchUser, "http-on-stop-request");
}

add_task(async function () {
  waitForExplicitFinish();

  await testNavigations();

  // If fission is enabled we also want to test the navigations with the bfcache
  // in the parent.
  if (SpecialPowers.getBoolPref("fission.autostart")) {
    await SpecialPowers.pushPrefEnv({
      set: [["fission.bfcacheInParent", true]],
    });

    await testNavigations();
  }

  finish();
});