diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml
index 3ef4ffd08714..402a55860682 100644
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1217,11 +1217,6 @@
var uriIsBlankPage = !aURI || isBlankPageURL(aURI);
var uriIsNotAboutBlank = aURI && aURI != "about:blank";
- if (uriIsBlankPage)
- t.setAttribute("label", this.mStringBundle.getString("tabs.emptyTabTitle"));
- else
- t.setAttribute("label", aURI);
-
t.setAttribute("crop", "end");
t.setAttribute("validate", "never");
t.setAttribute("onerror", "this.removeAttribute('image');");
@@ -1327,6 +1322,14 @@
// initialized by this point.
this.mPanelContainer.appendChild(notificationbox);
+ // Happens after the browser is in the DOM: the TabTitleAbridger
+ // classifies tabs by domains, requiring access to the browser.
+ if (uriIsBlankPage) {
+ t.label = this.mStringBundle.getString("tabs.emptyTabTitle");
+ } else {
+ t.label = aURI;
+ }
+
this.tabContainer.updateVisibility();
if (uriIsNotAboutBlank) {
@@ -2819,8 +2822,7 @@
this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
var tab = this.firstChild;
- tab.setAttribute("label",
- this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle"));
+ tab.label = this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle");
tab.setAttribute("crop", "end");
tab.setAttribute("validate", "never");
tab.setAttribute("onerror", "this.removeAttribute('image');");
@@ -3843,7 +3845,8 @@
class="tab-icon-image"
role="presentation"/>
+
+
+ return this.getAttribute("label");
+
+
+ this.setAttribute("label", val);
+ let event = new CustomEvent("TabLabelModified", {
+ bubbles: true,
+ cancelable: true
+ });
+ this.dispatchEvent(event);
+
+ if (!event.defaultPrevented)
+ this.visibleLabel = val;
+
+
+
+
+ return this.getAttribute("visibleLabel");
+
+
+ this.setAttribute("visibleLabel", val);
+
+
return this.getAttribute("pinned") == "true";
diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in
index fc33a728e357..e83ceb3cb501 100644
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -134,6 +134,7 @@ _BROWSER_FILES = \
browser_bug581242.js \
browser_bug581253.js \
browser_bug581947.js \
+ browser_bug583890_label.js \
browser_bug585785.js \
browser_bug585830.js \
browser_bug590206.js \
diff --git a/browser/base/content/test/browser_bug583890_label.js b/browser/base/content/test/browser_bug583890_label.js
new file mode 100644
index 000000000000..edbe3bf793fa
--- /dev/null
+++ b/browser/base/content/test/browser_bug583890_label.js
@@ -0,0 +1,88 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/* Tests:
+ * verify that the visibleLabel attribute works
+ * verify the TabLabelModified event works
+ */
+
+function test() {
+ waitForExplicitFinish();
+ let tab = gBrowser.addTab("about:newtab",
+ {skipAnimation: true});
+ tab.linkedBrowser.addEventListener("load", function onLoad(event) {
+ event.currentTarget.removeEventListener("load", onLoad, true);
+ gBrowser.selectedTab = tab;
+ executeSoon(afterLoad);
+ }, true);
+ tab.addEventListener("TabLabelModified", handleInTest, true);
+}
+
+// Prevent interference
+function handleInTest(aEvent) {
+ aEvent.preventDefault();
+ aEvent.stopPropagation();
+ aEvent.target.visibleLabel = aEvent.target.label;
+}
+
+function afterLoad() {
+ let tab = gBrowser.selectedTab;
+ let xulLabel = document.getAnonymousElementByAttribute(tab, "anonid",
+ "tab-label");
+ // Verify we're starting out on the right foot
+ is(tab.label, "New Tab", "Initial tab label is default");
+ is(xulLabel.value, "New Tab", "Label element is default");
+ is(tab.visibleLabel, "New Tab", "visibleLabel is default");
+
+ // Check that a normal label setting works correctly
+ tab.label = "Hello, world!";
+ is(tab.label, "Hello, world!", "tab label attribute set via tab.label");
+ is(xulLabel.value, "Hello, world!", "xul:label set via tab.label");
+ is(tab.visibleLabel, "Hello, world!", "visibleLabel set via tab.label");
+
+ // Check that setting visibleLabel only affects the label element
+ tab.visibleLabel = "Goodnight, Irene";
+ is(tab.label, "Hello, world!", "Tab.label unaffected by visibleLabel setter");
+ is(xulLabel.value, "Goodnight, Irene",
+ "xul:label set by visibleLabel setter");
+ is(tab.visibleLabel, "Goodnight, Irene",
+ "visibleLabel attribute set by visibleLabel setter");
+
+ // Check that setting the label property hits everything
+ tab.label = "One more label";
+ is(tab.label, "One more label",
+ "Tab label set via label property after diverging from visibleLabel");
+ is(xulLabel.value, "One more label",
+ "xul:label set via label property after diverging from visibleLabel");
+ is(tab.visibleLabel, "One more label",
+ "visibleLabel set from label property after diverging from visibleLabel");
+
+ tab.removeEventListener("TabLabelModified", handleInTest, true);
+ tab.addEventListener("TabLabelModified", handleTabLabel, true);
+ tab.label = "This won't be the visibleLabel";
+}
+
+function handleTabLabel(aEvent) {
+ aEvent.target.removeEventListener("TabLabelModified", handleTabLabel, true);
+ aEvent.preventDefault();
+ aEvent.stopPropagation();
+ aEvent.target.visibleLabel = "Handler set this as the visible label";
+ executeSoon(checkTabLabelModified);
+}
+
+function checkTabLabelModified() {
+ let tab = gBrowser.selectedTab;
+ let xulLabel = document.getAnonymousElementByAttribute(tab, "anonid",
+ "tab-label");
+
+ is(tab.label, "This won't be the visibleLabel",
+ "Tab label set via label property that triggered event");
+ is(xulLabel.value, "Handler set this as the visible label",
+ "xul:label set by TabLabelModified handler");
+ is(tab.visibleLabel, "Handler set this as the visible label",
+ "visibleLabel set by TabLabelModified handler");
+
+ gBrowser.removeCurrentTab({animate: false});
+ finish();
+}
+