summaryrefslogtreecommitdiffstats
path: root/dom/events/test/test_focus_blur_on_click_in_deep_cross_origin_iframe.html
blob: f360ef7c20e442a3f02778c73e3bf3e248b1e485 (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
<!DOCTYPE html>
<meta charset="utf-8">
<title></title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<script src="/tests/SimpleTest/paint_listener.js"></script>
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_utils.js"></script>
<script src="/tests/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js"></script>
<iframe width=100 height=200 scrolling="no"></iframe>
<script>
let state = "start";

const scale = window.devicePixelRatio;

function getScreenPosition(aElement, aOffsetX, aOffsetY) {
  const rect = aElement.getBoundingClientRect();
  const x = aOffsetX + window.mozInnerScreenX + rect.left;
  const y = aOffsetY + window.mozInnerScreenY + rect.top;
  return [Math.round(x * scale), Math.round(y * scale)];
}

add_task(async () => {
  await SimpleTest.promiseFocus();

  const loadsPromise = new Promise((resolve, reject) => {
    let readyMiddle = false;
    let readyInner = false;
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (event.data == "middleready") {
        readyMiddle = true;
      } else if (event.data == "innerready") {
        readyInner = true;
      } else {
        reject("Unexpected message when waiting for ready " + event.data);
      }
      if (readyInner && readyMiddle) {
        state = "ready";
        window.removeEventListener("message", listener);
        resolve();
      }
    });
  });

  const iframe = document.querySelectorAll("iframe")[0];
  iframe.src = "https://example.com/tests/dom/events/test/file_focus_blur_on_click_in_deep_cross_origin_iframe_middle.html";

  await loadsPromise;

  // Wait for APZ state stable so that mouse event handling APZ works properly
  // in out-of-process iframes.
  await waitUntilApzStable();

  // NOTE: synthesizeMouseAtCenter doesn't work for OOP iframes (bug 1528935),
  // so we use promiseNativeMouseEventWithAPZ instead.
  const [expectedScreenX, expectedScreenY] =
    getScreenPosition(iframe, 10, 10);

  const firstClickPromise = new Promise((resolve, reject) => {
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (state == "ready") {
        if (event.data == "innerfocus") {
          state = "innerfocusbeforeclick";
        } else if (event.data == "innerclick") {
          ok(false, "Focusing failed to complete before mouseup");
          state = "innerclickbeforefocus";
        } else if (event.data == "middlefocus") {
          is(false, "Should not get an extra middlefocus.");
        } else {
          is(event.data, "neverthisevent", "Unexpected event (first click)");
        }
      } else if (state == "innerfocusbeforeclick") {
        is(event.data, "innerclick", "The second event should be 'innerclick'");
        state = "firstclick";
        window.removeEventListener("message", listener);
        resolve();
      } else if (state == "innerclickbeforefocus") {
        is(event.data, "innerfocus", "The second event should be 'innerfocus'");
        state = "firstclick";
        window.removeEventListener("message", listener);
        resolve();
     } else {
        reject("Unexpected message in firstClickPromise " + event.data);
      }
    });
  });

  await promiseNativeMouseEventWithAPZ({
    type: "click",
    target: iframe,
    screenX: expectedScreenX,
    screenY: expectedScreenY + Math.round(110 * scale),
  });

  await firstClickPromise;

  SimpleTest.requestFlakyTimeout("Waiting for unwanted events that don't exist on success.");

  const secondClickPromise = new Promise((resolve, reject) => {
    window.addEventListener("message", function listener(event) {
      info(`receive ${event.data}`);
      if (state == "firstclick") {
        is(event.data, "middlefocus", "The third event should be 'middlefocus'.");
        state = "middlefocusbeforeclick";
      } else if (state == "middlefocusbeforeclick") {
        // The order of blur and click is non-deterministic even in the non-Fission case.
        if (event.data == "middleclick") {
          state = "waitingforinnerblurafterclick";
        } else if (event.data == "innerblur") {
          state = "innerblurbeforeclick";
        } else {
          is(event.data, "neverthisevent", "Unexpected event (first click)");
        }
      } else if (state == "waitingforinnerblurafterclick") {
        is(event.data, "innerblur", "The fifth event should be 'innerblur'.");
        state = "secondclick";
        setTimeout(function() {
          // Wait for potential other unwanted events
          window.removeEventListener("message", listener);
          resolve()
        }, 200);
      } else if (state == "innerblurbeforeclick") {
        is(event.data, "middleclick", "The fifth event should be 'middleclick'.");
        state = "secondclick";
        setTimeout(function() {
          // Wait for potential other unwanted events
          window.removeEventListener("message", listener);
          resolve()
        }, 200);
      } else {
        reject("Unexpected message in secondClickPromise " + event.data);
      }
    });
  });

  await promiseNativeMouseEventWithAPZ({
    type: "click",
    target: iframe,
    screenX: expectedScreenX,
    screenY: expectedScreenY,
  });

  await secondClickPromise;
});
</script>