Bug 1366870 - Part 1: Add test for about: pages' initial tab titles. r?dao draft
authorChris Peterson <cpeterson@mozilla.com>
Mon, 29 May 2017 14:58:57 -0700
changeset 592161 8b8f8990a8e0dbe22e290bbb15788b1e89e07fff
parent 592129 8a990794c2ee923ccd839750912d10ff3a690a2a
child 592162 048c093aa259ec76a9a7d5b2e36c5b7cc0fdc62f
push id63304
push usercpeterson@mozilla.com
push dateSat, 10 Jun 2017 23:20:00 +0000
reviewersdao
bugs1366870, 1364127, 1371896
milestone55.0a1
Bug 1366870 - Part 1: Add test for about: pages' initial tab titles. r?dao This test case documents the current behavior of about: pages's initial tab titles. 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. This test case uses the about:robots page because its title is not localized, which makes testing easier. MozReview-Commit-ID: JGaRciaZUEC
browser/base/content/tabbrowser.xml
browser/components/sessionstore/test/browser_tab_label_during_restore.js
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1428,34 +1428,59 @@
           }
           this._tabAttrModified(tab, ["sharing"]);
 
           if (aBrowser == this.mCurrentBrowser)
             gIdentityHandler.updateSharingIndicator();
         ]]></body>
       </method>
 
-
       <!-- TODO: remove after 57, once we know add-ons can no longer use it. -->
       <method name="setTabTitleLoading">
         <parameter name="aTab"/>
         <body/>
       </method>
 
       <method name="setInitialTabTitle">
         <parameter name="aTab"/>
         <parameter name="aTitle"/>
         <parameter name="aOptions"/>
         <body><![CDATA[
-          if (aTitle) {
+          // If we don't have the content title yet, aTitle is a URI. Set its hostname
+          // as the label so that the tab isn't empty while the content is loading.
+          const label = aOptions && aOptions.isContentTitle
+                        ? aTitle
+                        : getHostnameWithoutWWW(aTitle, this.mURIFixup);
+
+          if (label) {
             // Don't replace the set label with the empty tab label or the URL
             // while the tab is loading.
             aTab._suppressTransientPlaceholderLabel = true;
 
-            this._setTabLabel(aTab, aTitle, aOptions);
+            this._setTabLabel(aTab, label, aOptions);
+          }
+
+          function getHostnameWithoutWWW(uri, URIFixup) {
+            // about: pages don't have hostnames, so we can bail early here.
+            if (uri.startsWith("about:")) {
+              return uri;
+            }
+
+            // Some tests pass in values that are not valid URLs, such as
+            // "example.com" with no scheme. Just show whatever was passed in
+            // until we know the page's actual title.
+            let hostname;
+            try {
+              const fixedURI = URIFixup.createFixupURI(uri, URIFixup.FIXUP_FLAG_NONE);
+              hostname = fixedURI.host;
+            } catch (e) {
+              return uri;
+            }
+
+            return hostname.startsWith("www.") ? hostname.slice(4) : hostname;
           }
         ]]></body>
       </method>
 
       <method name="setTabTitle">
         <parameter name="aTab"/>
         <body>
           <![CDATA[
@@ -2388,17 +2413,17 @@
             }
 
             var uriIsAboutBlank = aURI == "about:blank";
 
             if (!aNoInitialLabel) {
               if (isBlankPageURL(aURI)) {
                 t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle"));
               } else {
-                // Set URL as label so that the tab isn't empty initially.
+                // Set hostname as label so that the tab isn't empty initially.
                 this.setInitialTabTitle(t, aURI, { beforeTabOpen: true });
               }
             }
 
             if (aIsPrerendered) {
               t.setAttribute("hidden", "true");
             }
 
--- a/browser/components/sessionstore/test/browser_tab_label_during_restore.js
+++ b/browser/components/sessionstore/test/browser_tab_label_during_restore.js
@@ -1,24 +1,29 @@
 /* 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 TEST_URL = "http://example.com/";
+  const TEST_URL = "http://www.example.com/";
+  const ABOUT_ROBOTS_URI = "about:robots";
+  const ABOUT_ROBOTS_TITLE = "Gort! Klaatu barada nikto!";
 
   function observeLabelChanges(tab) {
     info("observing tab label changes. initial label: " + tab.label);
     let labelChangeCount = 0;
     function TabAttrModifiedListener(event) {
       if (event.detail.changed.some(attr => { return attr == "label" })) {
         info("tab label change: " + tab.label);
         labelChangeCount++;
@@ -32,58 +37,78 @@ add_task(async function() {
   }
 
   info("setting test browser state");
   let browserLoadedPromise = BrowserTestUtils.firstBrowserLoaded(window, false);
   await promiseBrowserState({
     windows: [{
       tabs: [
         { entries: [{ url: TEST_URL }] },
+        { entries: [{ url: ABOUT_ROBOTS_URI }] },
         { entries: [{ url: TEST_URL }] },
       ]
     }]
   });
-  let [firstTab, secondTab] = gBrowser.tabs;
+  let [firstTab, secondTab, thirdTab] = gBrowser.tabs;
   is(gBrowser.selectedTab, firstTab, "first tab is selected");
 
   await browserLoadedPromise;
   const CONTENT_TITLE = firstTab.linkedBrowser.contentTitle;
   is(firstTab.linkedBrowser.currentURI.spec, TEST_URL, "correct URL loaded in first tab");
   is(typeof CONTENT_TITLE, "string", "content title is a string");
   isnot(CONTENT_TITLE.length, 0, "content title isn't empty");
   isnot(CONTENT_TITLE, TEST_URL, "content title is different from the URL");
   is(firstTab.label, CONTENT_TITLE, "first tab displays content title");
   ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
   ok(secondTab.hasAttribute("pending"), "second tab is pending");
-  is(secondTab.label, TEST_URL, "second tab displays URL as its title");
+  // 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.
+  is(secondTab.label, ABOUT_ROBOTS_URI, "second tab displays URI as its initial title");
+  ok(thirdTab.hasAttribute("pending"), "third tab is pending");
+  is(thirdTab.label, "example.com", "third tab's initial tab title is its hostname without 'www.'");
 
   info("selecting the second tab");
   let checkLabelChangeCount = observeLabelChanges(secondTab);
-  browserLoadedPromise = BrowserTestUtils.browserLoaded(secondTab.linkedBrowser, false, TEST_URL);
+  browserLoadedPromise = BrowserTestUtils.browserLoaded(secondTab.linkedBrowser, false, ABOUT_ROBOTS_URI);
   gBrowser.selectedTab = secondTab;
   await browserLoadedPromise;
   ok(!secondTab.hasAttribute("pending"), "second tab isn't pending anymore");
-  is(secondTab.label, CONTENT_TITLE, "second tab displays content title");
+  is(secondTab.label, ABOUT_ROBOTS_TITLE, "second tab displays content title");
+  ok(document.title.startsWith(ABOUT_ROBOTS_TITLE), "title bar displays content title");
+  checkLabelChangeCount(1); // ABOUT_ROBOTS_URI -> ABOUT_ROBOTS_TITLE
+
+  info("selecting the third tab");
+  checkLabelChangeCount = observeLabelChanges(thirdTab);
+  browserLoadedPromise = BrowserTestUtils.browserLoaded(thirdTab.linkedBrowser, false, TEST_URL);
+  gBrowser.selectedTab = thirdTab;
+  await browserLoadedPromise;
+  ok(!thirdTab.hasAttribute("pending"), "third tab isn't pending anymore");
+  is(thirdTab.label, CONTENT_TITLE, "third tab displays content title");
   ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
-  checkLabelChangeCount(1);
+  checkLabelChangeCount(1); // TEST_URL -> CONTENT_TITLE
 
   info("restoring the modified browser state");
   await TabStateFlusher.flushWindow(window);
   await promiseBrowserState(SessionStore.getBrowserState());
-  [firstTab, secondTab] = gBrowser.tabs;
-  is(secondTab, gBrowser.selectedTab, "second tab is selected after restoring");
+  [firstTab, secondTab, thirdTab] = gBrowser.tabs;
+  is(thirdTab, gBrowser.selectedTab, "third tab is selected after restoring");
   ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
   ok(firstTab.hasAttribute("pending"), "first tab is pending after restoring");
   is(firstTab.label, CONTENT_TITLE, "first tab displays content title in pending state");
+  ok(secondTab.hasAttribute("pending"), "second tab is pending after restoring");
+  is(secondTab.label, ABOUT_ROBOTS_TITLE, "second tab displays content title");
+  ok(!thirdTab.hasAttribute("pending"), "third tab is not pending after restoring");
+  is(thirdTab.label, CONTENT_TITLE, "third tab displays content title in pending state");
 
   info("selecting the first tab");
   checkLabelChangeCount = observeLabelChanges(firstTab);
   let tabContentRestored = TestUtils.topicObserved("sessionstore-debug-tab-restored");
   gBrowser.selectedTab = firstTab;
   ok(document.title.startsWith(CONTENT_TITLE), "title bar displays content title");
   await tabContentRestored;
   ok(!firstTab.hasAttribute("pending"), "first tab isn't pending anymore");
   checkLabelChangeCount(0);
   is(firstTab.label, CONTENT_TITLE, "first tab displays content title after restoring content");
 
   await promiseBrowserState(BACKUP_STATE);
 });
-