summaryrefslogtreecommitdiffstats
path: root/docshell/test/browser/browser_bug1415918_beforeunload_options.js
blob: 5ce57cbb607ee02c44a68dd67914a6fdcacf85ff (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
/* Any copyright is dedicated to the Public Domain.
   http://creativecommons.org/publicdomain/zero/1.0/ */

const TEST_PATH = getRootDirectory(gTestPath).replace(
  "chrome://mochitests/content",
  "http://example.com"
);

SimpleTest.requestFlakyTimeout("Needs to test a timeout");

function delay(msec) {
  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  return new Promise(resolve => setTimeout(resolve, msec));
}

add_task(async function test() {
  await SpecialPowers.pushPrefEnv({
    set: [["dom.require_user_interaction_for_beforeunload", false]],
  });

  await SpecialPowers.pushPrefEnv({
    set: [["prompts.contentPromptSubDialog", false]],
  });

  const permitUnloadTimeout = Services.prefs.getIntPref(
    "dom.beforeunload_timeout_ms"
  );

  let url = TEST_PATH + "dummy_page.html";
  let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
  let browser = tab.linkedBrowser;

  await SpecialPowers.spawn(browser.browsingContext, [], () => {
    content.addEventListener("beforeunload", event => {
      event.preventDefault();
    });
  });

  let allowNavigation;
  let promptShown = false;
  let promptDismissed = false;
  let promptTimeout;

  const DIALOG_TOPIC = "tabmodal-dialog-loaded";
  async function observer(node) {
    promptShown = true;

    if (promptTimeout) {
      await delay(promptTimeout);
    }

    let button = node.querySelector(
      `.tabmodalprompt-button${allowNavigation ? 0 : 1}`
    );
    button.click();
    promptDismissed = true;
  }
  Services.obs.addObserver(observer, DIALOG_TOPIC);

  /*
   * Check condition where beforeunload handlers request a prompt.
   */

  // Prompt is shown, user clicks OK.
  allowNavigation = true;
  promptShown = false;

  ok(browser.permitUnload().permitUnload, "permit unload should be true");
  ok(promptShown, "prompt should have been displayed");

  // Prompt is shown, user clicks CANCEL.
  allowNavigation = false;
  promptShown = false;

  ok(!browser.permitUnload().permitUnload, "permit unload should be false");
  ok(promptShown, "prompt should have been displayed");

  // Prompt is not shown, don't permit unload.
  promptShown = false;
  ok(
    !browser.permitUnload("dontUnload").permitUnload,
    "permit unload should be false"
  );
  ok(!promptShown, "prompt should not have been displayed");

  // Prompt is not shown, permit unload.
  promptShown = false;
  ok(
    browser.permitUnload("unload").permitUnload,
    "permit unload should be true"
  );
  ok(!promptShown, "prompt should not have been displayed");

  promptShown = false;
  promptDismissed = false;
  promptTimeout = 3 * permitUnloadTimeout;
  let promise = browser.asyncPermitUnload();

  let promiseResolved = false;
  promise.then(() => {
    promiseResolved = true;
  });

  await TestUtils.waitForCondition(() => promptShown);
  ok(!promptDismissed, "Should not have dismissed prompt yet");
  ok(!promiseResolved, "Should not have resolved promise yet");

  await delay(permitUnloadTimeout * 1.5);

  ok(!promptDismissed, "Should not have dismissed prompt yet");
  ok(!promiseResolved, "Should not have resolved promise yet");

  let { permitUnload } = await promise;
  ok(promptDismissed, "Should have dismissed prompt");
  ok(!permitUnload, "Should not have permitted unload");

  promptTimeout = null;

  /*
   * Check condition where no one requests a prompt.  In all cases,
   * permitUnload should be true, and all handlers fired.
   */

  allowNavigation = true;

  url += "?1";
  BrowserTestUtils.loadURI(browser, url);
  await BrowserTestUtils.browserLoaded(browser, false, url);

  promptShown = false;
  ok(browser.permitUnload().permitUnload, "permit unload should be true");
  ok(!promptShown, "prompt should not have been displayed");

  promptShown = false;
  ok(
    browser.permitUnload("dontUnload").permitUnload,
    "permit unload should be true"
  );
  ok(!promptShown, "prompt should not have been displayed");

  promptShown = false;
  ok(
    browser.permitUnload("unload").permitUnload,
    "permit unload should be true"
  );
  ok(!promptShown, "prompt should not have been displayed");

  await BrowserTestUtils.removeTab(tab);

  Services.obs.removeObserver(observer, DIALOG_TOPIC);
});