summaryrefslogtreecommitdiffstats
path: root/dom/base/test/fullscreen/browser_fullscreen-contextmenu-esc.js
blob: e89409a90f097c4c457c7d9102c8ce3eeb69418b (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
"use strict";

// This test tends to trigger a race in the fullscreen time telemetry,
// where the fullscreen enter and fullscreen exit events (which use the
// same histogram ID) overlap. That causes TelemetryStopwatch to log an
// error.
SimpleTest.ignoreAllUncaughtExceptions(true);

function captureUnexpectedFullscreenChange() {
  ok(false, "Caught an unexpected fullscreen change");
}

const kPage =
  "https://example.org/browser/dom/base/test/fullscreen/dummy_page.html";

function waitForDocActivated(aBrowser) {
  return SpecialPowers.spawn(aBrowser, [], () => {
    return ContentTaskUtils.waitForCondition(
      () => content.browsingContext.isActive && content.document.hasFocus()
    );
  });
}

add_task(async function () {
  await pushPrefs(
    ["full-screen-api.transition-duration.enter", "0 0"],
    ["full-screen-api.transition-duration.leave", "0 0"]
  );

  let tab = await BrowserTestUtils.openNewForegroundTab({
    gBrowser,
    opening: kPage,
    waitForStateStop: true,
  });
  let browser = tab.linkedBrowser;

  // As requestFullscreen checks the active state of the docshell,
  // wait for the document to be activated, just to be sure that
  // the fullscreen request won't be denied.
  await SpecialPowers.spawn(browser, [], () => {
    return ContentTaskUtils.waitForCondition(
      () => content.browsingContext.isActive && content.document.hasFocus()
    );
  });

  let contextMenu = document.getElementById("contentAreaContextMenu");
  ok(contextMenu, "Got context menu");

  let state;
  info("Enter DOM fullscreen");
  let fullScreenChangedPromise = BrowserTestUtils.waitForContentEvent(
    browser,
    "fullscreenchange"
  );
  await SpecialPowers.spawn(browser, [], () => {
    content.document.body.requestFullscreen();
  });

  await fullScreenChangedPromise;
  state = await SpecialPowers.spawn(browser, [], () => {
    return !!content.document.fullscreenElement;
  });
  ok(state, "The content should have entered fullscreen");
  ok(document.fullscreenElement, "The chrome should also be in fullscreen");

  let removeContentEventListener = BrowserTestUtils.addContentEventListener(
    browser,
    "fullscreenchange",
    captureUnexpectedFullscreenChange
  );

  info("Open context menu");
  is(contextMenu.state, "closed", "Should not have opened context menu");

  let popupShownPromise = promiseWaitForEvent(window, "popupshown");

  EventUtils.synthesizeMouse(
    browser,
    screen.width / 2,
    screen.height / 2,
    { type: "contextmenu", button: 2 },
    window
  );
  await popupShownPromise;
  is(contextMenu.state, "open", "Should have opened context menu");

  let popupHidePromise = promiseWaitForEvent(window, "popuphidden");

  if (
    !AppConstants.platform == "macosx" ||
    !Services.prefs.getBoolPref("widget.macos.native-context-menus", false)
  ) {
    info("Send the first escape");
    EventUtils.synthesizeKey("KEY_Escape");
  } else {
    // We cannot synthesize key events at native macOS menus.
    // We also do not see key events that are processed by native macOS menus,
    // so we cannot accidentally exit fullscreen when the user closes a native
    // menu with Escape.
    // Close the menu normally.
    info("Close the context menu");
    contextMenu.hidePopup();
  }
  await popupHidePromise;
  is(contextMenu.state, "closed", "Should have closed context menu");

  // Wait a small time to confirm that the first ESC key
  // does not exit fullscreen.
  // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
  await new Promise(resolve => setTimeout(resolve, 1000));
  state = await SpecialPowers.spawn(browser, [], () => {
    return !!content.document.fullscreenElement;
  });
  ok(state, "The content should still be in fullscreen");
  ok(document.fullscreenElement, "The chrome should still be in fullscreen");

  removeContentEventListener();
  info("Send the second escape");
  let fullscreenExitPromise = BrowserTestUtils.waitForContentEvent(
    browser,
    "fullscreenchange"
  );
  EventUtils.synthesizeKey("KEY_Escape");
  await fullscreenExitPromise;
  ok(!document.fullscreenElement, "The chrome should have exited fullscreen");

  gBrowser.removeTab(tab);
});