document-state.https.html (6160B)
1 <!DOCTYPE html> 2 <meta charset="utf-8"> 3 <title>Test the properties of a session history entry's document state</title> 4 <link rel="help" href="https://html.spec.whatwg.org/#document-state"> 5 <script src="/common/dispatcher/dispatcher.js"></script> 6 <script src="/common/get-host-info.sub.js"></script> 7 <script src="/common/utils.js"></script> 8 <script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script> 9 <script src="/resources/testharness.js"></script> 10 <script src="/resources/testharnessreport.js"></script> 11 12 <body> 13 <script> 14 // In this test, we create an auxiliary window with a session history A -> B, 15 // where the document on site B is the current active document. Bf-cache is 16 // disabled via `Cache-Control: no-store` headers. We then `history.back()` to 17 // site A, and perform `location.replace(B)`. This makes the first document in 18 // the session history now same-origin/site with the URL in the subsequent 19 // session history entry's document state. 20 // 21 // We then perform `history.forward()` in the first document, which loads the 22 // second document (from network). We confirm that the resulting navigation 23 // request was made with the expected state, stored on the history entry's 24 // document state. The consequences of this are: 25 // - The navigation is made with the `Sec-Fetch-Site: cross-site` header, 26 // indicating that the *original* document state's initiator origin was 27 // preserved 28 // - The navigation is made with a cross-origin `Referer` header, indicating 29 // that the *original* document state's referrer was preserved 30 // - The resulting document has a cross-origin `document.referrer`, indicating 31 // the same as above 32 promise_test(async t => { 33 const rcHelper = new RemoteContextHelper(); 34 const A = await rcHelper.addWindow(); 35 36 // Create B on a new origin (with bf-cache disabled). 37 const B = await A.navigateToNew({ 38 origin: 'HTTPS_NOTSAMESITE_ORIGIN', 39 headers: [['Cache-Control', 'no-store']], 40 }); 41 42 // This is the origin we're going to navigate A to, so that it becomes 43 // same-origin with B. 44 const originB = new URL(await B.executeScript(() => location.href)).origin; 45 await B.historyBack(); 46 47 // Make A navigate to the same document but in origin B: 48 const urlA = await A.executeScript(() => location.href); 49 const originA = new URL(urlA).origin; 50 assert_not_equals(originA, originB, 'Contexts A and B are cross-origin'); 51 52 // Load A's current document but on origin B. 53 const newUrlOnOriginB = urlA.replace(originA, originB); 54 await A.navigate((url) => { 55 location.replace(url); 56 }, [newUrlOnOriginB]); 57 58 // Assert that A and B are now same-origin: 59 const newUrlA = await A.executeScript(() => { 60 return location.href; 61 }); 62 63 // Now the session history looks like: 64 // B -> B (initiator origin: A) 65 assert_equals(new URL(newUrlA).origin, originB); 66 67 // This means that when we navigate forward, we should request the second 68 // document with the history entry's document state, which mostly preserves 69 // parameters from the original initiator (a cross-site document), despite a 70 // now-same-origin document initiating this navigation via history. 71 await A.historyForward(); 72 73 const requestHeaders = await B.getRequestHeaders(); 74 const documentReferrer = await B.executeScript(() => document.referrer); 75 76 assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site', 77 'Same-origin forward history navigation to a document whose original ' + 78 'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' + 79 'header'); 80 assert_equals(requestHeaders.get('referer'), originA + '/', 81 'Same-origin forward history navigation to a document whose original ' + 82 'initiator was cross-site ends up with the Referer header that is the ' + 83 'original cross-site initiator'); 84 assert_equals(documentReferrer, originA + '/', 85 'Same-origin forward history navigation to a document whose original ' + 86 'initiator was cross-site ends up with document.referrer that is the ' + 87 'original cross-site initiator'); 88 }, "A navigation's initiator origin and referrer are stored in the document " + 89 "state and used in the document repopulation case"); 90 91 // This test is similar to the above, but instead of testing for the true 92 // history entry -> document state -> document repopulation case, we stay on [B] 93 // (the document who was navigated to from [A]) and run `location.reload()` to 94 // confirm that the initiator information from the [A] -> [B] navigation is used 95 // when reloading [B], not [B]'s own same-origin information. 96 promise_test(async t => { 97 const rcHelper = new RemoteContextHelper(); 98 const A = await rcHelper.addWindow(); 99 100 const originA = new URL(await A.executeScript(() => location.href)).origin; 101 102 // Create B on a new origin. 103 const B = await A.navigateToNew({ 104 origin: 'HTTPS_NOTSAMESITE_ORIGIN', 105 }); 106 107 const originB = new URL(await B.executeScript(() => location.href)).origin; 108 assert_not_equals(originA, originB, 'Contexts A and B are cross-origin'); 109 110 // Reload B. 111 await B.navigate(() => { 112 location.reload(); 113 }, []); 114 115 const requestHeaders = await B.getRequestHeaders(); 116 const documentReferrer = await B.executeScript(() => document.referrer); 117 118 assert_equals(requestHeaders.get('sec-fetch-site'), 'cross-site', 119 'Same-origin forward history navigation to a document whose original ' + 120 'initiator was cross-site, ends up with Sec-Fetch-Dest: cross-site ' + 121 'header'); 122 assert_equals(requestHeaders.get('referer'), originA + '/', 123 'Same-origin forward history navigation to a document whose original ' + 124 'initiator was cross-site ends up with the Referer header that is the ' + 125 'original cross-site initiator'); 126 assert_equals(documentReferrer, originA + '/', 127 'Same-origin forward history navigation to a document whose original ' + 128 'initiator was cross-site ends up with document.referrer that is the ' + 129 'original cross-site initiator'); 130 }, "A navigation's initiator origin and referrer are stored in the document " + 131 "state and used on location.reload()"); 132 </script> 133 </body>