summaryrefslogtreecommitdiffstats
path: root/dom/security/test/https-first/browser_beforeunload_permit_http.js
blob: dda5fbbba9d00afd08096adca0a849bbf2a16b51 (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
"use strict";

const { PromptTestUtils } = ChromeUtils.importESModule(
  "resource://testing-common/PromptTestUtils.sys.mjs"
);

const TEST_PATH_HTTP = getRootDirectory(gTestPath).replace(
  "chrome://mochitests/content",
  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
  "http://nocert.example.com/"
);
/*
 * Description of Tests:
 *
 * Test load page and reload:
 * 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
 * 2. Open an HTTP site. HTTPS-First will try to upgrade it to https - but since it has no cert that try will fail
 * 3. Then simulated user interaction and reload the page with a reload flag.
 * 4. That should lead to a beforeUnload prompt that asks for users permission to perform reload. HTTPS-First should not try to upgrade the reload again
 *
 * Test Navigation:
 * 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
 * 2. Open an http site. HTTPS-First will try to upgrade it to https - but since it has no cert for https that try will fail
 * 3. Then simulated user interaction and navigate to another http page. Again HTTPS-First will try to upgrade to HTTPS
 * 4. This attempted navigation leads to a prompt which askes for permission to leave page - accept it
 * 5. Since the site is not using a valid HTTPS cert HTTPS-First will downgrade the request back to HTTP
 * 6. User should NOT get asked again for permission to unload
 *
 * Test Session History Navigation:
 * 1. Enable HTTPS-First and the pref to trigger beforeunload by user interaction
 * 2. Open an http site. HTTPS-First will try to upgrade it to https - but since it has no cert for https that try will fail
 * 3. Then navigate to another http page and simulated a user interaction.
 * 4. Trigger a session history navigation by clicking the "back button".
 * 5. This attempted navigation leads to a prompt which askes for permission to leave page - accept it
 */
add_setup(async function () {
  await SpecialPowers.pushPrefEnv({
    set: [
      ["dom.security.https_first", true],
      ["dom.require_user_interaction_for_beforeunload", true],
    ],
  });
});
const TESTS = [
  {
    name: "Normal Reload (No flag)",
    reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_NONE,
  },
  {
    name: "Bypass Cache Reload",
    reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE,
  },
  {
    name: "Bypass Proxy Reload",
    reloadFlag: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY,
  },
  {
    name: "Bypass Cache and Proxy Reload",
    reloadFlag:
      Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE |
      Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY,
  },
];

add_task(async function testReloadFlags() {
  for (let index = 0; index < TESTS.length; index++) {
    const testCase = TESTS[index];
    // The onbeforeunload dialog should appear
    let dialogPromise = PromptTestUtils.waitForPrompt(null, {
      modalType: Services.prompt.MODAL_TYPE_CONTENT,
      promptType: "confirmEx",
    });
    let reloadPromise = loadPageAndReload(testCase);
    let dialog = await dialogPromise;
    Assert.ok(true, "Showed the beforeunload dialog.");
    await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
    await reloadPromise;
  }
});

add_task(async function testNavigation() {
  // The onbeforeunload dialog should appear
  let dialogPromise = PromptTestUtils.waitForPrompt(null, {
    modalType: Services.prompt.MODAL_TYPE_CONTENT,
    promptType: "confirmEx",
  });

  let openPagePromise = openPage();
  let dialog = await dialogPromise;
  Assert.ok(true, "Showed the beforeunload dialog.");
  await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
  await openPagePromise;
});

add_task(async function testSessionHistoryNavigation() {
  // The onbeforeunload dialog should appear
  let dialogPromise = PromptTestUtils.waitForPrompt(null, {
    modalType: Services.prompt.MODAL_TYPE_CONTENT,
    promptType: "confirmEx",
  });

  let openPagePromise = loadPagesAndUseBackButton();
  let dialog = await dialogPromise;
  Assert.ok(true, "Showed the beforeunload dialog.");
  await PromptTestUtils.handlePrompt(dialog, { buttonNumClick: 0 });
  await openPagePromise;
});

async function openPage() {
  // Open about:blank in a new tab
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: "about:blank" },
    async function (browser) {
      // Load http page
      BrowserTestUtils.loadURIString(
        browser,
        `${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
      );
      await BrowserTestUtils.browserLoaded(browser);
      // Interact with page such that unload permit will be necessary
      await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);
      let hasInteractedWith = await SpecialPowers.spawn(
        browser,
        [""],
        function () {
          return content.document.userHasInteracted;
        }
      );

      is(true, hasInteractedWith, "Simulated successfully user interaction");
      // And then navigate away to another site which proves that user won't be asked twice to permit a reload (otherwise the test get timed out)
      BrowserTestUtils.loadURIString(
        browser,
        // eslint-disable-next-line @microsoft/sdl/no-insecure-url
        "http://self-signed.example.com/"
      );
      await BrowserTestUtils.browserLoaded(browser);
      Assert.ok(true, "Navigated successfully.");
    }
  );
}

async function loadPageAndReload(testCase) {
  // Load initial site
  // Open about:blank in a new tab
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: "about:blank" },
    async function (browser) {
      BrowserTestUtils.loadURIString(
        browser,
        `${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
      );
      await BrowserTestUtils.browserLoaded(browser);
      // Interact with page such that unload permit will be necessary
      await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);

      let hasInteractedWith = await SpecialPowers.spawn(
        browser,
        [""],
        function () {
          return content.document.userHasInteracted;
        }
      );
      is(true, hasInteractedWith, "Simulated successfully user interaction");
      BrowserReloadWithFlags(testCase.reloadFlag);
      await BrowserTestUtils.browserLoaded(browser);
      is(true, true, `reload with flag ${testCase.name} was successful`);
    }
  );
}

async function loadPagesAndUseBackButton() {
  // Load initial site
  // Open about:blank in a new tab
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: "about:blank" },
    async function (browser) {
      BrowserTestUtils.loadURIString(
        browser,
        `${TEST_PATH_HTTP}file_beforeunload_permit_http.html`
      );
      await BrowserTestUtils.browserLoaded(browser);

      BrowserTestUtils.loadURIString(
        browser,
        `${TEST_PATH_HTTP}file_beforeunload_permit_http.html?getASessionHistoryEntry`
      );
      await BrowserTestUtils.browserLoaded(browser);
      // Interact with page such that unload permit will be necessary
      await BrowserTestUtils.synthesizeMouse("body", 2, 2, {}, browser);

      let hasInteractedWith = await SpecialPowers.spawn(
        browser,
        [""],
        function () {
          return content.document.userHasInteracted;
        }
      );
      is(true, hasInteractedWith, "Simulated successfully user interaction");
      // Go back one site by clicking the back button
      info("Clicking back button");
      let backButton = document.getElementById("back-button");
      backButton.click();
      await BrowserTestUtils.browserLoaded(browser);
      is(true, true, `Got back successful`);
    }
  );
}