Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden |
michael@0 | 2 | |
michael@0 | 3 | // Globals |
michael@0 | 4 | var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/"; |
michael@0 | 5 | var ctx = {}; |
michael@0 | 6 | |
michael@0 | 7 | // Helper function to check if a window is active |
michael@0 | 8 | function isActive(aWindow) { |
michael@0 | 9 | var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 10 | .getInterface(Ci.nsIWebNavigation) |
michael@0 | 11 | .QueryInterface(Ci.nsIDocShell); |
michael@0 | 12 | return docshell.isActive; |
michael@0 | 13 | } |
michael@0 | 14 | |
michael@0 | 15 | // We need to wait until the page from each testcase is fully loaded, |
michael@0 | 16 | // including all of its descendant iframes. To do that we manually count |
michael@0 | 17 | // how many load events should happen on that page (one for the toplevel doc |
michael@0 | 18 | // and one for each subframe) and wait until we receive the expected number |
michael@0 | 19 | // of events. |
michael@0 | 20 | function nShotsListener(aElem, aType, aCallback, aCount) { |
michael@0 | 21 | let count = aCount; |
michael@0 | 22 | aElem.addEventListener(aType, function listenerCallback() { |
michael@0 | 23 | if (--count == 0) { |
michael@0 | 24 | aElem.removeEventListener(aType, listenerCallback, true); |
michael@0 | 25 | |
michael@0 | 26 | // aCallback is executed asynchronously, which is handy because load |
michael@0 | 27 | // events fire before mIsDocumentLoaded is actually set to true. :( |
michael@0 | 28 | executeSoon(aCallback); |
michael@0 | 29 | } |
michael@0 | 30 | }, true); |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | function oneShotListener(aElem, aType, aCallback) { |
michael@0 | 34 | nShotsListener(aElem, aType, aCallback, 1); |
michael@0 | 35 | } |
michael@0 | 36 | |
michael@0 | 37 | // Entry point from Mochikit |
michael@0 | 38 | function test() { |
michael@0 | 39 | |
michael@0 | 40 | // Lots of callbacks going on here |
michael@0 | 41 | waitForExplicitFinish(); |
michael@0 | 42 | |
michael@0 | 43 | // Begin the test |
michael@0 | 44 | step1(); |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | function step1() { |
michael@0 | 48 | |
michael@0 | 49 | // Get a handle on the initial tab |
michael@0 | 50 | ctx.tab0 = gBrowser.selectedTab; |
michael@0 | 51 | ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0); |
michael@0 | 52 | ctx.tab0Window = ctx.tab0Browser.contentWindow; |
michael@0 | 53 | |
michael@0 | 54 | // Our current tab should be active |
michael@0 | 55 | ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start"); |
michael@0 | 56 | |
michael@0 | 57 | // Open a New Tab |
michael@0 | 58 | ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html"); |
michael@0 | 59 | ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1); |
michael@0 | 60 | ctx.tab1Window = ctx.tab1Browser.contentWindow; |
michael@0 | 61 | oneShotListener(ctx.tab1Browser, "load", step2); |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | function step2() { |
michael@0 | 65 | is(testPath + "bug343515_pg1.html", ctx.tab1Browser.currentURI.spec, |
michael@0 | 66 | "Got expected tab 1 url in step 2"); |
michael@0 | 67 | |
michael@0 | 68 | // Our current tab should still be active |
michael@0 | 69 | ok(isActive(ctx.tab0Window), "Tab 0 should still be active"); |
michael@0 | 70 | ok(!isActive(ctx.tab1Window), "Tab 1 should not be active"); |
michael@0 | 71 | |
michael@0 | 72 | // Switch to tab 1 |
michael@0 | 73 | gBrowser.selectedTab = ctx.tab1; |
michael@0 | 74 | |
michael@0 | 75 | // Tab 1 should now be active |
michael@0 | 76 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 77 | ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
michael@0 | 78 | |
michael@0 | 79 | // Open another tab |
michael@0 | 80 | ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html"); |
michael@0 | 81 | ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2); |
michael@0 | 82 | ctx.tab2Window = ctx.tab2Browser.contentWindow; |
michael@0 | 83 | |
michael@0 | 84 | // bug343515_pg2.html consists of a page with two iframes, |
michael@0 | 85 | // which will therefore generate 3 load events. |
michael@0 | 86 | nShotsListener(ctx.tab2Browser, "load", step3, 3); |
michael@0 | 87 | } |
michael@0 | 88 | |
michael@0 | 89 | function step3() { |
michael@0 | 90 | is(testPath + "bug343515_pg2.html", ctx.tab2Browser.currentURI.spec, |
michael@0 | 91 | "Got expected tab 2 url in step 3"); |
michael@0 | 92 | |
michael@0 | 93 | // Tab 0 should be inactive, Tab 1 should be active |
michael@0 | 94 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 95 | ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
michael@0 | 96 | |
michael@0 | 97 | // Tab 2's window _and_ its iframes should be inactive |
michael@0 | 98 | ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
michael@0 | 99 | is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); |
michael@0 | 100 | for (var i = 0; i < ctx.tab2Window.frames.length; i++) |
michael@0 | 101 | info("step 3, frame " + i + " info: " + ctx.tab2Window.frames[i].location); |
michael@0 | 102 | ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
michael@0 | 103 | ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
michael@0 | 104 | |
michael@0 | 105 | // Navigate tab 2 to a different page |
michael@0 | 106 | ctx.tab2Window.location = testPath + "bug343515_pg3.html"; |
michael@0 | 107 | |
michael@0 | 108 | // bug343515_pg3.html consists of a page with two iframes, one of which |
michael@0 | 109 | // contains another iframe, so there'll be a total of 4 load events |
michael@0 | 110 | nShotsListener(ctx.tab2Browser, "load", step4, 4); |
michael@0 | 111 | } |
michael@0 | 112 | |
michael@0 | 113 | function step4() { |
michael@0 | 114 | is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec, |
michael@0 | 115 | "Got expected tab 2 url in step 4"); |
michael@0 | 116 | |
michael@0 | 117 | // Tab 0 should be inactive, Tab 1 should be active |
michael@0 | 118 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 119 | ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
michael@0 | 120 | |
michael@0 | 121 | // Tab2 and all descendants should be inactive |
michael@0 | 122 | ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
michael@0 | 123 | is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); |
michael@0 | 124 | for (var i = 0; i < ctx.tab2Window.frames.length; i++) |
michael@0 | 125 | info("step 4, frame " + i + " info: " + ctx.tab2Window.frames[i].location); |
michael@0 | 126 | is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes"); |
michael@0 | 127 | ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
michael@0 | 128 | ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); |
michael@0 | 129 | ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
michael@0 | 130 | |
michael@0 | 131 | // Switch to Tab 2 |
michael@0 | 132 | gBrowser.selectedTab = ctx.tab2; |
michael@0 | 133 | |
michael@0 | 134 | // Check everything |
michael@0 | 135 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 136 | ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); |
michael@0 | 137 | ok(isActive(ctx.tab2Window), "Tab 2 should be active"); |
michael@0 | 138 | ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); |
michael@0 | 139 | ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active"); |
michael@0 | 140 | ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); |
michael@0 | 141 | |
michael@0 | 142 | // Go back |
michael@0 | 143 | oneShotListener(ctx.tab2Browser, "pageshow", step5); |
michael@0 | 144 | ctx.tab2Browser.goBack(); |
michael@0 | 145 | |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | function step5() { |
michael@0 | 149 | // Check everything |
michael@0 | 150 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 151 | ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); |
michael@0 | 152 | ok(isActive(ctx.tab2Window), "Tab 2 should be active"); |
michael@0 | 153 | ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); |
michael@0 | 154 | ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); |
michael@0 | 155 | |
michael@0 | 156 | // Switch to tab 1 |
michael@0 | 157 | gBrowser.selectedTab = ctx.tab1; |
michael@0 | 158 | |
michael@0 | 159 | // Navigate to page 3 |
michael@0 | 160 | ctx.tab1Window.location = testPath + "bug343515_pg3.html"; |
michael@0 | 161 | |
michael@0 | 162 | // bug343515_pg3.html consists of a page with two iframes, one of which |
michael@0 | 163 | // contains another iframe, so there'll be a total of 4 load events |
michael@0 | 164 | nShotsListener(ctx.tab1Browser, "load", step6, 4); |
michael@0 | 165 | } |
michael@0 | 166 | |
michael@0 | 167 | function step6() { |
michael@0 | 168 | |
michael@0 | 169 | // Check everything |
michael@0 | 170 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 171 | ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
michael@0 | 172 | ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); |
michael@0 | 173 | ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); |
michael@0 | 174 | ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); |
michael@0 | 175 | ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
michael@0 | 176 | ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
michael@0 | 177 | ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
michael@0 | 178 | |
michael@0 | 179 | // Go forward on tab 2 |
michael@0 | 180 | oneShotListener(ctx.tab2Browser, "pageshow", step7); |
michael@0 | 181 | var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor) |
michael@0 | 182 | .getInterface(Ci.nsIWebNavigation); |
michael@0 | 183 | tab2docshell.goForward(); |
michael@0 | 184 | } |
michael@0 | 185 | |
michael@0 | 186 | function step7() { |
michael@0 | 187 | |
michael@0 | 188 | ctx.tab2Window = ctx.tab2Browser.contentWindow; |
michael@0 | 189 | |
michael@0 | 190 | // Check everything |
michael@0 | 191 | ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); |
michael@0 | 192 | ok(isActive(ctx.tab1Window), "Tab 1 should be active"); |
michael@0 | 193 | ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); |
michael@0 | 194 | ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); |
michael@0 | 195 | ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); |
michael@0 | 196 | ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); |
michael@0 | 197 | ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); |
michael@0 | 198 | ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); |
michael@0 | 199 | ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); |
michael@0 | 200 | |
michael@0 | 201 | // That's probably enough |
michael@0 | 202 | allDone(); |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | function allDone() { |
michael@0 | 206 | |
michael@0 | 207 | // Close the tabs we made |
michael@0 | 208 | gBrowser.removeTab(ctx.tab1); |
michael@0 | 209 | gBrowser.removeTab(ctx.tab2); |
michael@0 | 210 | |
michael@0 | 211 | // Tell the framework we're done |
michael@0 | 212 | finish(); |
michael@0 | 213 | } |