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
  
     | 
    
      <!DOCTYPE html>
<meta charset="utf-8">
<title>Test the properties of a session history entry's document state</title>
<link rel="help" href="https://html.spec.whatwg.org/#document-state">
<script src="/common/dispatcher/dispatcher.js"></script>
<script src="/common/get-host-info.sub.js"></script>
<script src="/common/utils.js"></script>
<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script>
// In this test, we create an auxiliary window with a session history A -> B,
// where the document on site B is the current active document. Bf-cache is
// disabled via `Cache-Control: no-store` headers. We then `history.back()` to
// site A, and perform `location.replace(B)`. This makes the first document in
// the session history now same-origin/site with the URL in the subsequent
// session history entry's document state.
//
// We then perform `history.forward()` in the first document, which loads the
// second document (from network). We confirm that the resulting navigation
// request was made with the expected state, stored on the history entry's
// document state. The consequences of this are:
//  - The navigation is made with the `Sec-Fetch-Site: cross-site` header,
//    indicating that the *original* document state's initiator origin was
//    preserved
//  - The navigation is made with a cross-origin `Referer` header, indicating
//    that the *original* document state's referrer was preserved
//  - The resulting document has a cross-origin `document.referrer`, indicating
//    the same as above
promise_test(async t => {
  const rcHelper = new RemoteContextHelper();
  const A = await rcHelper.addWindow();
  // Create B on a new origin (with bf-cache disabled).
  const B = await A.navigateToNew({
    origin: 'HTTPS_NOTSAMESITE_ORIGIN',
    headers: [['Cache-Control', 'no-store']],
  });
  // This is the origin we're going to navigate A to, so that it becomes
  // same-origin with B.
  const originB = new URL(await B.executeScript(() => location.href)).origin;
  await B.historyBack();
  // Make A navigate to the same document but in origin B:
  const urlA = await A.executeScript(() => location.href);
  const originA = new URL(urlA).origin;
  assert_not_equals(originA, originB, 'Contexts A and B are cross-origin');
  // Load A's current document but on origin B.
  const newUrlOnOriginB = urlA.replace(originA, originB);
  await A.navigate((url) => {
    location.replace(url);
  }, [newUrlOnOriginB]);
  // Assert that A and B are now same-origin:
  const newUrlA = await A.executeScript(() => {
    return location.href;
  });
  // Now the session history looks like:
  // B -> B (initiator origin: A)
  assert_equals(new URL(newUrlA).origin, originB);
  // This means that when we navigate forward, we should request the second
  // document with the history entry's document state, which mostly preserves
  // parameters from the original initiator (a cross-site document), despite a
  // now-same-origin document initiating this navigation via history.
  await A.historyForward();
  const secFetchSite = await B.executeScript(() => window.requestHeaders['sec-fetch-site']);
  const referrer = await B.executeScript(() => window.requestHeaders['referer']);
  const documentReferrer = await B.executeScript(() => document.referrer);
  assert_equals(secFetchSite, 'cross-site',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' +
      'header');
  assert_equals(referrer, originA + '/',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site ends up with the Referer header that is the ' +
      'original cross-site initiator');
  assert_equals(documentReferrer, originA + '/',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site ends up with document.referrer that is the ' +
      'original cross-site initiator');
}, "A navigation's initiator origin and referrer are stored in the document " +
   "state and used in the document repopulation case");
// This test is similar to the above, but instead of testing for the true
// history entry -> document state -> document repopulation case, we stay on [B]
// (the document who was navigated to from [A]) and run `location.reload()` to
// confirm that the initiator information from the [A] -> [B] navigation is used
// when reloading [B], not [B]'s own same-origin information.
promise_test(async t => {
  const rcHelper = new RemoteContextHelper();
  const A = await rcHelper.addWindow();
  const originA = new URL(await A.executeScript(() => location.href)).origin;
  // Create B on a new origin.
  const B = await A.navigateToNew({
    origin: 'HTTPS_NOTSAMESITE_ORIGIN',
  });
  const originB = new URL(await B.executeScript(() => location.href)).origin;
  assert_not_equals(originA, originB, 'Contexts A and B are cross-origin');
  // Reload B.
  await B.navigate(() => {
    location.reload();
  }, []);
  const secFetchSite = await B.executeScript(() => window.requestHeaders['sec-fetch-site']);
  const referrer = await B.executeScript(() => window.requestHeaders['referer']);
  const documentReferrer = await B.executeScript(() => document.referrer);
  assert_equals(secFetchSite, 'cross-site',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' +
      'header');
  assert_equals(referrer, originA + '/',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site ends up with the Referer header that is the ' +
      'original cross-site initiator');
  assert_equals(documentReferrer, originA + '/',
      'Same-origin forward history navigation to a document whose original ' +
      'initiator was cross-site ends up with document.referrer that is the ' +
      'original cross-site initiator');
}, "A navigation's initiator origin and referrer are stored in the document " +
   "state and used on location.reload()");
</script>
</body>
 
     |