browser_bug670318.js (4393B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 /** 5 * Test for Bug 670318 6 * 7 * When LoadEntry() is called on a browser that has multiple duplicate history 8 * entries, history.index can end up out of range (>= history.count). 9 */ 10 11 const URL = 12 "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html"; 13 14 async function LegacySHTest(browser) { 15 await ContentTask.spawn(browser, URL, async function (URL) { 16 let history = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory; 17 let count = 0; 18 19 let testDone = {}; 20 testDone.promise = new Promise(resolve => { 21 testDone.resolve = resolve; 22 }); 23 24 // Since listener implements nsISupportsWeakReference, we are 25 // responsible for keeping it alive so that the GC doesn't clear 26 // it before the test completes. We do this by anchoring the listener 27 // to the message manager, and clearing it just before the test 28 // completes. 29 this._testListener = { 30 owner: this, 31 OnHistoryNewEntry(aNewURI) { 32 info("OnHistoryNewEntry " + aNewURI.spec + ", " + count); 33 if (aNewURI.spec == URL && 5 == ++count) { 34 addEventListener( 35 "load", 36 function onLoad() { 37 Assert.less( 38 history.index, 39 history.count, 40 "history.index is valid" 41 ); 42 testDone.resolve(); 43 }, 44 { capture: true, once: true } 45 ); 46 47 history.legacySHistory.removeSHistoryListener( 48 this.owner._testListener 49 ); 50 delete this.owner._testListener; 51 this.owner = null; 52 content.setTimeout(() => { 53 content.location.reload(); 54 }, 0); 55 } 56 }, 57 58 OnHistoryReload: () => true, 59 OnHistoryGotoIndex: () => {}, 60 OnHistoryPurge: () => {}, 61 OnHistoryReplaceEntry: () => { 62 // The initial load of about:blank causes a transient entry to be 63 // created, so our first navigation to a real page is a replace 64 // instead of a new entry. 65 ++count; 66 }, 67 68 QueryInterface: ChromeUtils.generateQI([ 69 "nsISHistoryListener", 70 "nsISupportsWeakReference", 71 ]), 72 }; 73 74 history.legacySHistory.addSHistoryListener(this._testListener); 75 content.location = URL; 76 77 await testDone.promise; 78 }); 79 } 80 81 async function SHIPTest(browser) { 82 let history = browser.browsingContext.sessionHistory; 83 let count = 0; 84 85 let testDone = {}; 86 testDone.promise = new Promise(resolve => { 87 testDone.resolve = resolve; 88 }); 89 90 let listener = { 91 async OnHistoryNewEntry(aNewURI) { 92 if (aNewURI.spec == URL && 5 == ++count) { 93 history.removeSHistoryListener(listener); 94 await ContentTask.spawn(browser, null, () => { 95 return new Promise(resolve => { 96 addEventListener( 97 "load", 98 () => { 99 let history = docShell.QueryInterface( 100 Ci.nsIWebNavigation 101 ).sessionHistory; 102 Assert.less( 103 history.index, 104 history.count, 105 "history.index is valid" 106 ); 107 resolve(); 108 }, 109 { capture: true, once: true } 110 ); 111 112 content.location.reload(); 113 }); 114 }); 115 testDone.resolve(); 116 } 117 }, 118 119 OnHistoryReload: () => true, 120 OnHistoryGotoIndex: () => {}, 121 OnHistoryPurge: () => {}, 122 OnHistoryReplaceEntry: () => { 123 // The initial load of about:blank causes a transient entry to be 124 // created, so our first navigation to a real page is a replace 125 // instead of a new entry. 126 ++count; 127 // XXX I think this will be notified once |URL|, i.e. file_bug670318.html loads. 128 // this is probably not desired. 129 }, 130 131 QueryInterface: ChromeUtils.generateQI([ 132 "nsISHistoryListener", 133 "nsISupportsWeakReference", 134 ]), 135 }; 136 137 history.addSHistoryListener(listener); 138 BrowserTestUtils.startLoadingURIString(browser, URL); 139 140 await testDone.promise; 141 } 142 143 add_task(async function test() { 144 const task = SpecialPowers.Services.appinfo.sessionHistoryInParent 145 ? SHIPTest 146 : LegacySHTest; 147 await BrowserTestUtils.withNewTab({ gBrowser, url: "about:blank" }, task); 148 });