michael@0: // Test for bug 343515 - Need API for tabbrowsers to tell docshells they're visible/hidden michael@0: michael@0: // Globals michael@0: var testPath = "http://mochi.test:8888/browser/docshell/test/navigation/"; michael@0: var ctx = {}; michael@0: michael@0: // Helper function to check if a window is active michael@0: function isActive(aWindow) { michael@0: var docshell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIWebNavigation) michael@0: .QueryInterface(Ci.nsIDocShell); michael@0: return docshell.isActive; michael@0: } michael@0: michael@0: // We need to wait until the page from each testcase is fully loaded, michael@0: // including all of its descendant iframes. To do that we manually count michael@0: // how many load events should happen on that page (one for the toplevel doc michael@0: // and one for each subframe) and wait until we receive the expected number michael@0: // of events. michael@0: function nShotsListener(aElem, aType, aCallback, aCount) { michael@0: let count = aCount; michael@0: aElem.addEventListener(aType, function listenerCallback() { michael@0: if (--count == 0) { michael@0: aElem.removeEventListener(aType, listenerCallback, true); michael@0: michael@0: // aCallback is executed asynchronously, which is handy because load michael@0: // events fire before mIsDocumentLoaded is actually set to true. :( michael@0: executeSoon(aCallback); michael@0: } michael@0: }, true); michael@0: } michael@0: michael@0: function oneShotListener(aElem, aType, aCallback) { michael@0: nShotsListener(aElem, aType, aCallback, 1); michael@0: } michael@0: michael@0: // Entry point from Mochikit michael@0: function test() { michael@0: michael@0: // Lots of callbacks going on here michael@0: waitForExplicitFinish(); michael@0: michael@0: // Begin the test michael@0: step1(); michael@0: } michael@0: michael@0: function step1() { michael@0: michael@0: // Get a handle on the initial tab michael@0: ctx.tab0 = gBrowser.selectedTab; michael@0: ctx.tab0Browser = gBrowser.getBrowserForTab(ctx.tab0); michael@0: ctx.tab0Window = ctx.tab0Browser.contentWindow; michael@0: michael@0: // Our current tab should be active michael@0: ok(isActive(ctx.tab0Window), "Tab 0 should be active at test start"); michael@0: michael@0: // Open a New Tab michael@0: ctx.tab1 = gBrowser.addTab(testPath + "bug343515_pg1.html"); michael@0: ctx.tab1Browser = gBrowser.getBrowserForTab(ctx.tab1); michael@0: ctx.tab1Window = ctx.tab1Browser.contentWindow; michael@0: oneShotListener(ctx.tab1Browser, "load", step2); michael@0: } michael@0: michael@0: function step2() { michael@0: is(testPath + "bug343515_pg1.html", ctx.tab1Browser.currentURI.spec, michael@0: "Got expected tab 1 url in step 2"); michael@0: michael@0: // Our current tab should still be active michael@0: ok(isActive(ctx.tab0Window), "Tab 0 should still be active"); michael@0: ok(!isActive(ctx.tab1Window), "Tab 1 should not be active"); michael@0: michael@0: // Switch to tab 1 michael@0: gBrowser.selectedTab = ctx.tab1; michael@0: michael@0: // Tab 1 should now be active michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(isActive(ctx.tab1Window), "Tab 1 should be active"); michael@0: michael@0: // Open another tab michael@0: ctx.tab2 = gBrowser.addTab(testPath + "bug343515_pg2.html"); michael@0: ctx.tab2Browser = gBrowser.getBrowserForTab(ctx.tab2); michael@0: ctx.tab2Window = ctx.tab2Browser.contentWindow; michael@0: michael@0: // bug343515_pg2.html consists of a page with two iframes, michael@0: // which will therefore generate 3 load events. michael@0: nShotsListener(ctx.tab2Browser, "load", step3, 3); michael@0: } michael@0: michael@0: function step3() { michael@0: is(testPath + "bug343515_pg2.html", ctx.tab2Browser.currentURI.spec, michael@0: "Got expected tab 2 url in step 3"); michael@0: michael@0: // Tab 0 should be inactive, Tab 1 should be active michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(isActive(ctx.tab1Window), "Tab 1 should be active"); michael@0: michael@0: // Tab 2's window _and_ its iframes should be inactive michael@0: ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); michael@0: is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); michael@0: for (var i = 0; i < ctx.tab2Window.frames.length; i++) michael@0: info("step 3, frame " + i + " info: " + ctx.tab2Window.frames[i].location); michael@0: ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); michael@0: michael@0: // Navigate tab 2 to a different page michael@0: ctx.tab2Window.location = testPath + "bug343515_pg3.html"; michael@0: michael@0: // bug343515_pg3.html consists of a page with two iframes, one of which michael@0: // contains another iframe, so there'll be a total of 4 load events michael@0: nShotsListener(ctx.tab2Browser, "load", step4, 4); michael@0: } michael@0: michael@0: function step4() { michael@0: is(testPath + "bug343515_pg3.html", ctx.tab2Browser.currentURI.spec, michael@0: "Got expected tab 2 url in step 4"); michael@0: michael@0: // Tab 0 should be inactive, Tab 1 should be active michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(isActive(ctx.tab1Window), "Tab 1 should be active"); michael@0: michael@0: // Tab2 and all descendants should be inactive michael@0: ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); michael@0: is(ctx.tab2Window.frames.length, 2, "Tab 2 should have 2 iframes"); michael@0: for (var i = 0; i < ctx.tab2Window.frames.length; i++) michael@0: info("step 4, frame " + i + " info: " + ctx.tab2Window.frames[i].location); michael@0: is(ctx.tab2Window.frames[0].frames.length, 1, "Tab 2 iframe 0 should have 1 iframes"); michael@0: ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); michael@0: michael@0: // Switch to Tab 2 michael@0: gBrowser.selectedTab = ctx.tab2; michael@0: michael@0: // Check everything michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); michael@0: ok(isActive(ctx.tab2Window), "Tab 2 should be active"); michael@0: ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); michael@0: ok(isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be active"); michael@0: ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); michael@0: michael@0: // Go back michael@0: oneShotListener(ctx.tab2Browser, "pageshow", step5); michael@0: ctx.tab2Browser.goBack(); michael@0: michael@0: } michael@0: michael@0: function step5() { michael@0: // Check everything michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(!isActive(ctx.tab1Window), "Tab 1 should be inactive"); michael@0: ok(isActive(ctx.tab2Window), "Tab 2 should be active"); michael@0: ok(isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be active"); michael@0: ok(isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be active"); michael@0: michael@0: // Switch to tab 1 michael@0: gBrowser.selectedTab = ctx.tab1; michael@0: michael@0: // Navigate to page 3 michael@0: ctx.tab1Window.location = testPath + "bug343515_pg3.html"; michael@0: michael@0: // bug343515_pg3.html consists of a page with two iframes, one of which michael@0: // contains another iframe, so there'll be a total of 4 load events michael@0: nShotsListener(ctx.tab1Browser, "load", step6, 4); michael@0: } michael@0: michael@0: function step6() { michael@0: michael@0: // Check everything michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(isActive(ctx.tab1Window), "Tab 1 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); michael@0: ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); michael@0: michael@0: // Go forward on tab 2 michael@0: oneShotListener(ctx.tab2Browser, "pageshow", step7); michael@0: var tab2docshell = ctx.tab2Window.QueryInterface(Ci.nsIInterfaceRequestor) michael@0: .getInterface(Ci.nsIWebNavigation); michael@0: tab2docshell.goForward(); michael@0: } michael@0: michael@0: function step7() { michael@0: michael@0: ctx.tab2Window = ctx.tab2Browser.contentWindow; michael@0: michael@0: // Check everything michael@0: ok(!isActive(ctx.tab0Window), "Tab 0 should be inactive"); michael@0: ok(isActive(ctx.tab1Window), "Tab 1 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[0]), "Tab1 iframe 0 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[0].frames[0]), "Tab1 iframe 0 subiframe 0 should be active"); michael@0: ok(isActive(ctx.tab1Window.frames[1]), "Tab1 iframe 1 should be active"); michael@0: ok(!isActive(ctx.tab2Window), "Tab 2 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[0]), "Tab2 iframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[0].frames[0]), "Tab2 iframe 0 subiframe 0 should be inactive"); michael@0: ok(!isActive(ctx.tab2Window.frames[1]), "Tab2 iframe 1 should be inactive"); michael@0: michael@0: // That's probably enough michael@0: allDone(); michael@0: } michael@0: michael@0: function allDone() { michael@0: michael@0: // Close the tabs we made michael@0: gBrowser.removeTab(ctx.tab1); michael@0: gBrowser.removeTab(ctx.tab2); michael@0: michael@0: // Tell the framework we're done michael@0: finish(); michael@0: }