summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html
blob: 77602b2d4258c87a7ac055475986d691da8dad90 (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>
<title>Verify history.back() on a persisted page resumes timers</title>
<meta name="timeout" content="long">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script type="text/javascript">

function make_post_back_url(name) {
  return new URL('resources/post_name_on_load.html?name=' + name,
                 window.location).href;
}

function wait_for_message(name) {
  return new Promise(resolve => {
    addEventListener('message', function onMsg(evt) {
      if (evt.data !== name) {
        return;
      }
      removeEventListener('message', onMsg);
      resolve();
    });
  });
}

function with_window_by_name(name) {
  let win = window.open(make_post_back_url(name));
  return wait_for_message(name).then(_ => {
    return win;
  });
}

function with_nested_frame(win, url) {
  return new Promise(resolve => {
    let frame = win.document.createElement('iframe');
    frame.addEventListener('load', function onLoad(evt) {
      removeEventListener('load', onLoad);
      resolve(frame);
    });
    frame.src = url;
    win.document.body.appendChild(frame);
  });
}

function delay(win, delay) {
  return new Promise(resolve => {
    win.setTimeout(_ => {
      resolve(win);
    }, delay);
  });
}

function navigate_by_name(win, name) {
  win.location = make_post_back_url(name);
  return wait_for_message(name).then(_ => {
    return win;
  });
}

function go_back(win) {
  return new Promise(resolve => {
    win.onpagehide = e => resolve(win);
    win.history.back();
  });
}

let DELAY = 500;

promise_test(t => {
  // Create a new window so we can navigate it later.
  return with_window_by_name('foo').then(win => {
    // Schedule a timer within the new window.  Our intent is
    // to navigate the window before the timer fires.
    let delayFired = false;
    let innerDelay = delay(win, DELAY);
    innerDelay.then(_ => {
      delayFired = true;
    });

    return navigate_by_name(win, 'bar').then(_ => {
      // Since the window has navigated the timer should not
      // fire.  We set a timer on our current test window
      // to verify the other timer is not received.
      assert_false(delayFired);
      return delay(window, DELAY * 2);
    }).then(_ => {
      // The navigated window's timer should not have fired.
      assert_false(delayFired);
      // Now go back to the document that set the timer.
      return go_back(win);
    }).then(_ => {
      // We wait for one of two conditions here.  For browsers
      // with a bfcache the original suspended timer will fire.
      // Alternatively, if the browser reloads the page the original
      // message will be sent again.  Wait for either of these
      // two events.
      return Promise.race([wait_for_message('foo'), innerDelay]);
    }).then(_ => {
      win.close();
    });
  });
}, 'history.back() handles top level page timer correctly');

promise_test(t => {
  let win;
  // Create a new window so we can navigate it later.
  return with_window_by_name('foo').then(w => {
    win = w;

    // Create a nested frame so we check if navigation and history.back()
    // properly handle child window state.
    return with_nested_frame(win, 'about:blank');

  }).then(frame => {
    // Schedule a timer within the nested frame contained by the new window.
    // Our intent is to navigate the window before the timer fires.
    let delayFired = false;
    let innerDelay = delay(frame.contentWindow, DELAY);
    innerDelay.then(_ => {
      delayFired = true;
    });

    return navigate_by_name(win, 'bar').then(_ => {
      // Since the window has navigated the timer should not
      // fire.  We set a timer on our current test window
      // to verify the other timer is not received.
      assert_false(delayFired);
      return delay(window, DELAY * 2);
    }).then(_ => {
      // The navigated window's timer should not have fired.
      assert_false(delayFired);
      // Now go back to the document containing the frame that set the timer.
      return go_back(win);
    }).then(_ => {
      // We wait for one of two conditions here.  For browsers
      // with a bfcache the original suspended timer will fire.
      // Alternatively, if the browser reloads the page the original
      // message will be sent again.  Wait for either of these
      // two events.
      return Promise.race([wait_for_message('foo'), innerDelay]);
    }).then(_ => {
      win.close();
    });
  });
}, 'history.back() handles nested iframe timer correctly');

</script>