/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ "use strict"; /** * Test that we don't do unnecessary tab label changes while restoring a tab. */ add_task(async function () { await SpecialPowers.pushPrefEnv({ set: [ ["browser.sessionstore.restore_on_demand", true], ["browser.sessionstore.restore_tabs_lazily", true], ], }); const BACKUP_STATE = SessionStore.getBrowserState(); const REMOTE_URL = "http://www.example.com/"; const ABOUT_ROBOTS_URI = "about:robots"; const ABOUT_ROBOTS_TITLE = "Gort! Klaatu barada nikto!"; const NO_TITLE_URL = "data:text/plain,foo"; const EMPTY_TAB_TITLE = gBrowser.tabContainer.emptyTabTitle; function observeLabelChanges(tab, expectedLabels) { let seenLabels = [tab.label]; function TabAttrModifiedListener(event) { if (event.detail.changed.some(attr => attr == "label")) { seenLabels.push(tab.label); } } tab.addEventListener("TabAttrModified", TabAttrModifiedListener); return async () => { await BrowserTestUtils.waitForCondition( () => seenLabels.length == expectedLabels.length, "saw " + seenLabels.length + " TabAttrModified events" ); tab.removeEventListener("TabAttrModified", TabAttrModifiedListener); is( JSON.stringify(seenLabels), JSON.stringify(expectedLabels || []), "observed tab label changes" ); }; } info("setting test browser state"); let browserLoadedPromise = BrowserTestUtils.firstBrowserLoaded(window, false); await promiseBrowserState({ windows: [ { tabs: [ { entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] }, { entries: [{ url: ABOUT_ROBOTS_URI, triggeringPrincipal_base64 }] }, { entries: [{ url: REMOTE_URL, triggeringPrincipal_base64 }] }, { entries: [{ url: NO_TITLE_URL, triggeringPrincipal_base64 }] }, { entries: [{ url: "about:blank", triggeringPrincipal_base64 }] }, ], }, ], }); let [tab1, tab2, tab3, tab4, tab5] = gBrowser.tabs; is(gBrowser.selectedTab, tab1, "first tab is selected"); await browserLoadedPromise; const REMOTE_TITLE = tab1.linkedBrowser.contentTitle; is( tab1.linkedBrowser.currentURI.spec, REMOTE_URL, "correct URL loaded in first tab" ); is(typeof REMOTE_TITLE, "string", "content title is a string"); isnot(REMOTE_TITLE.length, 0, "content title isn't empty"); isnot(REMOTE_TITLE, REMOTE_URL, "content title is different from the URL"); is(tab1.label, REMOTE_TITLE, "first tab displays content title"); ok( document.title.startsWith(REMOTE_TITLE), "title bar displays content title" ); ok(tab2.hasAttribute("pending"), "second tab is pending"); ok(tab3.hasAttribute("pending"), "third tab is pending"); ok(tab4.hasAttribute("pending"), "fourth tab is pending"); is(tab5.label, EMPTY_TAB_TITLE, "fifth tab dislpays empty tab title"); info("selecting the second tab"); // The fix for bug 1364127 caused about: pages' initial tab titles to show // their about: URIs until their actual page titles are known, e.g. // "about:addons" -> "Add-ons Manager". This is bug 1371896. Previously, // about: pages' initial tab titles were blank until the page title was known. let finishObservingLabelChanges = observeLabelChanges(tab2, [ ABOUT_ROBOTS_URI, ABOUT_ROBOTS_TITLE, ]); browserLoadedPromise = BrowserTestUtils.browserLoaded( tab2.linkedBrowser, false, ABOUT_ROBOTS_URI ); gBrowser.selectedTab = tab2; await browserLoadedPromise; ok(!tab2.hasAttribute("pending"), "second tab isn't pending anymore"); await finishObservingLabelChanges(); ok( document.title.startsWith(ABOUT_ROBOTS_TITLE), "title bar displays content title" ); info("selecting the third tab"); finishObservingLabelChanges = observeLabelChanges(tab3, [ "example.com/", REMOTE_TITLE, ]); browserLoadedPromise = BrowserTestUtils.browserLoaded( tab3.linkedBrowser, false, REMOTE_URL ); gBrowser.selectedTab = tab3; await browserLoadedPromise; ok(!tab3.hasAttribute("pending"), "third tab isn't pending anymore"); await finishObservingLabelChanges(); ok( document.title.startsWith(REMOTE_TITLE), "title bar displays content title" ); info("selecting the fourth tab"); finishObservingLabelChanges = observeLabelChanges(tab4, [NO_TITLE_URL]); browserLoadedPromise = BrowserTestUtils.browserLoaded( tab4.linkedBrowser, false, NO_TITLE_URL ); gBrowser.selectedTab = tab4; await browserLoadedPromise; ok(!tab4.hasAttribute("pending"), "fourth tab isn't pending anymore"); await finishObservingLabelChanges(); is( document.title, document.getElementById("bundle_brand").getString("brandFullName"), "title bar doesn't display content title since page doesn't have one" ); info("restoring the modified browser state"); gBrowser.selectedTab = tab3; await TabStateFlusher.flushWindow(window); await promiseBrowserState(SessionStore.getBrowserState()); [tab1, tab2, tab3, tab4, tab5] = gBrowser.tabs; is(tab3, gBrowser.selectedTab, "third tab is selected after restoring"); ok( document.title.startsWith(REMOTE_TITLE), "title bar displays content title" ); ok(tab1.hasAttribute("pending"), "first tab is pending after restoring"); ok(tab2.hasAttribute("pending"), "second tab is pending after restoring"); is(tab2.label, ABOUT_ROBOTS_TITLE, "second tab displays content title"); ok(!tab3.hasAttribute("pending"), "third tab is not pending after restoring"); is( tab3.label, REMOTE_TITLE, "third tab displays content title in pending state" ); ok(tab4.hasAttribute("pending"), "fourth tab is pending after restoring"); is(tab4.label, NO_TITLE_URL, "fourth tab displays URL"); is(tab5.label, EMPTY_TAB_TITLE, "fifth tab still displays empty tab title"); info("selecting the first tab"); finishObservingLabelChanges = observeLabelChanges(tab1, [REMOTE_TITLE]); let tabContentRestored = TestUtils.topicObserved( "sessionstore-debug-tab-restored" ); gBrowser.selectedTab = tab1; ok( document.title.startsWith(REMOTE_TITLE), "title bar displays content title" ); await tabContentRestored; ok(!tab1.hasAttribute("pending"), "first tab isn't pending anymore"); await finishObservingLabelChanges(); await promiseBrowserState(BACKUP_STATE); });