2007-08-21 21:58:49 -07:00
|
|
|
<?xml version="1.0"?>
|
|
|
|
|
2012-05-21 04:12:37 -07:00
|
|
|
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
2007-08-21 21:58:49 -07:00
|
|
|
|
|
|
|
<!DOCTYPE bindings [
|
2007-08-22 14:02:02 -07:00
|
|
|
<!ENTITY % tabBrowserDTD SYSTEM "chrome://browser/locale/tabbrowser.dtd" >
|
2007-08-21 21:58:49 -07:00
|
|
|
%tabBrowserDTD;
|
|
|
|
]>
|
|
|
|
|
2013-08-02 16:30:19 -07:00
|
|
|
# MAKE_E10S_WORK surrounds code needed to have the front-end try to be smart
|
|
|
|
# about using non-remote browsers for loading certain URIs when remote tabs
|
|
|
|
# (browser.tabs.remote) are enabled.
|
|
|
|
#define MAKE_E10S_WORK 1
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<bindings id="tabBrowserBindings"
|
|
|
|
xmlns="http://www.mozilla.org/xbl"
|
|
|
|
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
|
|
|
xmlns:xbl="http://www.mozilla.org/xbl">
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<binding id="tabbrowser">
|
|
|
|
<resources>
|
2008-01-14 19:04:37 -08:00
|
|
|
<stylesheet src="chrome://browser/content/tabbrowser.css"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
</resources>
|
|
|
|
|
|
|
|
<content>
|
2007-08-22 14:02:02 -07:00
|
|
|
<xul:stringbundle anonid="tbstringbundle" src="chrome://browser/locale/tabbrowser.properties"/>
|
2010-03-16 23:36:13 -07:00
|
|
|
<xul:tabbox anonid="tabbox" class="tabbrowser-tabbox"
|
|
|
|
flex="1" eventnode="document" xbl:inherits="handleCtrlPageUpDown"
|
2010-02-25 23:58:46 -08:00
|
|
|
onselect="if (event.target.localName == 'tabpanels') this.parentNode.updateCurrentBrowser();">
|
2007-08-21 22:01:04 -07:00
|
|
|
<xul:tabpanels flex="1" class="plain" selectedIndex="0" anonid="panelcontainer">
|
2007-08-21 22:01:12 -07:00
|
|
|
<xul:notificationbox flex="1">
|
2012-08-30 03:23:26 -07:00
|
|
|
<xul:hbox flex="1" class="browserSidebarContainer">
|
|
|
|
<xul:vbox flex="1" class="browserContainer">
|
2013-04-30 22:27:59 -07:00
|
|
|
<xul:stack flex="1" class="browserStack" anonid="browserStack">
|
2013-10-17 08:38:59 -07:00
|
|
|
<xul:browser anonid="initialBrowser" type="content-primary" message="true"
|
2013-08-25 18:34:23 -07:00
|
|
|
xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup,selectpopup"/>
|
2013-04-28 20:14:52 -07:00
|
|
|
</xul:stack>
|
2012-08-30 03:23:26 -07:00
|
|
|
</xul:vbox>
|
|
|
|
</xul:hbox>
|
2007-08-21 22:01:12 -07:00
|
|
|
</xul:notificationbox>
|
2007-08-21 21:58:49 -07:00
|
|
|
</xul:tabpanels>
|
|
|
|
</xul:tabbox>
|
|
|
|
<children/>
|
|
|
|
</content>
|
2013-04-24 22:29:39 -07:00
|
|
|
<implementation implements="nsIDOMEventListener, nsIMessageListener">
|
2010-03-22 10:49:55 -07:00
|
|
|
|
|
|
|
<property name="tabContextMenu" readonly="true"
|
|
|
|
onget="return this.tabContainer.contextMenu;"/>
|
|
|
|
|
2010-03-22 07:12:04 -07:00
|
|
|
<field name="tabContainer" readonly="true">
|
|
|
|
document.getElementById(this.getAttribute("tabcontainer"));
|
|
|
|
</field>
|
|
|
|
<field name="tabs" readonly="true">
|
|
|
|
this.tabContainer.childNodes;
|
|
|
|
</field>
|
2012-05-02 11:39:06 -07:00
|
|
|
|
2010-08-17 11:39:17 -07:00
|
|
|
<property name="visibleTabs" readonly="true">
|
|
|
|
<getter><![CDATA[
|
2012-05-02 11:39:06 -07:00
|
|
|
if (!this._visibleTabs)
|
|
|
|
this._visibleTabs = Array.filter(this.tabs,
|
|
|
|
function (tab) !tab.hidden && !tab.closing);
|
|
|
|
return this._visibleTabs;
|
2010-08-17 11:39:17 -07:00
|
|
|
]]></getter>
|
|
|
|
</property>
|
2013-05-29 07:07:26 -07:00
|
|
|
|
|
|
|
<field name="closingTabsEnum" readonly="true">({ ALL: 0, OTHER: 1, TO_END: 2 });</field>
|
|
|
|
|
2012-05-02 11:39:06 -07:00
|
|
|
<field name="_visibleTabs">null</field>
|
|
|
|
|
2007-08-21 21:59:55 -07:00
|
|
|
<field name="mURIFixup" readonly="true">
|
|
|
|
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
|
|
|
.getService(Components.interfaces.nsIURIFixup);
|
|
|
|
</field>
|
2007-10-09 22:03:52 -07:00
|
|
|
<field name="mFaviconService" readonly="true">
|
|
|
|
Components.classes["@mozilla.org/browser/favicon-service;1"]
|
|
|
|
.getService(Components.interfaces.nsIFaviconService);
|
|
|
|
</field>
|
2010-11-29 03:44:43 -08:00
|
|
|
<field name="_placesAutocomplete" readonly="true">
|
2010-11-19 16:39:55 -08:00
|
|
|
Components.classes["@mozilla.org/autocomplete/search;1?name=history"]
|
|
|
|
.getService(Components.interfaces.mozIPlacesAutoComplete);
|
2010-03-26 14:59:02 -07:00
|
|
|
</field>
|
2007-08-21 22:01:04 -07:00
|
|
|
<field name="mTabBox" readonly="true">
|
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "tabbox");
|
2007-08-21 21:58:49 -07:00
|
|
|
</field>
|
2007-08-21 22:01:04 -07:00
|
|
|
<field name="mPanelContainer" readonly="true">
|
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer");
|
2007-08-21 22:00:10 -07:00
|
|
|
</field>
|
2007-08-21 21:58:49 -07:00
|
|
|
<field name="mStringBundle">
|
2007-08-21 22:01:04 -07:00
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "tbstringbundle");
|
2007-08-21 21:58:49 -07:00
|
|
|
</field>
|
|
|
|
<field name="mCurrentTab">
|
|
|
|
null
|
|
|
|
</field>
|
2009-09-04 07:37:17 -07:00
|
|
|
<field name="_lastRelatedTab">
|
|
|
|
null
|
|
|
|
</field>
|
2007-08-21 21:58:49 -07:00
|
|
|
<field name="mCurrentBrowser">
|
|
|
|
null
|
|
|
|
</field>
|
|
|
|
<field name="mProgressListeners">
|
2007-08-21 22:01:04 -07:00
|
|
|
[]
|
2007-08-21 21:58:49 -07:00
|
|
|
</field>
|
2008-11-18 02:53:25 -08:00
|
|
|
<field name="mTabsProgressListeners">
|
|
|
|
[]
|
|
|
|
</field>
|
2007-08-21 21:58:49 -07:00
|
|
|
<field name="mTabListeners">
|
2011-03-23 04:31:35 -07:00
|
|
|
[]
|
2007-08-21 21:58:49 -07:00
|
|
|
</field>
|
|
|
|
<field name="mTabFilters">
|
2011-03-23 04:31:35 -07:00
|
|
|
[]
|
2007-08-21 21:58:49 -07:00
|
|
|
</field>
|
|
|
|
<field name="mIsBusy">
|
|
|
|
false
|
|
|
|
</field>
|
2007-08-21 22:00:10 -07:00
|
|
|
<field name="arrowKeysShouldWrap" readonly="true">
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
true
|
|
|
|
#else
|
|
|
|
false
|
|
|
|
#endif
|
2007-08-21 22:00:55 -07:00
|
|
|
</field>
|
2007-08-21 22:00:10 -07:00
|
|
|
|
2007-08-21 22:02:41 -07:00
|
|
|
<field name="_autoScrollPopup">
|
|
|
|
null
|
|
|
|
</field>
|
2007-08-21 22:01:33 -07:00
|
|
|
|
2009-10-05 21:26:15 -07:00
|
|
|
<field name="_previewMode">
|
|
|
|
false
|
|
|
|
</field>
|
|
|
|
|
2013-07-05 17:56:36 -07:00
|
|
|
<field name="_lastFindValue">
|
|
|
|
""
|
|
|
|
</field>
|
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
<property name="_numPinnedTabs" readonly="true">
|
|
|
|
<getter><![CDATA[
|
|
|
|
for (var i = 0; i < this.tabs.length; i++) {
|
|
|
|
if (!this.tabs[i].pinned)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return i;
|
|
|
|
]]></getter>
|
|
|
|
</property>
|
|
|
|
|
2013-07-05 17:56:36 -07:00
|
|
|
<method name="isFindBarInitialized">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
return (aTab || this.selectedTab)._findBar != undefined;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="getFindBar">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
if (!aTab)
|
|
|
|
aTab = this.selectedTab;
|
|
|
|
|
|
|
|
if (aTab._findBar)
|
|
|
|
return aTab._findBar;
|
|
|
|
|
|
|
|
let findBar = document.createElementNS(this.namespaceURI, "findbar");
|
|
|
|
let browser = this.getBrowserForTab(aTab);
|
|
|
|
let browserContainer = this.getBrowserContainer(browser);
|
2013-09-13 02:01:40 -07:00
|
|
|
browserContainer.appendChild(findBar);
|
2013-07-05 17:56:36 -07:00
|
|
|
|
|
|
|
// Force a style flush to ensure that our binding is attached.
|
|
|
|
findBar.clientTop;
|
|
|
|
|
|
|
|
findBar.browser = browser;
|
|
|
|
findBar._findField.value = this._lastFindValue;
|
|
|
|
|
|
|
|
aTab._findBar = findBar;
|
|
|
|
|
2013-08-04 14:06:19 -07:00
|
|
|
let event = document.createEvent("Events");
|
|
|
|
event.initEvent("TabFindInitialized", true, false);
|
|
|
|
aTab.dispatchEvent(event);
|
|
|
|
|
2013-07-05 17:56:36 -07:00
|
|
|
return findBar;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2013-09-12 14:36:05 -07:00
|
|
|
<method name="getStatusPanel">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (!this._statusPanel) {
|
|
|
|
this._statusPanel = document.createElementNS(this.namespaceURI, "statuspanel");
|
|
|
|
this._statusPanel.setAttribute("inactive", "true");
|
2013-11-24 17:59:00 -08:00
|
|
|
this._statusPanel.setAttribute("layer", "true");
|
2013-09-12 14:36:05 -07:00
|
|
|
this._appendStatusPanel();
|
|
|
|
}
|
|
|
|
return this._statusPanel;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_appendStatusPanel">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (this._statusPanel) {
|
|
|
|
let browser = this.selectedBrowser;
|
|
|
|
let browserContainer = this.getBrowserContainer(browser);
|
|
|
|
browserContainer.insertBefore(this._statusPanel, browser.parentNode.nextSibling);
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2011-01-17 06:35:32 -08:00
|
|
|
<method name="updateWindowResizers">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (!window.gShowPageResizers)
|
|
|
|
return;
|
|
|
|
|
2013-05-09 03:08:07 -07:00
|
|
|
var show = window.windowState == window.STATE_NORMAL;
|
2011-01-17 06:35:32 -08:00
|
|
|
for (let i = 0; i < this.browsers.length; i++) {
|
|
|
|
this.browsers[i].showWindowResizer = show;
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2011-02-07 05:54:26 -08:00
|
|
|
<method name="_setCloseKeyState">
|
|
|
|
<parameter name="aEnabled"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
let keyClose = document.getElementById("key_close");
|
|
|
|
let closeKeyEnabled = keyClose.getAttribute("disabled") != "true";
|
|
|
|
if (closeKeyEnabled == aEnabled)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (aEnabled)
|
|
|
|
keyClose.removeAttribute("disabled");
|
|
|
|
else
|
|
|
|
keyClose.setAttribute("disabled", "true");
|
|
|
|
|
|
|
|
// We also want to remove the keyboard shortcut from the file menu
|
|
|
|
// when the shortcut is disabled, and bring it back when it's
|
|
|
|
// renabled.
|
|
|
|
//
|
|
|
|
// Fixing bug 630826 could make that happen automatically.
|
|
|
|
// Fixing bug 630830 could avoid the ugly hack below.
|
2011-05-24 23:50:44 -07:00
|
|
|
|
2011-02-07 05:54:26 -08:00
|
|
|
let closeMenuItem = document.getElementById("menu_close");
|
|
|
|
let parentPopup = closeMenuItem.parentNode;
|
|
|
|
let nextItem = closeMenuItem.nextSibling;
|
|
|
|
let clonedItem = closeMenuItem.cloneNode(true);
|
|
|
|
|
|
|
|
parentPopup.removeChild(closeMenuItem);
|
|
|
|
|
|
|
|
if (aEnabled)
|
|
|
|
clonedItem.setAttribute("key", "key_close");
|
|
|
|
else
|
|
|
|
clonedItem.removeAttribute("key");
|
|
|
|
|
|
|
|
parentPopup.insertBefore(clonedItem, nextItem);
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
<method name="pinTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
if (aTab.pinned)
|
|
|
|
return;
|
|
|
|
|
2010-10-11 10:27:05 -07:00
|
|
|
if (aTab.hidden)
|
|
|
|
this.showTab(aTab);
|
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
this.moveTabTo(aTab, this._numPinnedTabs);
|
|
|
|
aTab.setAttribute("pinned", "true");
|
2011-04-11 23:50:56 -07:00
|
|
|
this.tabContainer._unlockTabSizing();
|
2010-06-24 07:29:02 -07:00
|
|
|
this.tabContainer._positionPinnedTabs();
|
2010-08-23 13:30:58 -07:00
|
|
|
this.tabContainer.adjustTabstrip();
|
2010-09-08 17:15:24 -07:00
|
|
|
|
2014-01-21 09:53:37 -08:00
|
|
|
// Bug 961867 - [e10s] Implement the logic for app tabs
|
|
|
|
if (!gMultiProcessBrowser)
|
|
|
|
this.getBrowserForTab(aTab).docShell.isAppTab = true;
|
2010-10-28 15:00:31 -07:00
|
|
|
|
2011-02-07 05:54:26 -08:00
|
|
|
if (aTab.selected)
|
|
|
|
this._setCloseKeyState(false);
|
|
|
|
|
2010-09-08 17:15:24 -07:00
|
|
|
let event = document.createEvent("Events");
|
2010-09-11 03:11:25 -07:00
|
|
|
event.initEvent("TabPinned", true, false);
|
2010-09-08 17:15:24 -07:00
|
|
|
aTab.dispatchEvent(event);
|
2010-06-24 07:29:02 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="unpinTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
if (!aTab.pinned)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.moveTabTo(aTab, this._numPinnedTabs - 1);
|
2010-08-05 13:18:17 -07:00
|
|
|
aTab.setAttribute("fadein", "true");
|
2010-06-24 07:29:02 -07:00
|
|
|
aTab.removeAttribute("pinned");
|
|
|
|
aTab.style.MozMarginStart = "";
|
2011-04-11 23:50:56 -07:00
|
|
|
this.tabContainer._unlockTabSizing();
|
2010-06-24 07:29:02 -07:00
|
|
|
this.tabContainer._positionPinnedTabs();
|
2010-08-23 13:30:58 -07:00
|
|
|
this.tabContainer.adjustTabstrip();
|
2010-09-08 17:15:24 -07:00
|
|
|
|
2014-01-21 09:53:37 -08:00
|
|
|
// Bug 961867 - [e10s] Implement the logic for app tabs
|
|
|
|
if (!gMultiProcessBrowser)
|
|
|
|
this.getBrowserForTab(aTab).docShell.isAppTab = false;
|
2010-10-28 15:00:31 -07:00
|
|
|
|
2011-02-07 05:54:26 -08:00
|
|
|
if (aTab.selected)
|
|
|
|
this._setCloseKeyState(true);
|
|
|
|
|
2010-09-08 17:15:24 -07:00
|
|
|
let event = document.createEvent("Events");
|
2010-09-11 03:11:25 -07:00
|
|
|
event.initEvent("TabUnpinned", true, false);
|
2010-09-08 17:15:24 -07:00
|
|
|
aTab.dispatchEvent(event);
|
2010-06-24 07:29:02 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2009-10-05 21:26:15 -07:00
|
|
|
<method name="previewTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<parameter name="aCallback"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
let currentTab = this.selectedTab;
|
|
|
|
try {
|
|
|
|
// Suppress focus, ownership and selected tab changes
|
|
|
|
this._previewMode = true;
|
|
|
|
this.selectedTab = aTab;
|
|
|
|
aCallback();
|
|
|
|
} finally {
|
|
|
|
this.selectedTab = currentTab;
|
|
|
|
this._previewMode = false;
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:59:41 -07:00
|
|
|
<method name="getBrowserAtIndex">
|
|
|
|
<parameter name="aIndex"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2007-11-19 23:58:58 -08:00
|
|
|
return this.browsers[aIndex];
|
2007-08-21 21:59:41 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="getBrowserIndexForDocument">
|
|
|
|
<parameter name="aDocument"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-02-25 23:58:46 -08:00
|
|
|
var tab = this._getTabForContentWindow(aDocument.defaultView);
|
|
|
|
return tab ? tab._tPos : -1;
|
2007-08-21 21:59:41 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:01:15 -07:00
|
|
|
<method name="getBrowserForDocument">
|
|
|
|
<parameter name="aDocument"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-02-25 23:58:46 -08:00
|
|
|
var tab = this._getTabForContentWindow(aDocument.defaultView);
|
|
|
|
return tab ? tab.linkedBrowser : null;
|
2007-08-21 22:01:15 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
<method name="_getTabForContentWindow">
|
|
|
|
<parameter name="aWindow"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
for (let i = 0; i < this.browsers.length; i++) {
|
|
|
|
if (this.browsers[i].contentWindow == aWindow)
|
2010-03-22 07:12:04 -07:00
|
|
|
return this.tabs[i];
|
2010-02-25 23:58:46 -08:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2013-04-24 22:29:39 -07:00
|
|
|
<method name="_getTabForBrowser">
|
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
for (let i = 0; i < this.tabs.length; i++) {
|
|
|
|
if (this.tabs[i].linkedBrowser == aBrowser)
|
|
|
|
return this.tabs[i];
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:01:12 -07:00
|
|
|
<method name="getNotificationBox">
|
2012-08-30 03:23:26 -07:00
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.getSidebarContainer(aBrowser).parentNode;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="getSidebarContainer">
|
2012-06-01 05:53:58 -07:00
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.getBrowserContainer(aBrowser).parentNode;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="getBrowserContainer">
|
2007-08-21 21:59:41 -07:00
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-09-15 20:01:00 -07:00
|
|
|
return (aBrowser || this.mCurrentBrowser).parentNode.parentNode;
|
2007-08-21 21:59:41 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2010-11-19 21:23:25 -08:00
|
|
|
<method name="getTabModalPromptBox">
|
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
let browser = (aBrowser || this.mCurrentBrowser);
|
|
|
|
let stack = browser.parentNode;
|
|
|
|
let self = this;
|
|
|
|
|
|
|
|
let promptBox = {
|
|
|
|
appendPrompt : function(args, onCloseCallback) {
|
|
|
|
let newPrompt = document.createElementNS(XUL_NS, "tabmodalprompt");
|
|
|
|
stack.appendChild(newPrompt);
|
2011-04-19 14:18:17 -07:00
|
|
|
browser.setAttribute("tabmodalPromptShowing", true);
|
|
|
|
|
2010-11-19 21:23:25 -08:00
|
|
|
newPrompt.clientTop; // style flush to assure binding is attached
|
|
|
|
|
2014-04-04 14:50:42 -07:00
|
|
|
let tab = self._getTabForBrowser(browser);
|
2010-11-19 21:23:25 -08:00
|
|
|
newPrompt.init(args, tab, onCloseCallback);
|
|
|
|
return newPrompt;
|
|
|
|
},
|
|
|
|
|
|
|
|
removePrompt : function(aPrompt) {
|
|
|
|
stack.removeChild(aPrompt);
|
2011-04-19 14:18:17 -07:00
|
|
|
|
|
|
|
let prompts = this.listPrompts();
|
|
|
|
if (prompts.length) {
|
|
|
|
let prompt = prompts[prompts.length - 1];
|
|
|
|
prompt.Dialog.setDefaultFocus();
|
|
|
|
} else {
|
|
|
|
browser.removeAttribute("tabmodalPromptShowing");
|
|
|
|
browser.focus();
|
|
|
|
}
|
2010-11-19 21:23:25 -08:00
|
|
|
},
|
|
|
|
|
|
|
|
listPrompts : function(aPrompt) {
|
|
|
|
let els = stack.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
|
|
|
|
// NodeList --> real JS array
|
2011-04-19 14:18:17 -07:00
|
|
|
let prompts = Array.slice(els);
|
2010-11-19 21:23:25 -08:00
|
|
|
return prompts;
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
return promptBox;
|
|
|
|
]]>
|
2007-08-21 21:59:41 -07:00
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
<method name="_callProgressListeners">
|
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<parameter name="aMethod"/>
|
|
|
|
<parameter name="aArguments"/>
|
|
|
|
<parameter name="aCallGlobalListeners"/>
|
|
|
|
<parameter name="aCallTabsListeners"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
var rv = true;
|
|
|
|
|
|
|
|
if (!aBrowser)
|
|
|
|
aBrowser = this.mCurrentBrowser;
|
|
|
|
|
|
|
|
if (aCallGlobalListeners != false &&
|
|
|
|
aBrowser == this.mCurrentBrowser) {
|
|
|
|
this.mProgressListeners.forEach(function (p) {
|
|
|
|
if (aMethod in p) {
|
|
|
|
try {
|
|
|
|
if (!p[aMethod].apply(p, aArguments))
|
|
|
|
rv = false;
|
|
|
|
} catch (e) {
|
|
|
|
// don't inhibit other listeners
|
|
|
|
Components.utils.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aCallTabsListeners != false) {
|
|
|
|
aArguments.unshift(aBrowser);
|
|
|
|
|
|
|
|
this.mTabsProgressListeners.forEach(function (p) {
|
|
|
|
if (aMethod in p) {
|
|
|
|
try {
|
|
|
|
if (!p[aMethod].apply(p, aArguments))
|
|
|
|
rv = false;
|
|
|
|
} catch (e) {
|
|
|
|
// don't inhibit other listeners
|
|
|
|
Components.utils.reportError(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
<!-- A web progress listener object definition for a given tab. -->
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="mTabProgressListener">
|
|
|
|
<parameter name="aTab"/>
|
2007-08-21 21:59:22 -07:00
|
|
|
<parameter name="aBrowser"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<parameter name="aStartsBlank"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return ({
|
2007-08-21 21:59:22 -07:00
|
|
|
mTabBrowser: this,
|
2007-08-21 21:58:49 -07:00
|
|
|
mTab: aTab,
|
2007-08-21 21:59:22 -07:00
|
|
|
mBrowser: aBrowser,
|
2007-08-21 21:58:49 -07:00
|
|
|
mBlank: aStartsBlank,
|
|
|
|
|
2010-09-15 23:09:27 -07:00
|
|
|
// cache flags for correct status UI update after tab switching
|
2007-08-21 22:01:05 -07:00
|
|
|
mStateFlags: 0,
|
|
|
|
mStatus: 0,
|
|
|
|
mMessage: "",
|
|
|
|
mTotalProgress: 0,
|
|
|
|
|
2007-08-21 22:01:09 -07:00
|
|
|
// count of open requests (should always be 0 or 1)
|
|
|
|
mRequestCount: 0,
|
|
|
|
|
2009-10-01 05:31:24 -07:00
|
|
|
destroy: function () {
|
2009-10-01 08:00:06 -07:00
|
|
|
delete this.mTab;
|
|
|
|
delete this.mBrowser;
|
|
|
|
delete this.mTabBrowser;
|
2009-10-01 05:31:24 -07:00
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
_callProgressListeners: function () {
|
|
|
|
Array.unshift(arguments, this.mBrowser);
|
|
|
|
return this.mTabBrowser._callProgressListeners.apply(this.mTabBrowser, arguments);
|
|
|
|
},
|
|
|
|
|
2013-03-27 02:01:04 -07:00
|
|
|
_shouldShowProgress: function (aRequest) {
|
|
|
|
if (this.mBlank)
|
|
|
|
return false;
|
|
|
|
|
2013-04-22 19:47:52 -07:00
|
|
|
if (gMultiProcessBrowser)
|
|
|
|
return true;
|
|
|
|
|
2013-03-27 02:01:04 -07:00
|
|
|
// Don't show progress indicators in tabs for about: URIs
|
|
|
|
// pointing to local resources.
|
|
|
|
try {
|
|
|
|
let channel = aRequest.QueryInterface(Ci.nsIChannel);
|
|
|
|
if (channel.originalURI.schemeIs("about") &&
|
|
|
|
(channel.URI.schemeIs("jar") || channel.URI.schemeIs("file")))
|
|
|
|
return false;
|
|
|
|
} catch (e) {}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onProgressChange: function (aWebProgress, aRequest,
|
|
|
|
aCurSelfProgress, aMaxSelfProgress,
|
|
|
|
aCurTotalProgress, aMaxTotalProgress) {
|
2008-11-18 02:53:25 -08:00
|
|
|
this.mTotalProgress = aMaxTotalProgress ? aCurTotalProgress / aMaxTotalProgress : 0;
|
|
|
|
|
2013-03-27 02:01:04 -07:00
|
|
|
if (!this._shouldShowProgress(aRequest))
|
2008-11-18 02:53:25 -08:00
|
|
|
return;
|
|
|
|
|
2010-10-11 20:47:59 -07:00
|
|
|
if (this.mTotalProgress)
|
|
|
|
this.mTab.setAttribute("progress", "true");
|
2009-10-01 05:31:24 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners("onProgressChange",
|
|
|
|
[aWebProgress, aRequest,
|
|
|
|
aCurSelfProgress, aMaxSelfProgress,
|
|
|
|
aCurTotalProgress, aMaxTotalProgress]);
|
2007-08-21 21:58:49 -07:00
|
|
|
},
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onProgressChange64: function (aWebProgress, aRequest,
|
|
|
|
aCurSelfProgress, aMaxSelfProgress,
|
|
|
|
aCurTotalProgress, aMaxTotalProgress) {
|
2007-08-21 22:02:29 -07:00
|
|
|
return this.onProgressChange(aWebProgress, aRequest,
|
|
|
|
aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress,
|
|
|
|
aMaxTotalProgress);
|
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus) {
|
2007-08-21 21:58:49 -07:00
|
|
|
if (!aRequest)
|
|
|
|
return;
|
|
|
|
|
|
|
|
var oldBlank = this.mBlank;
|
|
|
|
|
|
|
|
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
|
|
|
|
const nsIChannel = Components.interfaces.nsIChannel;
|
|
|
|
|
2007-08-21 22:01:09 -07:00
|
|
|
if (aStateFlags & nsIWebProgressListener.STATE_START) {
|
|
|
|
this.mRequestCount++;
|
|
|
|
}
|
|
|
|
else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
|
|
|
|
const NS_ERROR_UNKNOWN_HOST = 2152398878;
|
|
|
|
if (--this.mRequestCount > 0 && aStatus == NS_ERROR_UNKNOWN_HOST) {
|
|
|
|
// to prevent bug 235825: wait for the request handled
|
|
|
|
// by the automatic keyword resolver
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// since we (try to) only handle STATE_STOP of the last request,
|
|
|
|
// the count of open requests should now be 0
|
|
|
|
this.mRequestCount = 0;
|
|
|
|
}
|
|
|
|
|
2007-08-21 21:59:43 -07:00
|
|
|
if (aStateFlags & nsIWebProgressListener.STATE_START &&
|
2007-08-21 21:59:22 -07:00
|
|
|
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
|
2007-08-21 21:59:31 -07:00
|
|
|
// It's okay to clear what the user typed when we start
|
2007-08-21 22:00:35 -07:00
|
|
|
// loading a document. If the user types, this counter gets
|
|
|
|
// set to zero, if the document load ends without an
|
|
|
|
// onLocationChange, this counter gets decremented
|
|
|
|
// (so we keep it while switching tabs after failed loads)
|
2008-01-08 20:07:42 -08:00
|
|
|
// We need to add 2 because loadURIWithFlags may have
|
|
|
|
// cancelled a pending load which would have cleared
|
|
|
|
// its anchor scroll detection temporary increment.
|
2013-04-24 22:29:24 -07:00
|
|
|
if (aWebProgress.isTopLevel)
|
2008-01-08 20:07:42 -08:00
|
|
|
this.mBrowser.userTypedClear += 2;
|
2007-08-21 21:59:22 -07:00
|
|
|
|
2013-03-27 02:01:04 -07:00
|
|
|
if (this._shouldShowProgress(aRequest)) {
|
2009-09-09 09:31:25 -07:00
|
|
|
if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) {
|
|
|
|
this.mTab.setAttribute("busy", "true");
|
2013-07-29 08:03:41 -07:00
|
|
|
if (!(aWebProgress.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD))
|
|
|
|
this.mTabBrowser.setTabTitleLoading(this.mTab);
|
2009-09-09 09:31:25 -07:00
|
|
|
}
|
2007-08-21 21:59:22 -07:00
|
|
|
|
2010-09-10 01:05:36 -07:00
|
|
|
if (this.mTab.selected)
|
2007-08-21 21:59:22 -07:00
|
|
|
this.mTabBrowser.mIsBusy = true;
|
|
|
|
}
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
|
|
|
else if (aStateFlags & nsIWebProgressListener.STATE_STOP &&
|
|
|
|
aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
|
2012-03-29 01:22:53 -07:00
|
|
|
|
2012-03-29 02:28:38 -07:00
|
|
|
if (this.mTab.hasAttribute("busy")) {
|
|
|
|
this.mTab.removeAttribute("busy");
|
|
|
|
this.mTabBrowser._tabAttrModified(this.mTab);
|
|
|
|
if (!this.mTab.selected)
|
|
|
|
this.mTab.setAttribute("unread", "true");
|
|
|
|
}
|
|
|
|
this.mTab.removeAttribute("progress");
|
|
|
|
|
2013-04-24 22:29:24 -07:00
|
|
|
if (aWebProgress.isTopLevel) {
|
2012-03-29 02:36:34 -07:00
|
|
|
if (!Components.isSuccessCode(aStatus) &&
|
|
|
|
!isTabEmpty(this.mTab)) {
|
|
|
|
// Restore the current document's location in case the
|
|
|
|
// request was stopped (possibly from a content script)
|
|
|
|
// before the location changed.
|
|
|
|
|
|
|
|
this.mBrowser.userTypedValue = null;
|
|
|
|
|
|
|
|
if (this.mTab.selected && gURLBar)
|
|
|
|
URLBarSetURI();
|
|
|
|
} else {
|
|
|
|
// The document is done loading, we no longer want the
|
|
|
|
// value cleared.
|
|
|
|
|
|
|
|
if (this.mBrowser.userTypedClear > 1)
|
|
|
|
this.mBrowser.userTypedClear -= 2;
|
|
|
|
else if (this.mBrowser.userTypedClear > 0)
|
|
|
|
this.mBrowser.userTypedClear--;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!this.mBrowser.mIconURL)
|
|
|
|
this.mTabBrowser.useDefaultIcon(this.mTab);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this.mBlank)
|
|
|
|
this.mBlank = false;
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
var location = aRequest.QueryInterface(nsIChannel).URI;
|
2007-08-21 21:59:41 -07:00
|
|
|
|
|
|
|
// For keyword URIs clear the user typed value since they will be changed into real URIs
|
|
|
|
if (location.scheme == "keyword")
|
|
|
|
this.mBrowser.userTypedValue = null;
|
|
|
|
|
2010-10-12 14:25:17 -07:00
|
|
|
if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.connecting"))
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mTabBrowser.setTabTitle(this.mTab);
|
|
|
|
|
2010-09-10 01:05:36 -07:00
|
|
|
if (this.mTab.selected)
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mTabBrowser.mIsBusy = false;
|
|
|
|
}
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
if (oldBlank) {
|
|
|
|
this._callProgressListeners("onUpdateCurrentBrowser",
|
|
|
|
[aStateFlags, aStatus, "", 0],
|
|
|
|
true, false);
|
|
|
|
} else {
|
|
|
|
this._callProgressListeners("onStateChange",
|
|
|
|
[aWebProgress, aRequest, aStateFlags, aStatus],
|
|
|
|
true, false);
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
2007-08-21 22:01:05 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners("onStateChange",
|
|
|
|
[aWebProgress, aRequest, aStateFlags, aStatus],
|
|
|
|
false);
|
2008-11-18 02:53:25 -08:00
|
|
|
|
2007-08-21 22:01:05 -07:00
|
|
|
if (aStateFlags & (nsIWebProgressListener.STATE_START |
|
|
|
|
nsIWebProgressListener.STATE_STOP)) {
|
|
|
|
// reset cached temporary values at beginning and end
|
|
|
|
this.mMessage = "";
|
|
|
|
this.mTotalProgress = 0;
|
|
|
|
}
|
|
|
|
this.mStateFlags = aStateFlags;
|
|
|
|
this.mStatus = aStatus;
|
2007-08-21 21:59:43 -07:00
|
|
|
},
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2011-11-10 06:01:11 -08:00
|
|
|
onLocationChange: function (aWebProgress, aRequest, aLocation,
|
|
|
|
aFlags) {
|
2010-08-09 08:59:31 -07:00
|
|
|
// OnLocationChange is called for both the top-level content
|
|
|
|
// and the subframes.
|
2013-04-24 22:29:24 -07:00
|
|
|
let topLevel = aWebProgress.isTopLevel;
|
2010-08-09 08:59:31 -07:00
|
|
|
|
|
|
|
if (topLevel) {
|
2013-12-02 08:52:35 -08:00
|
|
|
// If userTypedClear > 0, the document loaded correctly and we should be
|
|
|
|
// clearing the user typed value. We also need to clear the typed value
|
|
|
|
// if the document failed to load, to make sure the urlbar reflects the
|
|
|
|
// failed URI (particularly for SSL errors). However, don't clear the value
|
|
|
|
// if the error page's URI is about:blank, because that causes complete
|
|
|
|
// loss of urlbar contents for invalid URI errors (see bug 867957).
|
2011-12-18 03:22:34 -08:00
|
|
|
if (this.mBrowser.userTypedClear > 0 ||
|
2013-12-02 08:52:35 -08:00
|
|
|
((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
|
|
|
|
aLocation.spec != "about:blank"))
|
2010-08-09 08:59:31 -07:00
|
|
|
this.mBrowser.userTypedValue = null;
|
2007-08-21 22:00:14 -07:00
|
|
|
|
2010-08-09 08:59:31 -07:00
|
|
|
// Clear out the missing plugins list since it's related to the
|
|
|
|
// previous location.
|
|
|
|
this.mBrowser.missingPlugins = null;
|
2007-08-21 22:01:14 -07:00
|
|
|
|
2013-07-10 14:53:34 -07:00
|
|
|
if (this.mTabBrowser.isFindBarInitialized(this.mTab)) {
|
|
|
|
let findBar = this.mTabBrowser.getFindBar(this.mTab);
|
|
|
|
|
|
|
|
// Close the Find toolbar if we're in old-style TAF mode
|
|
|
|
if (findBar.findMode != findBar.FIND_NORMAL)
|
|
|
|
findBar.close();
|
|
|
|
|
|
|
|
// fix bug 253793 - turn off highlight when page changes
|
|
|
|
findBar.getElement("highlight").checked = false;
|
|
|
|
}
|
|
|
|
|
2010-08-09 08:59:31 -07:00
|
|
|
// Don't clear the favicon if this onLocationChange was
|
|
|
|
// triggered by a pushState or a replaceState. See bug 550565.
|
2013-07-29 08:03:41 -07:00
|
|
|
if (aWebProgress.isLoadingDocument &&
|
|
|
|
!(aWebProgress.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE)) {
|
|
|
|
this.mBrowser.mIconURL = null;
|
2013-04-22 19:47:52 -07:00
|
|
|
}
|
2010-08-09 08:59:31 -07:00
|
|
|
|
2010-11-29 03:44:43 -08:00
|
|
|
let autocomplete = this.mTabBrowser._placesAutocomplete;
|
2010-08-13 18:52:30 -07:00
|
|
|
if (this.mBrowser.registeredOpenURI) {
|
2010-11-19 16:39:55 -08:00
|
|
|
autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI);
|
2010-08-13 18:52:30 -07:00
|
|
|
delete this.mBrowser.registeredOpenURI;
|
|
|
|
}
|
2013-01-29 10:12:13 -08:00
|
|
|
// Tabs in private windows aren't registered as "Open" so
|
|
|
|
// that they don't appear as switch-to-tab candidates.
|
|
|
|
if (!isBlankPageURL(aLocation.spec) &&
|
2013-04-22 23:00:38 -07:00
|
|
|
(!PrivateBrowsingUtils.isWindowPrivate(window) ||
|
|
|
|
PrivateBrowsingUtils.permanentPrivateBrowsing)) {
|
2010-11-19 16:39:55 -08:00
|
|
|
autocomplete.registerOpenPage(aLocation);
|
2010-11-07 04:59:28 -08:00
|
|
|
this.mBrowser.registeredOpenURI = aLocation;
|
|
|
|
}
|
2010-08-09 08:59:31 -07:00
|
|
|
}
|
2010-03-26 14:59:02 -07:00
|
|
|
|
|
|
|
if (!this.mBlank) {
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners("onLocationChange",
|
2011-11-10 06:01:11 -08:00
|
|
|
[aWebProgress, aRequest, aLocation,
|
|
|
|
aFlags]);
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
2008-11-18 02:53:25 -08:00
|
|
|
|
2013-06-24 18:26:22 -07:00
|
|
|
if (topLevel) {
|
2010-08-09 08:59:31 -07:00
|
|
|
this.mBrowser.lastURI = aLocation;
|
2013-06-24 18:26:22 -07:00
|
|
|
this.mBrowser.lastLocationChange = Date.now();
|
|
|
|
}
|
2007-08-21 21:58:49 -07:00
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
if (this.mBlank)
|
2007-08-21 21:58:49 -07:00
|
|
|
return;
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners("onStatusChange",
|
|
|
|
[aWebProgress, aRequest, aStatus, aMessage]);
|
2008-11-18 02:53:25 -08:00
|
|
|
|
2007-08-21 22:01:05 -07:00
|
|
|
this.mMessage = aMessage;
|
2007-08-21 21:58:49 -07:00
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onSecurityChange: function (aWebProgress, aRequest, aState) {
|
|
|
|
this._callProgressListeners("onSecurityChange",
|
|
|
|
[aWebProgress, aRequest, aState]);
|
2008-11-18 02:53:25 -08:00
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
onRefreshAttempted: function (aWebProgress, aURI, aDelay, aSameURI) {
|
|
|
|
return this._callProgressListeners("onRefreshAttempted",
|
|
|
|
[aWebProgress, aURI, aDelay, aSameURI]);
|
2007-08-21 21:58:49 -07:00
|
|
|
},
|
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
QueryInterface: function (aIID) {
|
2007-08-21 21:58:49 -07:00
|
|
|
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
|
2007-08-21 22:02:29 -07:00
|
|
|
aIID.equals(Components.interfaces.nsIWebProgressListener2) ||
|
2007-08-21 21:58:49 -07:00
|
|
|
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
|
|
|
|
aIID.equals(Components.interfaces.nsISupports))
|
|
|
|
return this;
|
|
|
|
throw Components.results.NS_NOINTERFACE;
|
|
|
|
}
|
2007-08-21 21:59:43 -07:00
|
|
|
});
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:14 -07:00
|
|
|
<method name="setIcon">
|
|
|
|
<parameter name="aTab"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<parameter name="aURI"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2007-08-21 22:00:14 -07:00
|
|
|
var browser = this.getBrowserForTab(aTab);
|
2009-07-28 22:55:18 -07:00
|
|
|
browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
|
2007-08-21 22:00:14 -07:00
|
|
|
|
2009-07-28 22:55:18 -07:00
|
|
|
if (aURI && this.mFaviconService) {
|
|
|
|
if (!(aURI instanceof Ci.nsIURI))
|
|
|
|
aURI = makeURI(aURI);
|
2012-02-23 02:30:48 -08:00
|
|
|
this.mFaviconService.setAndFetchFaviconForPage(browser.currentURI,
|
2012-09-05 21:34:50 -07:00
|
|
|
aURI, false,
|
2012-10-05 16:25:52 -07:00
|
|
|
PrivateBrowsingUtils.isWindowPrivate(window) ?
|
2012-09-05 21:34:50 -07:00
|
|
|
this.mFaviconService.FAVICON_LOAD_PRIVATE :
|
|
|
|
this.mFaviconService.FAVICON_LOAD_NON_PRIVATE);
|
2007-10-09 22:03:52 -07:00
|
|
|
}
|
|
|
|
|
2013-03-26 10:49:37 -07:00
|
|
|
let sizedIconUrl = browser.mIconURL || "";
|
|
|
|
if (sizedIconUrl) {
|
|
|
|
let size = Math.round(16 * window.devicePixelRatio);
|
|
|
|
sizedIconUrl += (sizedIconUrl.contains("#") ? "&" : "#") +
|
|
|
|
"-moz-resolution=" + size + "," + size;
|
|
|
|
}
|
|
|
|
if (sizedIconUrl != aTab.getAttribute("image")) {
|
|
|
|
if (sizedIconUrl)
|
|
|
|
aTab.setAttribute("image", sizedIconUrl);
|
2010-09-24 00:29:50 -07:00
|
|
|
else
|
|
|
|
aTab.removeAttribute("image");
|
|
|
|
this._tabAttrModified(aTab);
|
|
|
|
}
|
2007-08-21 22:00:14 -07:00
|
|
|
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners(browser, "onLinkIconAvailable", [browser.mIconURL]);
|
2007-08-21 22:00:14 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2009-12-14 23:49:08 -08:00
|
|
|
<method name="getIcon">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
let browser = aTab ? this.getBrowserForTab(aTab) : this.selectedBrowser;
|
|
|
|
return browser.mIconURL;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="shouldLoadFavIcon">
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-03-21 02:38:08 -07:00
|
|
|
return (aURI &&
|
|
|
|
Services.prefs.getBoolPref("browser.chrome.site_icons") &&
|
|
|
|
Services.prefs.getBoolPref("browser.chrome.favicons") &&
|
2007-08-21 21:58:49 -07:00
|
|
|
("schemeIs" in aURI) && (aURI.schemeIs("http") || aURI.schemeIs("https")));
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:00:14 -07:00
|
|
|
<method name="useDefaultIcon">
|
|
|
|
<parameter name="aTab"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2007-08-21 22:00:14 -07:00
|
|
|
var browser = this.getBrowserForTab(aTab);
|
2013-07-29 08:03:41 -07:00
|
|
|
var documentURI = browser.documentURI;
|
2010-09-24 00:29:50 -07:00
|
|
|
var icon = null;
|
2013-07-29 08:03:41 -07:00
|
|
|
|
|
|
|
if (browser.imageDocument) {
|
2010-03-21 02:38:08 -07:00
|
|
|
if (Services.prefs.getBoolPref("browser.chrome.site_icons")) {
|
2010-09-24 00:29:50 -07:00
|
|
|
let sz = Services.prefs.getIntPref("browser.chrome.image_icons.max_size");
|
2013-07-29 08:03:41 -07:00
|
|
|
if (browser.imageDocument.width <= sz &&
|
|
|
|
browser.imageDocument.height <= sz) {
|
|
|
|
icon = browser.currentURI;
|
|
|
|
}
|
2007-08-21 22:00:32 -07:00
|
|
|
}
|
2007-08-21 22:00:14 -07:00
|
|
|
}
|
2008-10-21 13:02:26 -07:00
|
|
|
// Use documentURIObject in the check for shouldLoadFavIcon so that we
|
|
|
|
// do the right thing with about:-style error pages. Bug 453442
|
2013-07-29 08:03:41 -07:00
|
|
|
else if (this.shouldLoadFavIcon(documentURI)) {
|
|
|
|
let url = documentURI.prePath + "/favicon.ico";
|
2007-10-09 22:03:52 -07:00
|
|
|
if (!this.isFailedIcon(url))
|
2010-09-24 00:29:50 -07:00
|
|
|
icon = url;
|
2007-08-21 22:00:14 -07:00
|
|
|
}
|
2010-09-24 00:29:50 -07:00
|
|
|
this.setIcon(aTab, icon);
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-10-09 22:03:52 -07:00
|
|
|
<method name="isFailedIcon">
|
2007-08-21 21:58:49 -07:00
|
|
|
<parameter name="aURI"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2009-07-28 22:55:18 -07:00
|
|
|
if (this.mFaviconService) {
|
|
|
|
if (!(aURI instanceof Ci.nsIURI))
|
|
|
|
aURI = makeURI(aURI);
|
2008-12-30 04:44:55 -08:00
|
|
|
return this.mFaviconService.isFailedFavicon(aURI);
|
2009-07-28 22:55:18 -07:00
|
|
|
}
|
2008-12-30 04:44:55 -08:00
|
|
|
return null;
|
2007-08-21 21:59:41 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2010-01-17 06:04:00 -08:00
|
|
|
<method name="getWindowTitleForBrowser">
|
|
|
|
<parameter name="aBrowser"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var newTitle = "";
|
2007-08-21 22:00:43 -07:00
|
|
|
var docElement = this.ownerDocument.documentElement;
|
|
|
|
var sep = docElement.getAttribute("titlemenuseparator");
|
|
|
|
|
2013-03-05 22:59:30 -08:00
|
|
|
// Strip out any null bytes in the content title, since the
|
|
|
|
// underlying widget implementations of nsWindow::SetTitle pass
|
|
|
|
// null-terminated strings to system APIs.
|
2013-03-10 19:47:07 -07:00
|
|
|
var docTitle = aBrowser.contentTitle.replace("\0", "", "g");
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 21:59:45 -07:00
|
|
|
if (!docTitle)
|
2007-08-21 22:00:43 -07:00
|
|
|
docTitle = docElement.getAttribute("titledefault");
|
2007-08-21 21:59:37 -07:00
|
|
|
|
2007-08-21 22:00:43 -07:00
|
|
|
var modifier = docElement.getAttribute("titlemodifier");
|
2007-08-21 21:58:49 -07:00
|
|
|
if (docTitle) {
|
2007-08-21 22:00:43 -07:00
|
|
|
newTitle += docElement.getAttribute("titlepreface");
|
2007-08-21 21:58:49 -07:00
|
|
|
newTitle += docTitle;
|
2007-08-21 21:59:37 -07:00
|
|
|
if (modifier)
|
|
|
|
newTitle += sep;
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
2007-08-21 21:59:16 -07:00
|
|
|
newTitle += modifier;
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:43 -07:00
|
|
|
// If location bar is hidden and the URL type supports a host,
|
|
|
|
// add the scheme and host to the title to prevent spoofing.
|
|
|
|
// XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
|
|
|
|
try {
|
2012-09-08 13:58:23 -07:00
|
|
|
if (docElement.getAttribute("chromehidden").contains("location")) {
|
2007-08-21 22:00:46 -07:00
|
|
|
var uri = this.mURIFixup.createExposableURI(
|
2010-01-17 06:04:00 -08:00
|
|
|
aBrowser.currentURI);
|
2007-08-21 22:02:33 -07:00
|
|
|
if (uri.scheme == "about")
|
|
|
|
newTitle = uri.spec + sep + newTitle;
|
|
|
|
else
|
2007-08-21 22:00:46 -07:00
|
|
|
newTitle = uri.prePath + sep + newTitle;
|
2007-08-21 22:00:43 -07:00
|
|
|
}
|
|
|
|
} catch (e) {}
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2010-01-17 06:04:00 -08:00
|
|
|
return newTitle;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="updateTitlebar">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2011-04-13 21:20:17 -07:00
|
|
|
if ("TabView" in window && TabView.isVisible()) {
|
2010-08-10 21:14:53 -07:00
|
|
|
// ToDo: this will be removed when we gain ability to draw to the menu bar.
|
|
|
|
// Bug 586175
|
2010-08-11 12:17:57 -07:00
|
|
|
this.ownerDocument.title = TabView.windowTitle;
|
2010-09-13 14:05:03 -07:00
|
|
|
}
|
|
|
|
else {
|
2010-07-15 01:41:08 -07:00
|
|
|
this.ownerDocument.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
|
|
|
|
}
|
2007-08-21 21:59:41 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="updateCurrentBrowser">
|
2008-11-15 11:47:53 -08:00
|
|
|
<parameter name="aForceUpdate"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-03-22 07:12:04 -07:00
|
|
|
var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
|
2008-11-15 11:47:53 -08:00
|
|
|
if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
|
2007-08-21 21:58:59 -07:00
|
|
|
return;
|
|
|
|
|
2012-10-11 10:54:27 -07:00
|
|
|
if (!aForceUpdate) {
|
2012-09-21 17:33:30 -07:00
|
|
|
TelemetryStopwatch.start("FX_TAB_SWITCH_UPDATE_MS");
|
2012-10-11 10:54:27 -07:00
|
|
|
window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
|
|
|
|
.beginTabSwitch();
|
|
|
|
}
|
2012-09-21 17:33:30 -07:00
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
var oldTab = this.mCurrentTab;
|
|
|
|
|
2009-10-05 21:26:15 -07:00
|
|
|
// Preview mode should not reset the owner
|
2012-12-24 08:08:22 -08:00
|
|
|
if (!this._previewMode && !oldTab.selected)
|
2009-12-12 11:31:21 -08:00
|
|
|
oldTab.owner = null;
|
2009-04-24 01:18:53 -07:00
|
|
|
|
2010-09-06 02:39:59 -07:00
|
|
|
if (this._lastRelatedTab) {
|
2012-12-24 08:08:22 -08:00
|
|
|
if (!this._lastRelatedTab.selected)
|
2010-09-06 02:39:59 -07:00
|
|
|
this._lastRelatedTab.owner = null;
|
|
|
|
this._lastRelatedTab = null;
|
|
|
|
}
|
2009-09-04 07:37:17 -07:00
|
|
|
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
var oldBrowser = this.mCurrentBrowser;
|
2010-08-05 08:27:52 -07:00
|
|
|
if (oldBrowser) {
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
oldBrowser.setAttribute("type", "content-targetable");
|
2011-06-24 14:32:27 -07:00
|
|
|
oldBrowser.docShellIsActive = false;
|
2010-08-05 08:27:52 -07:00
|
|
|
}
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2014-03-20 16:31:20 -07:00
|
|
|
var updateBlockedPopups = false;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
if (!oldBrowser ||
|
2014-03-20 16:31:20 -07:00
|
|
|
(oldBrowser.blockedPopups && !newBrowser.blockedPopups) ||
|
|
|
|
(!oldBrowser.blockedPopups && newBrowser.blockedPopups))
|
|
|
|
updateBlockedPopups = true;
|
2007-08-21 21:59:00 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
newBrowser.setAttribute("type", "content-primary");
|
2011-07-11 06:14:08 -07:00
|
|
|
newBrowser.docShellIsActive =
|
|
|
|
(window.windowState != window.STATE_MINIMIZED);
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mCurrentBrowser = newBrowser;
|
2012-12-28 23:12:00 -08:00
|
|
|
this.mCurrentTab = this.tabContainer.selectedItem;
|
2010-08-13 11:36:40 -07:00
|
|
|
this.showTab(this.mCurrentTab);
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2013-07-18 09:46:28 -07:00
|
|
|
var backForwardContainer = document.getElementById("urlbar-container");
|
2012-11-01 12:28:33 -07:00
|
|
|
if (backForwardContainer) {
|
2011-10-10 01:01:33 -07:00
|
|
|
backForwardContainer.setAttribute("switchingtabs", "true");
|
2012-11-01 12:28:33 -07:00
|
|
|
window.addEventListener("MozAfterPaint", function removeSwitchingtabsAttr() {
|
|
|
|
window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr);
|
|
|
|
backForwardContainer.removeAttribute("switchingtabs");
|
|
|
|
});
|
|
|
|
}
|
2011-10-10 01:01:33 -07:00
|
|
|
|
2013-09-12 14:36:05 -07:00
|
|
|
this._appendStatusPanel();
|
|
|
|
|
2014-03-20 16:31:20 -07:00
|
|
|
if (updateBlockedPopups)
|
|
|
|
this.mCurrentBrowser.updateBlockedPopups(false);
|
2007-08-21 21:59:00 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
// Update the URL bar.
|
|
|
|
var loc = this.mCurrentBrowser.currentURI;
|
2007-08-21 21:59:00 -07:00
|
|
|
|
2011-06-24 14:32:27 -07:00
|
|
|
// Bug 666809 - SecurityUI support for e10s
|
2013-04-24 22:29:31 -07:00
|
|
|
var webProgress = this.mCurrentBrowser.webProgress;
|
|
|
|
var securityUI = this.mCurrentBrowser.securityUI;
|
2007-08-21 22:00:50 -07:00
|
|
|
|
2013-04-24 22:29:31 -07:00
|
|
|
this._callProgressListeners(null, "onLocationChange",
|
|
|
|
[webProgress, null, loc, 0], true,
|
|
|
|
false);
|
2010-07-06 21:56:17 -07:00
|
|
|
|
2013-04-24 22:29:31 -07:00
|
|
|
if (securityUI) {
|
|
|
|
this._callProgressListeners(null, "onSecurityChange",
|
|
|
|
[webProgress, null, securityUI.state], true, false);
|
2010-07-06 21:56:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
var listener = this.mTabListeners[this.tabContainer.selectedIndex] || null;
|
|
|
|
if (listener && listener.mStateFlags) {
|
|
|
|
this._callProgressListeners(null, "onUpdateCurrentBrowser",
|
|
|
|
[listener.mStateFlags, listener.mStatus,
|
|
|
|
listener.mMessage, listener.mTotalProgress],
|
|
|
|
true, false);
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
2007-08-21 22:00:50 -07:00
|
|
|
|
2010-01-17 07:48:00 -08:00
|
|
|
if (!this._previewMode) {
|
2011-10-08 01:34:20 -07:00
|
|
|
this.mCurrentTab.removeAttribute("unread");
|
2014-02-06 08:28:54 -08:00
|
|
|
oldTab.lastAccessed = Date.now();
|
2011-10-08 01:34:20 -07:00
|
|
|
|
2013-07-05 17:56:36 -07:00
|
|
|
let oldFindBar = oldTab._findBar;
|
|
|
|
if (oldFindBar &&
|
|
|
|
oldFindBar.findMode == oldFindBar.FIND_NORMAL &&
|
|
|
|
!oldFindBar.hidden)
|
|
|
|
this._lastFindValue = oldFindBar._findField.value;
|
2010-08-10 17:21:05 -07:00
|
|
|
|
2010-01-17 07:48:00 -08:00
|
|
|
this.updateTitlebar();
|
2010-09-02 13:08:37 -07:00
|
|
|
|
|
|
|
this.mCurrentTab.removeAttribute("titlechanged");
|
2010-01-17 07:48:00 -08:00
|
|
|
}
|
2007-08-21 21:59:43 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
// If the new tab is busy, and our current state is not busy, then
|
|
|
|
// we need to fire a start to all progress listeners.
|
|
|
|
const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
|
|
|
|
if (this.mCurrentTab.hasAttribute("busy") && !this.mIsBusy) {
|
|
|
|
this.mIsBusy = true;
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners(null, "onStateChange",
|
|
|
|
[webProgress, null,
|
|
|
|
nsIWebProgressListener.STATE_START |
|
|
|
|
nsIWebProgressListener.STATE_IS_NETWORK, 0],
|
|
|
|
true, false);
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the new tab is not busy, and our current state is busy, then
|
|
|
|
// we need to fire a stop to all progress listeners.
|
|
|
|
if (!this.mCurrentTab.hasAttribute("busy") && this.mIsBusy) {
|
|
|
|
this.mIsBusy = false;
|
2010-07-06 21:56:17 -07:00
|
|
|
this._callProgressListeners(null, "onStateChange",
|
|
|
|
[webProgress, null,
|
|
|
|
nsIWebProgressListener.STATE_STOP |
|
|
|
|
nsIWebProgressListener.STATE_IS_NETWORK, 0],
|
|
|
|
true, false);
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
|
|
|
|
2012-12-24 08:08:22 -08:00
|
|
|
this._setCloseKeyState(!this.mCurrentTab.pinned);
|
2011-02-07 05:54:26 -08:00
|
|
|
|
2009-10-05 21:26:15 -07:00
|
|
|
// TabSelect events are suppressed during preview mode to avoid confusing extensions and other bits of code
|
|
|
|
// that might rely upon the other changes suppressed.
|
|
|
|
// Focus is suppressed in the event that the main browser window is minimized - focusing a tab would restore the window
|
|
|
|
if (!this._previewMode) {
|
|
|
|
// We've selected the new tab, so go ahead and notify listeners.
|
2014-02-06 19:19:12 -08:00
|
|
|
let event = new CustomEvent("TabSelect", {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: false,
|
|
|
|
detail: {
|
|
|
|
previousTab: oldTab
|
|
|
|
}
|
|
|
|
});
|
2009-10-05 21:26:15 -07:00
|
|
|
this.mCurrentTab.dispatchEvent(event);
|
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
this._tabAttrModified(oldTab);
|
|
|
|
this._tabAttrModified(this.mCurrentTab);
|
|
|
|
|
2010-11-09 01:25:07 -08:00
|
|
|
// Adjust focus
|
2011-07-01 03:18:23 -07:00
|
|
|
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
|
2010-11-09 01:25:07 -08:00
|
|
|
do {
|
2011-07-04 11:12:30 -07:00
|
|
|
// When focus is in the tab bar, retain it there.
|
|
|
|
if (document.activeElement == oldTab) {
|
|
|
|
// We need to explicitly focus the new tab, because
|
|
|
|
// tabbox.xml does this only in some cases.
|
|
|
|
this.mCurrentTab.focus();
|
|
|
|
break;
|
|
|
|
}
|
2011-04-19 14:18:17 -07:00
|
|
|
|
|
|
|
// If there's a tabmodal prompt showing, focus it.
|
|
|
|
if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
|
|
|
|
let XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
|
|
|
let prompts = newBrowser.parentNode.getElementsByTagNameNS(XUL_NS, "tabmodalprompt");
|
|
|
|
let prompt = prompts[prompts.length - 1];
|
|
|
|
prompt.Dialog.setDefaultFocus();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2010-11-09 01:25:07 -08:00
|
|
|
// Focus the location bar if it was previously focused for that tab.
|
|
|
|
// In full screen mode, only bother making the location bar visible
|
|
|
|
// if the tab is a blank one.
|
|
|
|
if (newBrowser._urlbarFocused && gURLBar) {
|
2011-05-25 01:44:28 -07:00
|
|
|
|
|
|
|
// Explicitly close the popup if the URL bar retains focus
|
|
|
|
gURLBar.closePopup();
|
|
|
|
|
2010-11-09 01:25:07 -08:00
|
|
|
if (!window.fullScreen) {
|
|
|
|
gURLBar.focus();
|
|
|
|
break;
|
|
|
|
} else if (isTabEmpty(this.mCurrentTab)) {
|
|
|
|
focusAndSelectUrlBar();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2010-04-21 07:53:42 -07:00
|
|
|
|
2013-07-11 16:42:34 -07:00
|
|
|
// If the find bar is open, focus it.
|
|
|
|
if (gFindBarInitialized && !gFindBar.hidden) {
|
|
|
|
gFindBar._findField.focus();
|
2011-02-28 11:56:56 -08:00
|
|
|
break;
|
2013-07-11 16:42:34 -07:00
|
|
|
}
|
2011-02-28 11:56:56 -08:00
|
|
|
|
2010-11-09 01:25:07 -08:00
|
|
|
// Otherwise, focus the content area.
|
|
|
|
let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager);
|
|
|
|
let focusFlags = fm.FLAG_NOSCROLL;
|
2013-04-22 19:47:52 -07:00
|
|
|
|
|
|
|
if (!gMultiProcessBrowser) {
|
|
|
|
let newFocusedElement = fm.getFocusedElementForWindow(window.content, true, {});
|
|
|
|
|
|
|
|
// for anchors, use FLAG_SHOWRING so that it is clear what link was
|
|
|
|
// last clicked when switching back to that tab
|
|
|
|
if (newFocusedElement &&
|
|
|
|
(newFocusedElement instanceof HTMLAnchorElement ||
|
|
|
|
newFocusedElement.getAttributeNS("http://www.w3.org/1999/xlink", "type") == "simple"))
|
|
|
|
focusFlags |= fm.FLAG_SHOWRING;
|
|
|
|
}
|
2010-04-21 07:53:42 -07:00
|
|
|
fm.setFocus(newBrowser, focusFlags);
|
2010-11-09 01:25:07 -08:00
|
|
|
} while (false);
|
2009-10-05 21:26:15 -07:00
|
|
|
}
|
2012-09-21 17:33:30 -07:00
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
|
|
|
|
2012-09-21 17:33:30 -07:00
|
|
|
if (!aForceUpdate)
|
|
|
|
TelemetryStopwatch.finish("FX_TAB_SWITCH_UPDATE_MS");
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
<method name="_tabAttrModified">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
2011-05-24 23:50:44 -07:00
|
|
|
if (aTab.closing)
|
2010-09-20 11:18:04 -07:00
|
|
|
return;
|
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
// This event should be dispatched when any of these attributes change:
|
|
|
|
// label, crop, busy, image, selected
|
|
|
|
var event = document.createEvent("Events");
|
|
|
|
event.initEvent("TabAttrModified", true, false);
|
|
|
|
aTab.dispatchEvent(event);
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:00:36 -07:00
|
|
|
<method name="setTabTitleLoading">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-10-12 14:25:17 -07:00
|
|
|
aTab.label = this.mStringBundle.getString("tabs.connecting");
|
2010-09-04 11:33:34 -07:00
|
|
|
aTab.crop = "end";
|
2009-12-12 11:31:21 -08:00
|
|
|
this._tabAttrModified(aTab);
|
2007-08-21 22:00:36 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="setTabTitle">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var browser = this.getBrowserForTab(aTab);
|
|
|
|
var crop = "end";
|
2007-08-21 22:02:16 -07:00
|
|
|
var title = browser.contentTitle;
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 21:59:55 -07:00
|
|
|
if (!title) {
|
|
|
|
if (browser.currentURI.spec) {
|
|
|
|
try {
|
|
|
|
title = this.mURIFixup.createExposableURI(browser.currentURI).spec;
|
|
|
|
} catch(ex) {
|
|
|
|
title = browser.currentURI.spec;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-25 14:43:27 -08:00
|
|
|
if (title && !isBlankPageURL(title)) {
|
2007-08-21 21:59:55 -07:00
|
|
|
// At this point, we now have a URI.
|
|
|
|
// Let's try to unescape it using a character set
|
|
|
|
// in case the URI is not ASCII.
|
2013-04-27 08:37:04 -07:00
|
|
|
try {
|
|
|
|
var characterSet = browser.characterSet;
|
|
|
|
const textToSubURI = Components.classes["@mozilla.org/intl/texttosuburi;1"]
|
|
|
|
.getService(Components.interfaces.nsITextToSubURI);
|
|
|
|
title = textToSubURI.unEscapeNonAsciiURI(characterSet, title);
|
|
|
|
} catch(ex) { /* Do nothing. */ }
|
2007-08-21 21:59:55 -07:00
|
|
|
|
|
|
|
crop = "center";
|
|
|
|
|
|
|
|
} else // Still no title? Fall back to our untitled string.
|
2010-03-18 00:04:42 -07:00
|
|
|
title = this.mStringBundle.getString("tabs.emptyTabTitle");
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
|
|
|
|
2010-09-04 09:51:52 -07:00
|
|
|
if (aTab.label == title &&
|
|
|
|
aTab.crop == crop)
|
|
|
|
return false;
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
aTab.label = title;
|
2010-09-04 11:33:34 -07:00
|
|
|
aTab.crop = crop;
|
2009-12-12 11:31:21 -08:00
|
|
|
this._tabAttrModified(aTab);
|
2010-09-10 01:05:36 -07:00
|
|
|
|
|
|
|
if (aTab.selected)
|
|
|
|
this.updateTitlebar();
|
|
|
|
|
2010-09-04 09:51:52 -07:00
|
|
|
return true;
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:00:28 -07:00
|
|
|
<method name="loadOneTab">
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<parameter name="aReferrerURI"/>
|
|
|
|
<parameter name="aCharset"/>
|
|
|
|
<parameter name="aPostData"/>
|
|
|
|
<parameter name="aLoadInBackground"/>
|
2007-08-21 22:01:08 -07:00
|
|
|
<parameter name="aAllowThirdPartyFixup"/>
|
2007-08-21 22:00:28 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-06-08 13:13:55 -07:00
|
|
|
var aFromExternal;
|
2009-09-14 16:33:00 -07:00
|
|
|
var aRelatedToCurrent;
|
2013-10-10 21:26:32 -07:00
|
|
|
var aDisableMCB;
|
2014-03-04 07:24:00 -08:00
|
|
|
var aSkipAnimation;
|
2009-09-14 16:33:00 -07:00
|
|
|
if (arguments.length == 2 &&
|
|
|
|
typeof arguments[1] == "object" &&
|
|
|
|
!(arguments[1] instanceof Ci.nsIURI)) {
|
|
|
|
let params = arguments[1];
|
|
|
|
aReferrerURI = params.referrerURI;
|
|
|
|
aCharset = params.charset;
|
|
|
|
aPostData = params.postData;
|
|
|
|
aLoadInBackground = params.inBackground;
|
|
|
|
aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
2010-06-08 13:13:55 -07:00
|
|
|
aFromExternal = params.fromExternal;
|
2009-09-14 16:33:00 -07:00
|
|
|
aRelatedToCurrent = params.relatedToCurrent;
|
2013-10-10 21:26:32 -07:00
|
|
|
aDisableMCB = params.disableMCB;
|
2014-03-04 07:24:00 -08:00
|
|
|
aSkipAnimation = params.skipAnimation;
|
2009-09-14 16:33:00 -07:00
|
|
|
}
|
|
|
|
|
2007-08-21 22:01:13 -07:00
|
|
|
var bgLoad = (aLoadInBackground != null) ? aLoadInBackground :
|
2010-03-21 02:38:08 -07:00
|
|
|
Services.prefs.getBoolPref("browser.tabs.loadInBackground");
|
2007-08-21 22:01:43 -07:00
|
|
|
var owner = bgLoad ? null : this.selectedTab;
|
2009-09-14 16:33:00 -07:00
|
|
|
var tab = this.addTab(aURI, {
|
|
|
|
referrerURI: aReferrerURI,
|
|
|
|
charset: aCharset,
|
|
|
|
postData: aPostData,
|
|
|
|
ownerTab: owner,
|
|
|
|
allowThirdPartyFixup: aAllowThirdPartyFixup,
|
2010-06-08 13:13:55 -07:00
|
|
|
fromExternal: aFromExternal,
|
2011-11-05 08:48:28 -07:00
|
|
|
relatedToCurrent: aRelatedToCurrent,
|
2014-03-04 07:24:00 -08:00
|
|
|
skipAnimation: aSkipAnimation,
|
2013-10-10 21:26:32 -07:00
|
|
|
disableMCB: aDisableMCB});
|
2007-08-21 22:00:54 -07:00
|
|
|
if (!bgLoad)
|
|
|
|
this.selectedTab = tab;
|
2008-02-13 02:21:54 -08:00
|
|
|
|
2007-08-21 22:00:28 -07:00
|
|
|
return tab;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
<method name="loadTabs">
|
|
|
|
<parameter name="aURIs"/>
|
|
|
|
<parameter name="aLoadInBackground"/>
|
|
|
|
<parameter name="aReplace"/>
|
|
|
|
<body><![CDATA[
|
2009-01-18 02:36:01 -08:00
|
|
|
if (!aURIs.length)
|
|
|
|
return;
|
|
|
|
|
2007-08-21 22:00:55 -07:00
|
|
|
// The tab selected after this new tab is closed (i.e. the new tab's
|
2007-08-21 22:00:54 -07:00
|
|
|
// "owner") is the next adjacent tab (i.e. not the previously viewed tab)
|
|
|
|
// when several urls are opened here (i.e. closing the first should select
|
|
|
|
// the next of many URLs opened) or if the pref to have UI links opened in
|
|
|
|
// the background is set (i.e. the link is not being opened modally)
|
|
|
|
//
|
|
|
|
// i.e.
|
|
|
|
// Number of URLs Load UI Links in BG Focus Last Viewed?
|
|
|
|
// == 1 false YES
|
|
|
|
// == 1 true NO
|
|
|
|
// > 1 false/true NO
|
2010-08-11 06:12:41 -07:00
|
|
|
var multiple = aURIs.length > 1;
|
|
|
|
var owner = multiple || aLoadInBackground ? null : this.selectedTab;
|
2007-08-21 22:00:54 -07:00
|
|
|
var firstTabAdded = null;
|
2009-01-23 03:52:14 -08:00
|
|
|
|
|
|
|
if (aReplace) {
|
|
|
|
try {
|
|
|
|
this.loadURI(aURIs[0], null, null);
|
|
|
|
} catch (e) {
|
|
|
|
// Ignore failure in case a URI is wrong, so we can continue
|
|
|
|
// opening the next ones.
|
|
|
|
}
|
|
|
|
}
|
2007-08-21 22:00:54 -07:00
|
|
|
else
|
2010-08-11 06:12:41 -07:00
|
|
|
firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple});
|
2007-08-21 22:00:54 -07:00
|
|
|
|
2010-03-22 07:12:04 -07:00
|
|
|
var tabNum = this.tabContainer.selectedIndex;
|
2008-07-10 01:21:01 -07:00
|
|
|
for (let i = 1; i < aURIs.length; ++i) {
|
2010-06-14 01:10:54 -07:00
|
|
|
let tab = this.addTab(aURIs[i], {skipAnimation: true});
|
2007-08-21 22:01:41 -07:00
|
|
|
if (aReplace)
|
|
|
|
this.moveTabTo(tab, ++tabNum);
|
|
|
|
}
|
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
if (!aLoadInBackground) {
|
|
|
|
if (firstTabAdded) {
|
|
|
|
// .selectedTab setter focuses the content area
|
|
|
|
this.selectedTab = firstTabAdded;
|
|
|
|
}
|
2007-08-21 22:00:55 -07:00
|
|
|
else
|
2012-09-19 03:59:26 -07:00
|
|
|
this.selectedBrowser.focus();
|
2007-08-21 22:00:54 -07:00
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 22:00:28 -07:00
|
|
|
|
2013-08-02 16:30:19 -07:00
|
|
|
#ifdef MAKE_E10S_WORK
|
2014-01-21 09:53:33 -08:00
|
|
|
<method name="updateBrowserRemoteness">
|
2013-08-02 16:30:19 -07:00
|
|
|
<parameter name="aBrowser"/>
|
2014-01-21 09:53:33 -08:00
|
|
|
<parameter name="aURL"/>
|
2013-08-02 16:30:19 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2014-01-21 09:53:33 -08:00
|
|
|
let shouldBeRemote = this._shouldBrowserBeRemote(aURL);
|
|
|
|
|
2013-08-02 16:30:19 -07:00
|
|
|
let isRemote = aBrowser.getAttribute("remote") == "true";
|
2014-01-21 09:53:33 -08:00
|
|
|
if (isRemote == shouldBeRemote)
|
2013-09-03 15:11:22 -07:00
|
|
|
return false;
|
2013-08-02 16:30:19 -07:00
|
|
|
|
2013-10-09 15:50:46 -07:00
|
|
|
let wasActive = document.activeElement == aBrowser;
|
|
|
|
|
2013-08-02 16:30:19 -07:00
|
|
|
// Unhook our progress listener.
|
|
|
|
let tab = this._getTabForBrowser(aBrowser);
|
|
|
|
let index = tab._tPos;
|
|
|
|
let filter = this.mTabFilters[index];
|
|
|
|
aBrowser.webProgress.removeProgressListener(filter);
|
|
|
|
|
|
|
|
// Change the "remote" attribute.
|
|
|
|
let parent = aBrowser.parentNode;
|
|
|
|
parent.removeChild(aBrowser);
|
2014-01-21 09:53:33 -08:00
|
|
|
aBrowser.setAttribute("remote", shouldBeRemote ? "true" : "false");
|
2013-08-02 16:30:19 -07:00
|
|
|
parent.appendChild(aBrowser);
|
|
|
|
|
|
|
|
// Restore the progress listener.
|
|
|
|
aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
|
2013-08-03 12:52:42 -07:00
|
|
|
|
2014-01-21 09:53:33 -08:00
|
|
|
if (shouldBeRemote)
|
2013-08-03 12:52:42 -07:00
|
|
|
tab.setAttribute("remote", "true");
|
|
|
|
else
|
|
|
|
tab.removeAttribute("remote");
|
2013-09-03 15:11:22 -07:00
|
|
|
|
2013-10-09 15:50:46 -07:00
|
|
|
if (wasActive)
|
|
|
|
aBrowser.focus();
|
|
|
|
|
2013-09-03 15:11:22 -07:00
|
|
|
return true;
|
2013-08-02 16:30:19 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<!--
|
|
|
|
Returns true if we want to load the content for this URL in a
|
|
|
|
remote process. Eventually this should just check whether aURL
|
|
|
|
is unprivileged. Right now, though, we would like to load
|
|
|
|
some unprivileged URLs (like about:neterror) in the main
|
|
|
|
process since they interact with chrome code through
|
|
|
|
BrowserOnClick.
|
|
|
|
-->
|
|
|
|
<method name="_shouldBrowserBeRemote">
|
|
|
|
<parameter name="aURL"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (!gMultiProcessBrowser)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// loadURI in browser.xml treats null as about:blank
|
|
|
|
if (!aURL)
|
|
|
|
aURL = "about:blank";
|
|
|
|
|
|
|
|
if (aURL.startsWith("about:") &&
|
|
|
|
aURL.toLowerCase() != "about:home" &&
|
|
|
|
aURL.toLowerCase() != "about:blank") {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aURL.startsWith("chrome:"))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
#endif
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="addTab">
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<parameter name="aReferrerURI"/>
|
2007-08-21 21:59:09 -07:00
|
|
|
<parameter name="aCharset"/>
|
2007-08-21 21:59:25 -07:00
|
|
|
<parameter name="aPostData"/>
|
2007-08-21 22:00:54 -07:00
|
|
|
<parameter name="aOwner"/>
|
2007-08-21 22:01:08 -07:00
|
|
|
<parameter name="aAllowThirdPartyFixup"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2013-04-25 22:41:46 -07:00
|
|
|
const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
2010-06-08 13:13:55 -07:00
|
|
|
var aFromExternal;
|
2009-09-14 16:33:00 -07:00
|
|
|
var aRelatedToCurrent;
|
2010-06-14 01:10:54 -07:00
|
|
|
var aSkipAnimation;
|
2013-10-10 21:26:32 -07:00
|
|
|
var aDisableMCB;
|
2009-09-14 16:33:00 -07:00
|
|
|
if (arguments.length == 2 &&
|
|
|
|
typeof arguments[1] == "object" &&
|
|
|
|
!(arguments[1] instanceof Ci.nsIURI)) {
|
|
|
|
let params = arguments[1];
|
|
|
|
aReferrerURI = params.referrerURI;
|
|
|
|
aCharset = params.charset;
|
|
|
|
aPostData = params.postData;
|
|
|
|
aOwner = params.ownerTab;
|
|
|
|
aAllowThirdPartyFixup = params.allowThirdPartyFixup;
|
2010-06-08 13:13:55 -07:00
|
|
|
aFromExternal = params.fromExternal;
|
2009-09-14 16:33:00 -07:00
|
|
|
aRelatedToCurrent = params.relatedToCurrent;
|
2010-06-14 01:10:54 -07:00
|
|
|
aSkipAnimation = params.skipAnimation;
|
2013-10-10 21:26:32 -07:00
|
|
|
aDisableMCB = params.disableMCB;
|
2009-09-14 16:33:00 -07:00
|
|
|
}
|
|
|
|
|
2007-08-21 22:01:25 -07:00
|
|
|
// if we're adding tabs, we're past interrupt mode, ditch the owner
|
|
|
|
if (this.mCurrentTab.owner)
|
|
|
|
this.mCurrentTab.owner = null;
|
|
|
|
|
2013-04-25 22:41:46 -07:00
|
|
|
var t = document.createElementNS(NS_XUL, "tab");
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2013-03-27 08:32:07 -07:00
|
|
|
var uriIsAboutBlank = !aURI || aURI == "about:blank";
|
2007-08-21 21:59:43 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
t.setAttribute("crop", "end");
|
2007-10-09 22:03:52 -07:00
|
|
|
t.setAttribute("onerror", "this.removeAttribute('image');");
|
2013-08-05 10:36:46 -07:00
|
|
|
t.className = "tabbrowser-tab";
|
|
|
|
|
|
|
|
#ifdef MAKE_E10S_WORK
|
|
|
|
let remote = this._shouldBrowserBeRemote(aURI);
|
|
|
|
#else
|
|
|
|
let remote = gMultiProcessBrowser;
|
|
|
|
#endif
|
2013-08-03 12:52:42 -07:00
|
|
|
if (remote)
|
|
|
|
t.setAttribute("remote", "true");
|
2007-08-21 22:01:46 -07:00
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
this.tabContainer._unlockTabSizing();
|
|
|
|
|
2010-06-14 01:10:54 -07:00
|
|
|
// When overflowing, new tabs are scrolled into view smoothly, which
|
|
|
|
// doesn't go well together with the width transition. So we skip the
|
|
|
|
// transition in that case.
|
2013-03-06 05:53:55 -08:00
|
|
|
let animate = !aSkipAnimation &&
|
|
|
|
this.tabContainer.getAttribute("overflow") != "true" &&
|
|
|
|
Services.prefs.getBoolPref("browser.tabs.animate");
|
|
|
|
if (!animate) {
|
2010-06-14 01:10:54 -07:00
|
|
|
t.setAttribute("fadein", "true");
|
|
|
|
setTimeout(function (tabContainer) {
|
|
|
|
tabContainer._handleNewTab(t);
|
|
|
|
}, 0, this.tabContainer);
|
|
|
|
}
|
|
|
|
|
2012-05-02 11:39:06 -07:00
|
|
|
// invalidate caches
|
2010-03-22 07:12:04 -07:00
|
|
|
this._browsers = null;
|
2012-05-02 11:39:06 -07:00
|
|
|
this._visibleTabs = null;
|
|
|
|
|
|
|
|
this.tabContainer.appendChild(t);
|
2007-08-21 22:01:25 -07:00
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
// If this new tab is owned by another, assert that relationship
|
2009-04-24 01:18:53 -07:00
|
|
|
if (aOwner)
|
2007-08-21 22:00:54 -07:00
|
|
|
t.owner = aOwner;
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2013-04-28 20:14:52 -07:00
|
|
|
var b = document.createElementNS(
|
|
|
|
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
|
|
|
"browser");
|
2007-08-21 22:01:01 -07:00
|
|
|
b.setAttribute("type", "content-targetable");
|
2013-04-28 20:14:52 -07:00
|
|
|
b.setAttribute("message", "true");
|
|
|
|
b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
|
|
|
|
b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
|
|
|
|
|
2013-08-02 16:30:19 -07:00
|
|
|
if (remote)
|
2013-04-28 20:14:52 -07:00
|
|
|
b.setAttribute("remote", "true");
|
2011-06-22 13:43:09 -07:00
|
|
|
|
2013-05-09 03:08:07 -07:00
|
|
|
if (window.gShowPageResizers && window.windowState == window.STATE_NORMAL) {
|
2011-01-17 06:35:32 -08:00
|
|
|
b.setAttribute("showresizer", "true");
|
|
|
|
}
|
|
|
|
|
2013-04-28 20:14:52 -07:00
|
|
|
if (this.hasAttribute("autocompletepopup"))
|
|
|
|
b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup"));
|
2013-08-25 18:34:23 -07:00
|
|
|
|
|
|
|
if (this.hasAttribute("selectpopup"))
|
|
|
|
b.setAttribute("selectpopup", this.getAttribute("selectpopup"));
|
|
|
|
|
2007-08-21 22:02:41 -07:00
|
|
|
b.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
|
2007-08-21 21:59:49 -07:00
|
|
|
|
2010-09-15 20:01:00 -07:00
|
|
|
// Create the browserStack container
|
2013-04-25 22:41:46 -07:00
|
|
|
var stack = document.createElementNS(NS_XUL, "stack");
|
2012-08-30 03:23:26 -07:00
|
|
|
stack.className = "browserStack";
|
2010-09-15 20:01:00 -07:00
|
|
|
stack.appendChild(b);
|
|
|
|
stack.setAttribute("flex", "1");
|
|
|
|
|
2012-06-01 05:53:58 -07:00
|
|
|
// Create the browserContainer
|
2013-04-25 22:41:46 -07:00
|
|
|
var browserContainer = document.createElementNS(NS_XUL, "vbox");
|
2012-08-30 03:23:26 -07:00
|
|
|
browserContainer.className = "browserContainer";
|
|
|
|
browserContainer.appendChild(stack);
|
|
|
|
browserContainer.setAttribute("flex", "1");
|
|
|
|
|
|
|
|
// Create the sidebar container
|
2013-04-25 22:41:46 -07:00
|
|
|
var browserSidebarContainer = document.createElementNS(NS_XUL,
|
|
|
|
"hbox");
|
2012-08-30 03:23:26 -07:00
|
|
|
browserSidebarContainer.className = "browserSidebarContainer";
|
|
|
|
browserSidebarContainer.appendChild(browserContainer);
|
|
|
|
browserSidebarContainer.setAttribute("flex", "1");
|
2012-06-01 05:53:58 -07:00
|
|
|
|
2007-08-21 22:00:55 -07:00
|
|
|
// Add the Message and the Browser to the box
|
2013-04-25 22:41:46 -07:00
|
|
|
var notificationbox = document.createElementNS(NS_XUL,
|
|
|
|
"notificationbox");
|
2007-08-21 22:01:12 -07:00
|
|
|
notificationbox.setAttribute("flex", "1");
|
2012-08-30 03:23:26 -07:00
|
|
|
notificationbox.appendChild(browserSidebarContainer);
|
2010-08-05 12:38:07 -07:00
|
|
|
|
|
|
|
var position = this.tabs.length - 1;
|
2013-09-28 11:07:07 -07:00
|
|
|
var uniqueId = this._generateUniquePanelID();
|
2010-08-05 12:38:07 -07:00
|
|
|
notificationbox.id = uniqueId;
|
|
|
|
t.linkedPanel = uniqueId;
|
|
|
|
t.linkedBrowser = b;
|
|
|
|
t._tPos = position;
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
2010-08-05 12:38:07 -07:00
|
|
|
|
2013-06-06 12:05:21 -07:00
|
|
|
// Prevent the superfluous initial load of a blank document
|
|
|
|
// if we're going to load something other than about:blank.
|
|
|
|
if (!uriIsAboutBlank) {
|
|
|
|
b.setAttribute("nodefaultsrc", "true");
|
|
|
|
}
|
|
|
|
|
2010-08-05 12:38:07 -07:00
|
|
|
// NB: this appendChild call causes us to run constructors for the
|
|
|
|
// browser element, which fires off a bunch of notifications. Some
|
|
|
|
// of those notifications can cause code to run that inspects our
|
|
|
|
// state, so it is important that the tab element is fully
|
|
|
|
// initialized by this point.
|
2007-08-21 22:01:12 -07:00
|
|
|
this.mPanelContainer.appendChild(notificationbox);
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2013-11-28 16:15:16 -08:00
|
|
|
// We've waited until the tab is in the DOM to set the label. This
|
|
|
|
// allows the TabLabelModified event to be properly dispatched.
|
|
|
|
if (!aURI || isBlankPageURL(aURI)) {
|
|
|
|
t.label = this.mStringBundle.getString("tabs.emptyTabTitle");
|
|
|
|
} else {
|
|
|
|
t.label = aURI;
|
|
|
|
}
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
this.tabContainer.updateVisibility();
|
2007-08-21 21:58:49 -07:00
|
|
|
|
|
|
|
// wire up a progress listener for the new browser object.
|
2013-03-27 08:32:07 -07:00
|
|
|
var tabListener = this.mTabProgressListener(t, b, uriIsAboutBlank);
|
2007-08-21 21:58:49 -07:00
|
|
|
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
|
|
|
|
.createInstance(Components.interfaces.nsIWebProgress);
|
|
|
|
filter.addProgressListener(tabListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
2013-04-24 22:29:31 -07:00
|
|
|
b.webProgress.addProgressListener(filter, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mTabListeners[position] = tabListener;
|
|
|
|
this.mTabFilters[position] = filter;
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2013-04-28 20:14:52 -07:00
|
|
|
b.droppedLinkHandler = handleDroppedLink;
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2013-05-24 03:08:31 -07:00
|
|
|
// If we just created a new tab that loads the default
|
|
|
|
// newtab url, swap in a preloaded page if possible.
|
|
|
|
// Do nothing if we're a private window.
|
|
|
|
let docShellsSwapped = false;
|
|
|
|
if (aURI == BROWSER_NEW_TAB_URL &&
|
2013-07-26 14:26:28 -07:00
|
|
|
!PrivateBrowsingUtils.isWindowPrivate(window) &&
|
|
|
|
!gMultiProcessBrowser) {
|
2013-05-24 03:08:31 -07:00
|
|
|
docShellsSwapped = gBrowserNewTabPreloader.newTab(t);
|
2014-02-25 09:51:41 -08:00
|
|
|
} else if (aURI == "about:customizing") {
|
|
|
|
docShellsSwapped = gCustomizationTabPreloader.newTab(t);
|
2013-05-24 03:08:31 -07:00
|
|
|
}
|
|
|
|
|
2013-06-19 13:07:59 -07:00
|
|
|
// Dispatch a new tab notification. We do this once we're
|
|
|
|
// entirely done, so that things are in a consistent state
|
|
|
|
// even if the event listener opens or closes tabs.
|
|
|
|
var evt = document.createEvent("Events");
|
|
|
|
evt.initEvent("TabOpen", true, false);
|
|
|
|
t.dispatchEvent(evt);
|
|
|
|
|
2013-05-24 03:08:31 -07:00
|
|
|
// If we didn't swap docShells with a preloaded browser
|
|
|
|
// then let's just continue loading the page normally.
|
|
|
|
if (!docShellsSwapped && !uriIsAboutBlank) {
|
2010-05-14 10:04:08 -07:00
|
|
|
// pretend the user typed this so it'll be available till
|
|
|
|
// the document successfully loads
|
2013-03-27 08:32:07 -07:00
|
|
|
if (aURI && gInitialPages.indexOf(aURI) == -1)
|
2012-02-17 13:26:38 -08:00
|
|
|
b.userTypedValue = aURI;
|
2010-05-14 10:04:08 -07:00
|
|
|
|
2010-06-08 13:13:55 -07:00
|
|
|
let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
2014-01-12 12:02:27 -08:00
|
|
|
if (aAllowThirdPartyFixup) {
|
2010-06-08 13:13:55 -07:00
|
|
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
|
2014-01-12 12:02:27 -08:00
|
|
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
|
|
|
|
}
|
2010-06-08 13:13:55 -07:00
|
|
|
if (aFromExternal)
|
|
|
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL;
|
2013-10-10 21:26:32 -07:00
|
|
|
if (aDisableMCB)
|
|
|
|
flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_MIXED_CONTENT;
|
2009-10-09 11:36:06 -07:00
|
|
|
try {
|
|
|
|
b.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset, aPostData);
|
2011-06-05 10:37:10 -07:00
|
|
|
} catch (ex) {
|
|
|
|
Cu.reportError(ex);
|
2009-10-09 11:36:06 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-30 20:06:49 -08:00
|
|
|
// We start our browsers out as inactive, and then maintain
|
|
|
|
// activeness in the tab switcher.
|
2011-06-24 14:32:27 -07:00
|
|
|
b.docShellIsActive = false;
|
2010-11-30 20:06:49 -08:00
|
|
|
|
2009-09-04 07:37:17 -07:00
|
|
|
// Check if we're opening a tab related to the current tab and
|
|
|
|
// move it to after the current tab.
|
|
|
|
// aReferrerURI is null or undefined if the tab is opened from
|
|
|
|
// an external application or bookmark, i.e. somewhere other
|
|
|
|
// than the current tab.
|
2011-08-03 11:39:51 -07:00
|
|
|
if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) &&
|
|
|
|
Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) {
|
2009-09-04 07:37:17 -07:00
|
|
|
let newTabPos = (this._lastRelatedTab ||
|
|
|
|
this.selectedTab)._tPos + 1;
|
2010-09-06 02:39:59 -07:00
|
|
|
if (this._lastRelatedTab)
|
|
|
|
this._lastRelatedTab.owner = null;
|
|
|
|
else
|
|
|
|
t.owner = this.selectedTab;
|
2011-08-03 11:39:51 -07:00
|
|
|
this.moveTabTo(t, newTabPos);
|
2009-09-04 07:37:17 -07:00
|
|
|
this._lastRelatedTab = t;
|
|
|
|
}
|
|
|
|
|
2013-03-06 05:53:55 -08:00
|
|
|
if (animate) {
|
2013-04-03 07:05:56 -07:00
|
|
|
mozRequestAnimationFrame(function () {
|
|
|
|
this.tabContainer._handleTabTelemetryStart(t, aURI);
|
|
|
|
|
|
|
|
// kick the animation off
|
|
|
|
t.setAttribute("fadein", "true");
|
|
|
|
|
|
|
|
// This call to adjustTabstrip is redundant but needed so that
|
|
|
|
// when opening a second tab, the first tab's close buttons
|
|
|
|
// appears immediately rather than when the transition ends.
|
2013-06-03 10:36:01 -07:00
|
|
|
if (this.tabs.length - this._removingTabs.length == 2)
|
2013-04-03 07:05:56 -07:00
|
|
|
this.tabContainer.adjustTabstrip();
|
|
|
|
}.bind(this));
|
2013-03-06 05:53:55 -08:00
|
|
|
}
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
return t;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
|
2007-08-21 21:59:41 -07:00
|
|
|
<method name="warnAboutClosingTabs">
|
2013-05-29 07:07:26 -07:00
|
|
|
<parameter name="aCloseTabs"/>
|
|
|
|
<parameter name="aTab"/>
|
2007-08-21 21:59:41 -07:00
|
|
|
<body>
|
2007-08-21 22:00:55 -07:00
|
|
|
<![CDATA[
|
2013-05-29 07:07:26 -07:00
|
|
|
var tabsToClose;
|
|
|
|
switch (aCloseTabs) {
|
|
|
|
case this.closingTabsEnum.ALL:
|
|
|
|
tabsToClose = this.tabs.length - this._removingTabs.length -
|
|
|
|
gBrowser._numPinnedTabs;
|
|
|
|
break;
|
|
|
|
case this.closingTabsEnum.OTHER:
|
|
|
|
tabsToClose = this.visibleTabs.length - 1 - gBrowser._numPinnedTabs;
|
|
|
|
break;
|
|
|
|
case this.closingTabsEnum.TO_END:
|
|
|
|
if (!aTab)
|
|
|
|
throw new Error("Required argument missing: aTab");
|
|
|
|
|
|
|
|
tabsToClose = this.getTabsToTheEndFrom(aTab).length;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw new Error("Invalid argument: " + aCloseTabs);
|
|
|
|
}
|
|
|
|
|
2013-12-13 13:55:49 -08:00
|
|
|
if (tabsToClose <= 1)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const pref = aCloseTabs == this.closingTabsEnum.ALL ?
|
|
|
|
"browser.tabs.warnOnClose" : "browser.tabs.warnOnCloseOtherTabs";
|
|
|
|
var shouldPrompt = Services.prefs.getBoolPref(pref);
|
|
|
|
if (!shouldPrompt)
|
2012-07-03 09:12:09 -07:00
|
|
|
return true;
|
2010-04-12 01:01:34 -07:00
|
|
|
|
|
|
|
var ps = Services.prompt;
|
|
|
|
|
|
|
|
// default to true: if it were false, we wouldn't get this far
|
|
|
|
var warnOnClose = { value: true };
|
|
|
|
var bundle = this.mStringBundle;
|
|
|
|
|
|
|
|
// focus the window before prompting.
|
|
|
|
// this will raise any minimized window, which will
|
|
|
|
// make it obvious which window the prompt is for and will
|
|
|
|
// solve the problem of windows "obscuring" the prompt.
|
|
|
|
// see bug #350299 for more details
|
|
|
|
window.focus();
|
2014-01-30 10:07:15 -08:00
|
|
|
var warningMessage =
|
|
|
|
PluralForm.get(tabsToClose, bundle.getString("tabs.closeWarningMultiple"))
|
|
|
|
.replace("#1", tabsToClose);
|
2010-04-12 01:01:34 -07:00
|
|
|
var buttonPressed =
|
|
|
|
ps.confirmEx(window,
|
|
|
|
bundle.getString("tabs.closeWarningTitle"),
|
2014-01-30 10:07:15 -08:00
|
|
|
warningMessage,
|
2010-04-12 01:01:34 -07:00
|
|
|
(ps.BUTTON_TITLE_IS_STRING * ps.BUTTON_POS_0)
|
|
|
|
+ (ps.BUTTON_TITLE_CANCEL * ps.BUTTON_POS_1),
|
|
|
|
bundle.getString("tabs.closeButtonMultiple"),
|
|
|
|
null, null,
|
2013-12-13 13:55:49 -08:00
|
|
|
aCloseTabs == this.closingTabsEnum.ALL ?
|
|
|
|
bundle.getString("tabs.closeWarningPromptMe") : null,
|
2010-04-12 01:01:34 -07:00
|
|
|
warnOnClose);
|
|
|
|
var reallyClose = (buttonPressed == 0);
|
2012-07-03 12:44:01 -07:00
|
|
|
|
2010-04-12 01:01:34 -07:00
|
|
|
// don't set the pref unless they press OK and it's false
|
2013-12-13 13:55:49 -08:00
|
|
|
if (aCloseTabs == this.closingTabsEnum.ALL && reallyClose && !warnOnClose.value)
|
2013-10-15 09:39:48 -07:00
|
|
|
Services.prefs.setBoolPref(pref, false);
|
2010-04-12 01:01:34 -07:00
|
|
|
|
2007-08-21 21:59:41 -07:00
|
|
|
return reallyClose;
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2013-05-29 07:07:26 -07:00
|
|
|
<method name="getTabsToTheEndFrom">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var tabsToEnd = [];
|
|
|
|
let tabs = this.visibleTabs;
|
|
|
|
for (let i = tabs.length - 1; tabs[i] != aTab && i >= 0; --i) {
|
|
|
|
tabsToEnd.push(tabs[i]);
|
|
|
|
}
|
|
|
|
return tabsToEnd.reverse();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="removeTabsToTheEndFrom">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (this.warnAboutClosingTabs(this.closingTabsEnum.TO_END, aTab)) {
|
|
|
|
let tabs = this.getTabsToTheEndFrom(aTab);
|
2013-12-13 13:55:49 -08:00
|
|
|
for (let i = tabs.length - 1; i >= 0; --i) {
|
2013-05-29 07:07:26 -07:00
|
|
|
this.removeTab(tabs[i], {animate: true});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:59:10 -07:00
|
|
|
<method name="removeAllTabsBut">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-07-22 08:51:55 -07:00
|
|
|
if (aTab.pinned)
|
|
|
|
return;
|
|
|
|
|
2013-05-29 07:07:26 -07:00
|
|
|
if (this.warnAboutClosingTabs(this.closingTabsEnum.OTHER)) {
|
2010-07-29 16:39:57 -07:00
|
|
|
let tabs = this.visibleTabs;
|
2008-10-21 12:57:26 -07:00
|
|
|
this.selectedTab = aTab;
|
2007-08-21 21:59:10 -07:00
|
|
|
|
2010-07-29 16:39:57 -07:00
|
|
|
for (let i = tabs.length - 1; i >= 0; --i) {
|
2013-12-13 13:55:49 -08:00
|
|
|
if (tabs[i] != aTab && !tabs[i].pinned)
|
2013-08-23 10:49:05 -07:00
|
|
|
this.removeTab(tabs[i], {animate: true});
|
2007-08-21 21:59:41 -07:00
|
|
|
}
|
2007-08-21 21:59:24 -07:00
|
|
|
}
|
2007-08-21 21:59:10 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="removeCurrentTab">
|
2010-08-06 13:15:18 -07:00
|
|
|
<parameter name="aParams"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-08-06 13:15:18 -07:00
|
|
|
this.removeTab(this.mCurrentTab, aParams);
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
<field name="_removingTabs">
|
|
|
|
[]
|
|
|
|
</field>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="removeTab">
|
|
|
|
<parameter name="aTab"/>
|
2010-08-06 13:15:18 -07:00
|
|
|
<parameter name="aParams"/>
|
2008-08-11 01:38:43 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2011-04-11 23:50:56 -07:00
|
|
|
if (aParams) {
|
2010-08-06 13:15:18 -07:00
|
|
|
var animate = aParams.animate;
|
2011-04-11 23:50:56 -07:00
|
|
|
var byMouse = aParams.byMouse;
|
|
|
|
}
|
2010-08-06 13:15:18 -07:00
|
|
|
|
2010-08-11 06:12:54 -07:00
|
|
|
// Handle requests for synchronously removing an already
|
|
|
|
// asynchronously closing tab.
|
|
|
|
if (!animate &&
|
2011-05-24 23:50:44 -07:00
|
|
|
aTab.closing) {
|
2010-08-11 06:12:54 -07:00
|
|
|
this._endRemoveTab(aTab);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
|
|
|
|
|
2010-08-06 13:15:18 -07:00
|
|
|
if (!this._beginRemoveTab(aTab, false, null, true))
|
|
|
|
return;
|
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse)
|
|
|
|
this.tabContainer._lockTabSizing(aTab);
|
|
|
|
else
|
|
|
|
this.tabContainer._unlockTabSizing();
|
|
|
|
|
2010-10-21 23:29:17 -07:00
|
|
|
if (!animate /* the caller didn't opt in */ ||
|
2010-08-06 13:15:18 -07:00
|
|
|
isLastTab ||
|
|
|
|
aTab.pinned ||
|
2012-02-29 14:02:34 -08:00
|
|
|
aTab.hidden ||
|
2010-10-21 23:29:17 -07:00
|
|
|
this._removingTabs.length > 3 /* don't want lots of concurrent animations */ ||
|
|
|
|
aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ ||
|
2010-11-26 03:43:16 -08:00
|
|
|
window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ ||
|
2010-08-06 13:15:18 -07:00
|
|
|
!Services.prefs.getBoolPref("browser.tabs.animate")) {
|
|
|
|
this._endRemoveTab(aTab);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-03-11 04:47:46 -07:00
|
|
|
this.tabContainer._handleTabTelemetryStart(aTab);
|
2011-12-16 20:11:57 -08:00
|
|
|
|
2010-08-06 13:15:18 -07:00
|
|
|
this._blurTab(aTab);
|
2013-03-17 14:03:08 -07:00
|
|
|
aTab.style.maxWidth = ""; // ensure that fade-out transition happens
|
2010-08-06 13:15:18 -07:00
|
|
|
aTab.removeAttribute("fadein");
|
2010-12-23 14:31:03 -08:00
|
|
|
|
2013-06-03 10:36:01 -07:00
|
|
|
if (this.tabs.length - this._removingTabs.length == 1) {
|
|
|
|
// The second tab just got closed and we will end up with a single
|
|
|
|
// one. Remove the first tab's close button immediately (if needed)
|
|
|
|
// rather than after the tabclose animation ends.
|
|
|
|
this.tabContainer.adjustTabstrip();
|
|
|
|
}
|
|
|
|
|
2010-12-23 14:31:03 -08:00
|
|
|
setTimeout(function (tab, tabbrowser) {
|
2011-01-14 02:47:38 -08:00
|
|
|
if (tab.parentNode &&
|
|
|
|
window.getComputedStyle(tab).maxWidth == "0.1px") {
|
2010-12-23 14:31:03 -08:00
|
|
|
NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)");
|
|
|
|
tabbrowser._endRemoveTab(tab);
|
|
|
|
}
|
2011-01-07 05:34:28 -08:00
|
|
|
}, 3000, aTab, this);
|
2008-08-11 01:38:43 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
<!-- Tab close requests are ignored if the window is closing anyway,
|
|
|
|
e.g. when holding Ctrl+W. -->
|
|
|
|
<field name="_windowIsClosing">
|
|
|
|
false
|
|
|
|
</field>
|
|
|
|
|
2008-08-11 01:38:43 -07:00
|
|
|
<method name="_beginRemoveTab">
|
|
|
|
<parameter name="aTab"/>
|
2009-05-14 09:46:50 -07:00
|
|
|
<parameter name="aTabWillBeMoved"/>
|
2008-10-21 11:05:51 -07:00
|
|
|
<parameter name="aCloseWindowWithLastTab"/>
|
2009-04-05 01:10:24 -07:00
|
|
|
<parameter name="aCloseWindowFastpath"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2012-02-17 04:29:25 -08:00
|
|
|
if (aTab.closing ||
|
|
|
|
aTab._pendingPermitUnload ||
|
|
|
|
this._windowIsClosing)
|
2010-08-06 13:15:18 -07:00
|
|
|
return false;
|
2009-03-24 04:47:06 -07:00
|
|
|
|
|
|
|
var browser = this.getBrowserForTab(aTab);
|
|
|
|
|
2009-05-14 09:46:50 -07:00
|
|
|
if (!aTabWillBeMoved) {
|
2009-03-24 04:47:06 -07:00
|
|
|
let ds = browser.docShell;
|
2012-02-17 04:29:25 -08:00
|
|
|
if (ds && ds.contentViewer) {
|
|
|
|
// We need to block while calling permitUnload() because it
|
|
|
|
// processes the event queue and may lead to another removeTab()
|
|
|
|
// call before permitUnload() even returned.
|
|
|
|
aTab._pendingPermitUnload = true;
|
|
|
|
let permitUnload = ds.contentViewer.permitUnload();
|
|
|
|
delete aTab._pendingPermitUnload;
|
|
|
|
|
|
|
|
if (!permitUnload)
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-17 08:06:54 -07:00
|
|
|
}
|
|
|
|
|
2008-10-21 11:05:51 -07:00
|
|
|
var closeWindow = false;
|
2009-04-25 01:09:39 -07:00
|
|
|
var newTab = false;
|
2010-08-13 07:22:31 -07:00
|
|
|
if (this.tabs.length - this._removingTabs.length == 1) {
|
2010-08-11 16:51:39 -07:00
|
|
|
closeWindow = aCloseWindowWithLastTab != null ? aCloseWindowWithLastTab :
|
|
|
|
!window.toolbar.visible ||
|
|
|
|
this.tabContainer._closeWindowWithLastTab;
|
|
|
|
|
|
|
|
// Closing the tab and replacing it with a blank one is notably slower
|
|
|
|
// than closing the window right away. If the caller opts in, take
|
|
|
|
// the fast path.
|
|
|
|
if (closeWindow &&
|
2010-08-12 03:32:07 -07:00
|
|
|
aCloseWindowFastpath &&
|
2014-02-10 12:54:10 -08:00
|
|
|
this._removingTabs.length == 0) {
|
|
|
|
// This call actually closes the window, unless the user
|
|
|
|
// cancels the operation. We are finished here in both cases.
|
|
|
|
this._windowIsClosing = window.closeWindow(true, window.warnAboutClosingWindow);
|
2010-08-11 16:51:39 -07:00
|
|
|
return null;
|
2014-02-10 12:54:10 -08:00
|
|
|
}
|
2010-08-11 16:51:39 -07:00
|
|
|
|
|
|
|
newTab = true;
|
|
|
|
}
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2011-05-24 23:50:44 -07:00
|
|
|
aTab.closing = true;
|
2009-03-24 04:47:06 -07:00
|
|
|
this._removingTabs.push(aTab);
|
2012-05-02 11:39:06 -07:00
|
|
|
this._visibleTabs = null; // invalidate cache
|
2013-09-25 10:25:53 -07:00
|
|
|
|
|
|
|
// Invalidate hovered tab state tracking for this closing tab.
|
|
|
|
if (this.tabContainer._hoveredTab == aTab)
|
|
|
|
aTab._mouseleave();
|
|
|
|
|
2011-05-18 01:04:36 -07:00
|
|
|
if (newTab)
|
2012-01-25 14:43:27 -08:00
|
|
|
this.addTab(BROWSER_NEW_TAB_URL, {skipAnimation: true});
|
2011-05-18 01:04:36 -07:00
|
|
|
else
|
|
|
|
this.tabContainer.updateVisibility();
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// We're committed to closing the tab now.
|
2007-08-21 22:01:44 -07:00
|
|
|
// Dispatch a notification.
|
|
|
|
// We dispatch it before any teardown so that event listeners can
|
|
|
|
// inspect the tab that's about to close.
|
2009-05-14 09:46:50 -07:00
|
|
|
var evt = document.createEvent("UIEvent");
|
|
|
|
evt.initUIEvent("TabClose", true, false, window, aTabWillBeMoved ? 1 : 0);
|
2007-08-21 22:01:44 -07:00
|
|
|
aTab.dispatchEvent(evt);
|
|
|
|
|
2014-01-15 06:53:20 -08:00
|
|
|
if (!aTabWillBeMoved && !gMultiProcessBrowser) {
|
2013-04-22 19:47:52 -07:00
|
|
|
// Prevent this tab from showing further dialogs, since we're closing it
|
|
|
|
var windowUtils = browser.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).
|
|
|
|
getInterface(Ci.nsIDOMWindowUtils);
|
2013-10-08 14:00:12 -07:00
|
|
|
windowUtils.disableDialogs();
|
2013-04-22 19:47:52 -07:00
|
|
|
}
|
2012-08-13 12:05:34 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
// Remove the tab's filter and progress listener.
|
2009-03-24 04:47:06 -07:00
|
|
|
const filter = this.mTabFilters[aTab._tPos];
|
2013-04-22 19:47:34 -07:00
|
|
|
|
2013-04-24 22:29:31 -07:00
|
|
|
browser.webProgress.removeProgressListener(filter);
|
2013-04-22 19:47:34 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
filter.removeProgressListener(this.mTabListeners[aTab._tPos]);
|
2009-10-01 05:31:24 -07:00
|
|
|
this.mTabListeners[aTab._tPos].destroy();
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2010-09-06 07:27:29 -07:00
|
|
|
if (browser.registeredOpenURI && !aTabWillBeMoved) {
|
2010-11-29 03:44:43 -08:00
|
|
|
this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI);
|
2010-08-13 18:52:30 -07:00
|
|
|
delete browser.registeredOpenURI;
|
|
|
|
}
|
2010-03-26 14:59:02 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
// We are no longer the primary content area.
|
2009-03-24 04:47:06 -07:00
|
|
|
browser.setAttribute("type", "content-targetable");
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2008-03-20 02:08:36 -07:00
|
|
|
// Remove this tab as the owner of any other tabs, since it's going away.
|
2010-03-22 07:12:04 -07:00
|
|
|
Array.forEach(this.tabs, function (tab) {
|
2008-08-11 01:38:43 -07:00
|
|
|
if ("owner" in tab && tab.owner == aTab)
|
2008-03-20 02:08:36 -07:00
|
|
|
// |tab| is a child of the tab we're removing, make it an orphan
|
|
|
|
tab.owner = null;
|
2009-03-24 04:47:06 -07:00
|
|
|
});
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2010-08-06 13:15:18 -07:00
|
|
|
aTab._endRemoveArgs = [closeWindow, newTab];
|
|
|
|
return true;
|
2008-08-11 01:38:43 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_endRemoveTab">
|
2010-08-06 13:15:18 -07:00
|
|
|
<parameter name="aTab"/>
|
2008-08-11 01:38:43 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-08-06 13:15:18 -07:00
|
|
|
if (!aTab || !aTab._endRemoveArgs)
|
2008-09-22 06:56:51 -07:00
|
|
|
return;
|
2010-08-06 13:15:18 -07:00
|
|
|
|
|
|
|
var [aCloseWindow, aNewTab] = aTab._endRemoveArgs;
|
|
|
|
aTab._endRemoveArgs = null;
|
|
|
|
|
|
|
|
if (this._windowIsClosing) {
|
|
|
|
aCloseWindow = false;
|
|
|
|
aNewTab = false;
|
|
|
|
}
|
2008-09-17 08:07:26 -07:00
|
|
|
|
2009-09-04 07:37:17 -07:00
|
|
|
this._lastRelatedTab = null;
|
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// update the UI early for responsiveness
|
|
|
|
aTab.collapsed = true;
|
|
|
|
this.tabContainer._fillTrailingGap();
|
|
|
|
this._blurTab(aTab);
|
|
|
|
|
|
|
|
this._removingTabs.splice(this._removingTabs.indexOf(aTab), 1);
|
|
|
|
|
|
|
|
if (aCloseWindow) {
|
|
|
|
this._windowIsClosing = true;
|
|
|
|
while (this._removingTabs.length)
|
2010-08-06 13:15:18 -07:00
|
|
|
this._endRemoveTab(this._removingTabs[0]);
|
2009-03-24 04:47:06 -07:00
|
|
|
} else if (!this._windowIsClosing) {
|
2009-10-05 06:41:24 -07:00
|
|
|
if (aNewTab)
|
|
|
|
focusAndSelectUrlBar();
|
2009-07-10 05:19:07 -07:00
|
|
|
|
|
|
|
// workaround for bug 345399
|
|
|
|
this.tabContainer.mTabstrip._updateScrollButtonsDisabledState();
|
2009-03-24 04:47:06 -07:00
|
|
|
}
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// We're going to remove the tab and the browser now.
|
|
|
|
// Clean up mTabFilters and mTabListeners now rather than in
|
|
|
|
// _beginRemoveTab, so that their size is always in sync with the
|
|
|
|
// number of tabs and browsers (the xbl destructor depends on this).
|
|
|
|
this.mTabFilters.splice(aTab._tPos, 1);
|
|
|
|
this.mTabListeners.splice(aTab._tPos, 1);
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
var browser = this.getBrowserForTab(aTab);
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2007-08-21 21:59:56 -07:00
|
|
|
// Because of the way XBL works (fields just set JS
|
|
|
|
// properties on the element) and the code we have in place
|
|
|
|
// to preserve the JS objects for any elements that have
|
|
|
|
// JS properties set on them, the browser element won't be
|
|
|
|
// destroyed until the document goes away. So we force a
|
|
|
|
// cleanup ourselves.
|
2007-08-21 21:59:58 -07:00
|
|
|
// This has to happen before we remove the child so that the
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 11:00:39 -07:00
|
|
|
// XBL implementation of nsIObserver still works.
|
2008-08-11 01:38:43 -07:00
|
|
|
browser.destroy();
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2008-08-11 01:38:43 -07:00
|
|
|
if (browser == this.mCurrentBrowser)
|
2007-12-14 16:25:17 -08:00
|
|
|
this.mCurrentBrowser = null;
|
|
|
|
|
2011-01-18 00:47:48 -08:00
|
|
|
var wasPinned = aTab.pinned;
|
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// Invalidate browsers cache, as the tab is removed from the
|
|
|
|
// tab container.
|
|
|
|
this._browsers = null;
|
2007-08-21 22:00:10 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// Remove the tab ...
|
|
|
|
this.tabContainer.removeChild(aTab);
|
2008-03-20 02:08:36 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// ... and fix up the _tPos properties immediately.
|
2010-03-22 07:12:04 -07:00
|
|
|
for (let i = aTab._tPos; i < this.tabs.length; i++)
|
|
|
|
this.tabs[i]._tPos = i;
|
2008-10-21 11:05:51 -07:00
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
if (!this._windowIsClosing) {
|
2011-01-18 00:47:48 -08:00
|
|
|
if (wasPinned)
|
|
|
|
this.tabContainer._positionPinnedTabs();
|
2010-06-24 07:29:02 -07:00
|
|
|
|
|
|
|
// update tab close buttons state
|
2009-08-15 17:34:20 -07:00
|
|
|
this.tabContainer.adjustTabstrip();
|
2013-03-17 14:03:08 -07:00
|
|
|
|
|
|
|
setTimeout(function(tabs) {
|
|
|
|
tabs._lastTabClosedByMouse = false;
|
|
|
|
}, 0, this.tabContainer);
|
2010-06-24 07:29:02 -07:00
|
|
|
}
|
2009-08-15 17:34:20 -07:00
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
// update tab positional properties and attributes
|
2009-03-24 04:47:06 -07:00
|
|
|
this.selectedTab._selected = true;
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
2009-03-24 04:47:06 -07:00
|
|
|
|
2010-07-29 23:50:08 -07:00
|
|
|
// Removing the panel requires fixing up selectedPanel immediately
|
|
|
|
// (see below), which would be hindered by the potentially expensive
|
|
|
|
// browser removal. So we remove the browser and the panel in two
|
|
|
|
// steps.
|
2012-06-01 05:53:58 -07:00
|
|
|
|
|
|
|
var panel = this.getNotificationBox(browser);
|
2010-07-29 23:50:08 -07:00
|
|
|
|
2009-03-24 04:47:06 -07:00
|
|
|
// This will unload the document. An unload handler could remove
|
|
|
|
// dependant tabs, so it's important that the tabbrowser is now in
|
|
|
|
// a consistent state (tab removed, tab positions updated, etc.).
|
2012-08-30 03:23:26 -07:00
|
|
|
browser.parentNode.removeChild(browser);
|
2008-03-20 02:08:36 -07:00
|
|
|
|
2011-06-18 04:03:41 -07:00
|
|
|
// Release the browser in case something is erroneously holding a
|
|
|
|
// reference to the tab after its removal.
|
|
|
|
aTab.linkedBrowser = null;
|
|
|
|
|
2010-07-29 23:50:08 -07:00
|
|
|
// As the browser is removed, the removal of a dependent document can
|
2009-03-24 04:47:06 -07:00
|
|
|
// cause the whole window to close. So at this point, it's possible
|
|
|
|
// that the binding is destructed.
|
2010-07-29 23:50:08 -07:00
|
|
|
if (this.mTabBox) {
|
|
|
|
let selectedPanel = this.mTabBox.selectedPanel;
|
|
|
|
|
|
|
|
this.mPanelContainer.removeChild(panel);
|
|
|
|
|
|
|
|
// Under the hood, a selectedIndex attribute controls which panel
|
|
|
|
// is displayed. Removing a panel A which precedes the selected
|
|
|
|
// panel B makes selectedIndex point to the panel next to B. We
|
|
|
|
// need to explicitly preserve B as the selected panel.
|
|
|
|
this.mTabBox.selectedPanel = selectedPanel;
|
|
|
|
}
|
2007-08-21 21:59:56 -07:00
|
|
|
|
2008-10-21 11:05:51 -07:00
|
|
|
if (aCloseWindow)
|
2013-01-14 22:06:55 -08:00
|
|
|
this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow);
|
2009-03-24 04:47:06 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_blurTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2012-12-24 08:08:22 -08:00
|
|
|
if (!aTab.selected)
|
2009-03-24 04:47:06 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (aTab.owner &&
|
2011-01-17 01:54:32 -08:00
|
|
|
!aTab.owner.hidden &&
|
2011-05-24 23:50:44 -07:00
|
|
|
!aTab.owner.closing &&
|
2010-03-21 02:38:08 -07:00
|
|
|
Services.prefs.getBoolPref("browser.tabs.selectOwnerOnClose")) {
|
2009-03-24 04:47:06 -07:00
|
|
|
this.selectedTab = aTab.owner;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-08-17 11:39:17 -07:00
|
|
|
// Switch to a visible tab unless there aren't any others remaining
|
|
|
|
let remainingTabs = this.visibleTabs;
|
|
|
|
let numTabs = remainingTabs.length;
|
|
|
|
if (numTabs == 0 || numTabs == 1 && remainingTabs[0] == aTab) {
|
|
|
|
remainingTabs = Array.filter(this.tabs, function(tab) {
|
2011-05-24 23:50:44 -07:00
|
|
|
return !tab.closing;
|
2010-08-17 11:39:17 -07:00
|
|
|
}, this);
|
2010-07-29 16:39:57 -07:00
|
|
|
}
|
2010-07-29 16:39:57 -07:00
|
|
|
|
|
|
|
// Try to find a remaining tab that comes after the given tab
|
|
|
|
var tab = aTab;
|
2009-03-24 04:47:06 -07:00
|
|
|
do {
|
|
|
|
tab = tab.nextSibling;
|
2010-07-29 16:39:57 -07:00
|
|
|
} while (tab && remainingTabs.indexOf(tab) == -1);
|
2009-03-24 04:47:06 -07:00
|
|
|
|
|
|
|
if (!tab) {
|
|
|
|
tab = aTab;
|
|
|
|
|
|
|
|
do {
|
|
|
|
tab = tab.previousSibling;
|
2010-07-29 16:39:57 -07:00
|
|
|
} while (tab && remainingTabs.indexOf(tab) == -1);
|
2009-03-24 04:47:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
this.selectedTab = tab;
|
2008-08-11 01:38:43 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2012-08-13 09:30:18 -07:00
|
|
|
<method name="swapNewTabWithBrowser">
|
|
|
|
<parameter name="aNewTab"/>
|
|
|
|
<parameter name="aBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
// The browser must be standalone.
|
|
|
|
if (aBrowser.getTabBrowser())
|
|
|
|
throw Cr.NS_ERROR_INVALID_ARG;
|
|
|
|
|
|
|
|
// The tab is definitely not loading.
|
|
|
|
aNewTab.removeAttribute("busy");
|
2012-12-24 08:08:22 -08:00
|
|
|
if (aNewTab.selected) {
|
2012-08-13 09:30:18 -07:00
|
|
|
this.mIsBusy = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._swapBrowserDocShells(aNewTab, aBrowser);
|
|
|
|
|
|
|
|
// Update the new tab's title.
|
|
|
|
this.setTabTitle(aNewTab);
|
|
|
|
|
2012-12-24 08:08:22 -08:00
|
|
|
if (aNewTab.selected) {
|
2012-08-13 09:30:18 -07:00
|
|
|
this.updateCurrentBrowser(true);
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2008-08-11 01:38:43 -07:00
|
|
|
<method name="swapBrowsersAndCloseOther">
|
|
|
|
<parameter name="aOurTab"/>
|
|
|
|
<parameter name="aOtherTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2012-12-02 12:57:06 -08:00
|
|
|
// Do not allow transfering a private tab to a non-private window
|
|
|
|
// and vice versa.
|
|
|
|
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
|
|
|
|
PrivateBrowsingUtils.isWindowPrivate(aOtherTab.ownerDocument.defaultView))
|
|
|
|
return;
|
|
|
|
|
2009-04-16 07:44:07 -07:00
|
|
|
// That's gBrowser for the other window, not the tab's browser!
|
2010-08-06 13:15:18 -07:00
|
|
|
var remoteBrowser = aOtherTab.ownerDocument.defaultView.gBrowser;
|
2013-02-22 09:41:23 -08:00
|
|
|
var isPending = aOtherTab.hasAttribute("pending");
|
2008-08-11 01:38:43 -07:00
|
|
|
|
|
|
|
// First, start teardown of the other browser. Make sure to not
|
2008-10-21 11:05:51 -07:00
|
|
|
// fire the beforeunload event in the process. Close the other
|
|
|
|
// window if this was its last tab.
|
2010-08-06 13:15:18 -07:00
|
|
|
if (!remoteBrowser._beginRemoveTab(aOtherTab, true, true))
|
|
|
|
return;
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2012-08-13 09:30:18 -07:00
|
|
|
let ourBrowser = this.getBrowserForTab(aOurTab);
|
|
|
|
let otherBrowser = aOtherTab.linkedBrowser;
|
2009-04-16 07:44:07 -07:00
|
|
|
|
2013-02-22 09:41:23 -08:00
|
|
|
// If the other tab is pending (i.e. has not been restored, yet)
|
|
|
|
// then do not switch docShells but retrieve the other tab's state
|
|
|
|
// and apply it to our tab.
|
|
|
|
if (isPending) {
|
2013-08-27 15:52:28 -07:00
|
|
|
SessionStore.setTabState(aOurTab, SessionStore.getTabState(aOtherTab));
|
2013-02-22 09:41:23 -08:00
|
|
|
|
|
|
|
// Make sure to unregister any open URIs.
|
|
|
|
this._swapRegisteredOpenURIs(ourBrowser, otherBrowser);
|
|
|
|
} else {
|
|
|
|
// Workarounds for bug 458697
|
|
|
|
// Icon might have been set on DOMLinkAdded, don't override that.
|
|
|
|
if (!ourBrowser.mIconURL && otherBrowser.mIconURL)
|
|
|
|
this.setIcon(aOurTab, otherBrowser.mIconURL);
|
|
|
|
var isBusy = aOtherTab.hasAttribute("busy");
|
|
|
|
if (isBusy) {
|
|
|
|
aOurTab.setAttribute("busy", "true");
|
|
|
|
this._tabAttrModified(aOurTab);
|
|
|
|
if (aOurTab.selected)
|
|
|
|
this.mIsBusy = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._swapBrowserDocShells(aOurTab, otherBrowser);
|
|
|
|
}
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2013-07-05 17:56:36 -07:00
|
|
|
// Handle findbar data (if any)
|
|
|
|
let otherFindBar = aOtherTab._findBar;
|
|
|
|
if (otherFindBar &&
|
|
|
|
otherFindBar.findMode == otherFindBar.FIND_NORMAL) {
|
|
|
|
let ourFindBar = this.getFindBar(aOurTab);
|
|
|
|
ourFindBar._findField.value = otherFindBar._findField.value;
|
2013-07-18 13:00:46 -07:00
|
|
|
if (!otherFindBar.hidden)
|
|
|
|
ourFindBar.onFindCommand();
|
2013-07-05 17:56:36 -07:00
|
|
|
}
|
|
|
|
|
2008-08-11 01:38:43 -07:00
|
|
|
// Finish tearing down the tab that's going away.
|
2010-08-06 13:15:18 -07:00
|
|
|
remoteBrowser._endRemoveTab(aOtherTab);
|
2008-08-11 01:38:43 -07:00
|
|
|
|
2009-04-16 07:44:07 -07:00
|
|
|
if (isBusy)
|
|
|
|
this.setTabTitleLoading(aOurTab);
|
|
|
|
else
|
|
|
|
this.setTabTitle(aOurTab);
|
2008-11-15 11:47:53 -08:00
|
|
|
|
2009-01-22 19:00:54 -08:00
|
|
|
// If the tab was already selected (this happpens in the scenario
|
|
|
|
// of replaceTabWithWindow), notify onLocationChange, etc.
|
2012-12-24 08:08:22 -08:00
|
|
|
if (aOurTab.selected)
|
2008-11-15 11:47:53 -08:00
|
|
|
this.updateCurrentBrowser(true);
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2012-08-13 09:30:18 -07:00
|
|
|
<method name="_swapBrowserDocShells">
|
|
|
|
<parameter name="aOurTab"/>
|
|
|
|
<parameter name="aOtherBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
// Unhook our progress listener
|
|
|
|
let index = aOurTab._tPos;
|
|
|
|
const filter = this.mTabFilters[index];
|
|
|
|
let tabListener = this.mTabListeners[index];
|
|
|
|
let ourBrowser = this.getBrowserForTab(aOurTab);
|
|
|
|
ourBrowser.webProgress.removeProgressListener(filter);
|
|
|
|
filter.removeProgressListener(tabListener);
|
|
|
|
|
2013-02-22 09:41:23 -08:00
|
|
|
// Make sure to unregister any open URIs.
|
|
|
|
this._swapRegisteredOpenURIs(ourBrowser, aOtherBrowser);
|
2012-08-13 09:30:18 -07:00
|
|
|
|
2013-10-29 08:44:25 -07:00
|
|
|
// Give others a chance to swap state.
|
|
|
|
let event = new CustomEvent("SwapDocShells", {"detail": aOtherBrowser});
|
|
|
|
ourBrowser.dispatchEvent(event);
|
|
|
|
|
2012-08-13 09:30:18 -07:00
|
|
|
// Swap the docshells
|
|
|
|
ourBrowser.swapDocShells(aOtherBrowser);
|
|
|
|
|
|
|
|
// Restore the progress listener
|
|
|
|
this.mTabListeners[index] = tabListener =
|
|
|
|
this.mTabProgressListener(aOurTab, ourBrowser, false);
|
|
|
|
|
|
|
|
const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
|
|
|
|
filter.addProgressListener(tabListener, notifyAll);
|
|
|
|
ourBrowser.webProgress.addProgressListener(filter, notifyAll);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2013-02-22 09:41:23 -08:00
|
|
|
<method name="_swapRegisteredOpenURIs">
|
|
|
|
<parameter name="aOurBrowser"/>
|
|
|
|
<parameter name="aOtherBrowser"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
// If the current URI is registered as open remove it from the list.
|
|
|
|
if (aOurBrowser.registeredOpenURI) {
|
|
|
|
this._placesAutocomplete.unregisterOpenPage(aOurBrowser.registeredOpenURI);
|
|
|
|
delete aOurBrowser.registeredOpenURI;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the other/new URI is registered as open then copy it over.
|
|
|
|
if (aOtherBrowser.registeredOpenURI) {
|
|
|
|
aOurBrowser.registeredOpenURI = aOtherBrowser.registeredOpenURI;
|
|
|
|
delete aOtherBrowser.registeredOpenURI;
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="reloadAllTabs">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-07-29 16:39:57 -07:00
|
|
|
let tabs = this.visibleTabs;
|
|
|
|
let l = tabs.length;
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
for (var i = 0; i < l; i++) {
|
|
|
|
try {
|
2010-07-29 16:39:57 -07:00
|
|
|
this.getBrowserForTab(tabs[i]).reload();
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
} catch (e) {
|
|
|
|
// ignore failure to reload so others will be reloaded
|
|
|
|
}
|
|
|
|
}
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="reloadTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
bug 213228: new toolkit independence bug, part 7: update and use the new toolkit widgetry. tabbrowser.xml: bug 205341, 112697, 210760 by jag, bug 121234, 133503 by neil, bug 206668 by shliang. not ported: bug 169589, [mac] ctrl-tab no longer moves btwn frames bug 203960, go back group bug 104778, remember what user typed when switching tabs. bug 103720, prefill URI when opening new tab.
2007-08-21 21:59:18 -07:00
|
|
|
this.getBrowserForTab(aTab).reload();
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="addProgressListener">
|
|
|
|
<parameter name="aListener"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2011-03-25 11:50:00 -07:00
|
|
|
if (arguments.length != 1) {
|
|
|
|
Components.utils.reportError("gBrowser.addProgressListener was " +
|
|
|
|
"called with a second argument, " +
|
|
|
|
"which is not supported. See bug " +
|
2013-08-16 18:12:47 -07:00
|
|
|
"608628. Call stack: " + new Error().stack);
|
2011-03-25 11:50:00 -07:00
|
|
|
}
|
2011-03-23 04:35:21 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mProgressListeners.push(aListener);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="removeProgressListener">
|
|
|
|
<parameter name="aListener"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-07-06 21:56:17 -07:00
|
|
|
this.mProgressListeners =
|
|
|
|
this.mProgressListeners.filter(function (l) l != aListener);
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2008-11-18 02:53:25 -08:00
|
|
|
<method name="addTabsProgressListener">
|
|
|
|
<parameter name="aListener"/>
|
|
|
|
<body>
|
|
|
|
this.mTabsProgressListeners.push(aListener);
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="removeTabsProgressListener">
|
|
|
|
<parameter name="aListener"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-07-06 21:56:17 -07:00
|
|
|
this.mTabsProgressListeners =
|
|
|
|
this.mTabsProgressListeners.filter(function (l) l != aListener);
|
2008-11-18 02:53:25 -08:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<method name="getBrowserForTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2007-08-21 22:00:10 -07:00
|
|
|
return aTab.linkedBrowser;
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
2008-09-02 01:50:22 -07:00
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2010-07-29 16:39:57 -07:00
|
|
|
<method name="showOnlyTheseTabs">
|
|
|
|
<parameter name="aTabs"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
Array.forEach(this.tabs, function(tab) {
|
2010-08-13 11:36:40 -07:00
|
|
|
if (aTabs.indexOf(tab) == -1)
|
|
|
|
this.hideTab(tab);
|
|
|
|
else
|
|
|
|
this.showTab(tab);
|
|
|
|
}, this);
|
2011-12-02 08:31:12 -08:00
|
|
|
|
2012-10-25 10:59:33 -07:00
|
|
|
this.tabContainer._handleTabSelect(false);
|
2010-08-13 11:36:40 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="showTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (aTab.hidden) {
|
2010-10-11 10:27:05 -07:00
|
|
|
aTab.removeAttribute("hidden");
|
2012-05-02 11:39:06 -07:00
|
|
|
this._visibleTabs = null; // invalidate cache
|
|
|
|
|
2010-11-26 00:39:07 -08:00
|
|
|
this.tabContainer.adjustTabstrip();
|
2012-05-02 11:39:06 -07:00
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
|
|
|
|
2010-08-13 11:36:40 -07:00
|
|
|
let event = document.createEvent("Events");
|
|
|
|
event.initEvent("TabShow", true, false);
|
|
|
|
aTab.dispatchEvent(event);
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="hideTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-08-17 11:39:17 -07:00
|
|
|
if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
|
2011-05-24 23:50:44 -07:00
|
|
|
!aTab.closing) {
|
2010-10-11 10:27:05 -07:00
|
|
|
aTab.setAttribute("hidden", "true");
|
2012-05-02 11:39:06 -07:00
|
|
|
this._visibleTabs = null; // invalidate cache
|
|
|
|
|
2010-11-26 00:39:07 -08:00
|
|
|
this.tabContainer.adjustTabstrip();
|
2012-05-02 11:39:06 -07:00
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
|
|
|
|
2010-08-13 11:36:40 -07:00
|
|
|
let event = document.createEvent("Events");
|
|
|
|
event.initEvent("TabHide", true, false);
|
|
|
|
aTab.dispatchEvent(event);
|
|
|
|
}
|
2010-07-29 16:39:57 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2008-09-02 01:50:22 -07:00
|
|
|
<method name="selectTabAtIndex">
|
|
|
|
<parameter name="aIndex"/>
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-07-29 16:39:57 -07:00
|
|
|
let tabs = this.visibleTabs;
|
|
|
|
|
2008-09-02 01:50:22 -07:00
|
|
|
// count backwards for aIndex < 0
|
|
|
|
if (aIndex < 0)
|
2010-07-29 16:39:57 -07:00
|
|
|
aIndex += tabs.length;
|
2008-09-02 01:50:22 -07:00
|
|
|
|
2010-07-29 16:39:57 -07:00
|
|
|
if (aIndex >= 0 && aIndex < tabs.length)
|
|
|
|
this.selectedTab = tabs[aIndex];
|
2008-09-02 01:50:22 -07:00
|
|
|
|
|
|
|
if (aEvent) {
|
|
|
|
aEvent.preventDefault();
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
}
|
|
|
|
]]>
|
2007-08-21 21:58:49 -07:00
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<property name="selectedTab">
|
|
|
|
<getter>
|
2012-12-28 23:12:00 -08:00
|
|
|
return this.mCurrentTab;
|
2007-08-21 21:58:49 -07:00
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
2007-08-21 22:00:27 -07:00
|
|
|
// Update the tab
|
|
|
|
this.mTabBox.selectedTab = val;
|
|
|
|
return val;
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<property name="selectedBrowser"
|
|
|
|
onget="return this.mCurrentBrowser;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
<property name="browsers" readonly="true">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
2008-09-02 05:15:06 -07:00
|
|
|
return this._browsers ||
|
2010-03-22 07:12:04 -07:00
|
|
|
(this._browsers = Array.map(this.tabs, function (tab) tab.linkedBrowser));
|
2007-08-21 22:00:10 -07:00
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
</property>
|
2012-05-02 11:39:06 -07:00
|
|
|
<field name="_browsers">null</field>
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2009-03-07 08:03:32 -08:00
|
|
|
<!-- Moves a tab to a new browser window, unless it's already the only tab
|
|
|
|
in the current window, in which case this will do nothing. -->
|
2009-01-22 19:00:54 -08:00
|
|
|
<method name="replaceTabWithWindow">
|
2008-11-15 11:47:53 -08:00
|
|
|
<parameter name="aTab"/>
|
2011-07-04 03:51:47 -07:00
|
|
|
<parameter name="aOptions"/>
|
2008-11-15 11:47:53 -08:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-11-10 00:38:08 -08:00
|
|
|
if (this.tabs.length == 1)
|
2009-05-15 06:44:05 -07:00
|
|
|
return null;
|
2009-03-07 08:03:32 -08:00
|
|
|
|
2014-02-20 14:42:33 -08:00
|
|
|
let event = new CustomEvent("TabBecomingWindow", {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: true
|
|
|
|
});
|
|
|
|
aTab.dispatchEvent(event);
|
|
|
|
if (event.defaultPrevented) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2011-07-04 03:51:47 -07:00
|
|
|
var options = "chrome,dialog=no,all";
|
|
|
|
for (var name in aOptions)
|
|
|
|
options += "," + name + "=" + aOptions[name];
|
|
|
|
|
2008-11-15 11:47:53 -08:00
|
|
|
// tell a new window to take the "dropped" tab
|
2011-07-04 03:51:47 -07:00
|
|
|
return window.openDialog(getBrowserURL(), "_blank", options, aTab);
|
2008-11-15 11:47:53 -08:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
<method name="moveTabTo">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<parameter name="aIndex"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2010-02-04 23:33:46 -08:00
|
|
|
var oldPosition = aTab._tPos;
|
|
|
|
if (oldPosition == aIndex)
|
|
|
|
return;
|
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
// Don't allow mixing pinned and unpinned tabs.
|
|
|
|
if (aTab.pinned)
|
|
|
|
aIndex = Math.min(aIndex, this._numPinnedTabs - 1);
|
|
|
|
else
|
|
|
|
aIndex = Math.max(aIndex, this._numPinnedTabs);
|
|
|
|
if (oldPosition == aIndex)
|
|
|
|
return;
|
|
|
|
|
2009-09-04 07:37:17 -07:00
|
|
|
this._lastRelatedTab = null;
|
2010-06-24 07:29:02 -07:00
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
this.mTabFilters.splice(aIndex, 0, this.mTabFilters.splice(aTab._tPos, 1)[0]);
|
|
|
|
this.mTabListeners.splice(aIndex, 0, this.mTabListeners.splice(aTab._tPos, 1)[0]);
|
|
|
|
|
2012-12-24 06:29:15 -08:00
|
|
|
let wasFocused = (document.activeElement == this.mCurrentTab);
|
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
aIndex = aIndex < aTab._tPos ? aIndex: aIndex+1;
|
2007-08-21 22:02:31 -07:00
|
|
|
this.mCurrentTab._selected = false;
|
2012-05-02 11:39:06 -07:00
|
|
|
|
|
|
|
// invalidate caches
|
|
|
|
this._browsers = null;
|
|
|
|
this._visibleTabs = null;
|
|
|
|
|
2007-08-21 22:02:19 -07:00
|
|
|
// use .item() instead of [] because dragging to the end of the strip goes out of
|
|
|
|
// bounds: .item() returns null (so it acts like appendChild), but [] throws
|
2010-03-22 07:12:04 -07:00
|
|
|
this.tabContainer.insertBefore(aTab, this.tabs.item(aIndex));
|
2007-08-21 22:00:44 -07:00
|
|
|
|
2010-03-22 07:12:04 -07:00
|
|
|
for (let i = 0; i < this.tabs.length; i++) {
|
|
|
|
this.tabs[i]._tPos = i;
|
|
|
|
this.tabs[i]._selected = false;
|
2007-08-21 22:00:10 -07:00
|
|
|
}
|
2007-08-21 22:02:31 -07:00
|
|
|
this.mCurrentTab._selected = true;
|
2012-12-24 06:29:15 -08:00
|
|
|
|
|
|
|
if (wasFocused)
|
|
|
|
this.mCurrentTab.focus();
|
|
|
|
|
2012-10-25 10:59:33 -07:00
|
|
|
this.tabContainer._handleTabSelect(false);
|
2007-08-21 22:01:25 -07:00
|
|
|
|
2010-06-24 07:29:02 -07:00
|
|
|
if (aTab.pinned)
|
|
|
|
this.tabContainer._positionPinnedTabs();
|
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
this.tabContainer._setPositionalAttributes();
|
|
|
|
|
2007-08-21 22:01:25 -07:00
|
|
|
var evt = document.createEvent("UIEvents");
|
|
|
|
evt.initUIEvent("TabMove", true, false, window, oldPosition);
|
|
|
|
aTab.dispatchEvent(evt);
|
2007-08-21 22:00:10 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="moveTabForward">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2012-12-24 09:02:37 -08:00
|
|
|
let nextTab = this.mCurrentTab.nextSibling;
|
|
|
|
while (nextTab && nextTab.hidden)
|
|
|
|
nextTab = nextTab.nextSibling;
|
|
|
|
|
|
|
|
if (nextTab)
|
|
|
|
this.moveTabTo(this.mCurrentTab, nextTab._tPos);
|
2007-08-21 22:00:10 -07:00
|
|
|
else if (this.arrowKeysShouldWrap)
|
|
|
|
this.moveTabToStart();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="moveTabBackward">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2012-12-24 09:02:37 -08:00
|
|
|
let previousTab = this.mCurrentTab.previousSibling;
|
|
|
|
while (previousTab && previousTab.hidden)
|
|
|
|
previousTab = previousTab.previousSibling;
|
|
|
|
|
|
|
|
if (previousTab)
|
|
|
|
this.moveTabTo(this.mCurrentTab, previousTab._tPos);
|
2007-08-21 22:00:10 -07:00
|
|
|
else if (this.arrowKeysShouldWrap)
|
|
|
|
this.moveTabToEnd();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="moveTabToStart">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var tabPos = this.mCurrentTab._tPos;
|
2012-12-24 06:29:15 -08:00
|
|
|
if (tabPos > 0)
|
2007-08-21 22:00:10 -07:00
|
|
|
this.moveTabTo(this.mCurrentTab, 0);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
<method name="moveTabToEnd">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var tabPos = this.mCurrentTab._tPos;
|
2012-12-24 06:29:15 -08:00
|
|
|
if (tabPos < this.browsers.length - 1)
|
|
|
|
this.moveTabTo(this.mCurrentTab, this.browsers.length - 1);
|
2007-08-21 22:00:10 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:10 -07:00
|
|
|
<method name="moveTabOver">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
var direction = window.getComputedStyle(this.parentNode, null).direction;
|
|
|
|
if ((direction == "ltr" && aEvent.keyCode == KeyEvent.DOM_VK_RIGHT) ||
|
|
|
|
(direction == "rtl" && aEvent.keyCode == KeyEvent.DOM_VK_LEFT))
|
|
|
|
this.moveTabForward();
|
|
|
|
else
|
|
|
|
this.moveTabBackward();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-12-12 05:19:50 -08:00
|
|
|
<method name="duplicateTab">
|
|
|
|
<parameter name="aTab"/><!-- can be from a different window as well -->
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2013-08-27 15:52:28 -07:00
|
|
|
return SessionStore.duplicateTab(window, aTab);
|
2007-12-12 05:19:50 -08:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<!-- BEGIN FORWARDED BROWSER PROPERTIES. IF YOU ADD A PROPERTY TO THE BROWSER ELEMENT
|
|
|
|
MAKE SURE TO ADD IT HERE AS WELL. -->
|
|
|
|
<property name="canGoBack"
|
|
|
|
onget="return this.mCurrentBrowser.canGoBack;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="canGoForward"
|
|
|
|
onget="return this.mCurrentBrowser.canGoForward;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<method name="goBack">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.goBack();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="goForward">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.goForward();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="reload">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.reload();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="reloadWithFlags">
|
|
|
|
<parameter name="aFlags"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.reloadWithFlags(aFlags);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="stop">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.stop();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<!-- throws exception for unknown schemes -->
|
|
|
|
<method name="loadURI">
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<parameter name="aReferrerURI"/>
|
2007-08-21 21:59:09 -07:00
|
|
|
<parameter name="aCharset"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2013-08-02 16:30:19 -07:00
|
|
|
#ifdef MAKE_E10S_WORK
|
2014-01-21 09:53:33 -08:00
|
|
|
this.updateBrowserRemoteness(this.mCurrentBrowser, aURI);
|
2013-08-02 16:30:19 -07:00
|
|
|
try {
|
|
|
|
#endif
|
2007-08-21 21:59:09 -07:00
|
|
|
return this.mCurrentBrowser.loadURI(aURI, aReferrerURI, aCharset);
|
2013-08-02 16:30:19 -07:00
|
|
|
#ifdef MAKE_E10S_WORK
|
|
|
|
} catch (e) {
|
|
|
|
let url = this.mCurrentBrowser.currentURI.spec;
|
2014-01-21 09:53:33 -08:00
|
|
|
this.updateBrowserRemoteness(this.mCurrentBrowser, url);
|
2013-08-07 10:52:06 -07:00
|
|
|
throw e;
|
2013-08-02 16:30:19 -07:00
|
|
|
}
|
|
|
|
#endif
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<!-- throws exception for unknown schemes -->
|
|
|
|
<method name="loadURIWithFlags">
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<parameter name="aFlags"/>
|
|
|
|
<parameter name="aReferrerURI"/>
|
2007-08-21 21:59:09 -07:00
|
|
|
<parameter name="aCharset"/>
|
2008-01-18 08:57:14 -08:00
|
|
|
<parameter name="aPostData"/>
|
2007-08-21 21:58:49 -07:00
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2013-08-02 16:30:19 -07:00
|
|
|
#ifdef MAKE_E10S_WORK
|
2014-01-21 09:53:33 -08:00
|
|
|
this.updateBrowserRemoteness(this.mCurrentBrowser, aURI);
|
2013-08-02 16:30:19 -07:00
|
|
|
try {
|
|
|
|
#endif
|
2008-01-18 08:57:14 -08:00
|
|
|
return this.mCurrentBrowser.loadURIWithFlags(aURI, aFlags, aReferrerURI, aCharset, aPostData);
|
2013-08-02 16:30:19 -07:00
|
|
|
#ifdef MAKE_E10S_WORK
|
|
|
|
} catch (e) {
|
|
|
|
let url = this.mCurrentBrowser.currentURI.spec;
|
2014-01-21 09:53:33 -08:00
|
|
|
this.updateBrowserRemoteness(this.mCurrentBrowser, url);
|
2013-08-07 10:52:06 -07:00
|
|
|
throw e;
|
2013-08-02 16:30:19 -07:00
|
|
|
}
|
|
|
|
#endif
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="goHome">
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.goHome();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<property name="homePage">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.homePage;
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
<![CDATA[
|
|
|
|
this.mCurrentBrowser.homePage = val;
|
|
|
|
return val;
|
|
|
|
]]>
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
|
|
|
|
<method name="gotoIndex">
|
|
|
|
<parameter name="aIndex"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
return this.mCurrentBrowser.gotoIndex(aIndex);
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 21:59:06 -07:00
|
|
|
<method name="attachFormFill">
|
|
|
|
<body><![CDATA[
|
2007-08-21 21:59:41 -07:00
|
|
|
for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) {
|
|
|
|
var cb = this.getBrowserAtIndex(i);
|
2007-08-21 21:59:15 -07:00
|
|
|
cb.attachFormFill();
|
|
|
|
}
|
2007-08-21 21:59:06 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="detachFormFill">
|
|
|
|
<body><![CDATA[
|
2007-08-21 21:59:41 -07:00
|
|
|
for (var i = 0; i < this.mPanelContainer.childNodes.length; ++i) {
|
|
|
|
var cb = this.getBrowserAtIndex(i);
|
2007-08-21 21:59:15 -07:00
|
|
|
cb.detachFormFill();
|
|
|
|
}
|
2007-08-21 21:59:06 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 21:58:49 -07:00
|
|
|
|
|
|
|
<property name="currentURI"
|
|
|
|
onget="return this.mCurrentBrowser.currentURI;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2013-09-13 07:41:23 -07:00
|
|
|
<property name="finder"
|
|
|
|
onget="return this.mCurrentBrowser.finder"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<property name="docShell"
|
|
|
|
onget="return this.mCurrentBrowser.docShell"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="webNavigation"
|
|
|
|
onget="return this.mCurrentBrowser.webNavigation"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="webBrowserFind"
|
|
|
|
readonly="true"
|
|
|
|
onget="return this.mCurrentBrowser.webBrowserFind"/>
|
|
|
|
|
|
|
|
<property name="webProgress"
|
|
|
|
readonly="true"
|
|
|
|
onget="return this.mCurrentBrowser.webProgress"/>
|
|
|
|
|
|
|
|
<property name="contentWindow"
|
|
|
|
readonly="true"
|
|
|
|
onget="return this.mCurrentBrowser.contentWindow"/>
|
|
|
|
|
|
|
|
<property name="sessionHistory"
|
|
|
|
onget="return this.mCurrentBrowser.sessionHistory;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="markupDocumentViewer"
|
|
|
|
onget="return this.mCurrentBrowser.markupDocumentViewer;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="contentViewerEdit"
|
|
|
|
onget="return this.mCurrentBrowser.contentViewerEdit;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="contentViewerFile"
|
|
|
|
onget="return this.mCurrentBrowser.contentViewerFile;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
|
|
|
<property name="contentDocument"
|
|
|
|
onget="return this.mCurrentBrowser.contentDocument;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2007-08-21 21:59:35 -07:00
|
|
|
<property name="contentTitle"
|
|
|
|
onget="return this.mCurrentBrowser.contentTitle;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2007-08-21 22:02:30 -07:00
|
|
|
<property name="contentPrincipal"
|
|
|
|
onget="return this.mCurrentBrowser.contentPrincipal;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<property name="securityUI"
|
|
|
|
onget="return this.mCurrentBrowser.securityUI;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2014-01-13 09:36:26 -08:00
|
|
|
<property name="fullZoom"
|
|
|
|
onget="return this.mCurrentBrowser.fullZoom;"
|
|
|
|
onset="this.mCurrentBrowser.fullZoom = val;"/>
|
|
|
|
|
|
|
|
<property name="textZoom"
|
|
|
|
onget="return this.mCurrentBrowser.textZoom;"
|
|
|
|
onset="this.mCurrentBrowser.textZoom = val;"/>
|
|
|
|
|
|
|
|
<property name="isSyntheticDocument"
|
|
|
|
onget="return this.mCurrentBrowser.isSyntheticDocument;"
|
|
|
|
readonly="true"/>
|
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
<method name="_handleKeyEvent">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
2007-08-21 22:00:10 -07:00
|
|
|
if (!aEvent.isTrusted) {
|
|
|
|
// Don't let untrusted events mess with tabs.
|
|
|
|
return;
|
|
|
|
}
|
2007-08-21 22:00:17 -07:00
|
|
|
|
2010-05-13 08:37:17 -07:00
|
|
|
if (aEvent.altKey)
|
2007-08-21 22:00:17 -07:00
|
|
|
return;
|
2008-03-28 23:44:15 -07:00
|
|
|
|
2013-01-06 19:24:13 -08:00
|
|
|
if (aEvent.ctrlKey && aEvent.shiftKey && !aEvent.metaKey) {
|
|
|
|
switch (aEvent.keyCode) {
|
|
|
|
case aEvent.DOM_VK_PAGE_UP:
|
|
|
|
this.moveTabBackward();
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
aEvent.preventDefault();
|
|
|
|
return;
|
|
|
|
case aEvent.DOM_VK_PAGE_DOWN:
|
|
|
|
this.moveTabForward();
|
|
|
|
aEvent.stopPropagation();
|
|
|
|
aEvent.preventDefault();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-30 02:50:39 -07:00
|
|
|
// We need to take care of FAYT-watching as long as the findbar
|
|
|
|
// isn't initialized. The checks on aEvent are copied from
|
|
|
|
// _shouldFastFind (see findbar.xml).
|
|
|
|
if (!gFindBarInitialized &&
|
|
|
|
!(aEvent.ctrlKey || aEvent.metaKey) &&
|
2011-12-08 01:21:32 -08:00
|
|
|
!aEvent.defaultPrevented) {
|
2010-05-30 02:50:39 -07:00
|
|
|
let charCode = aEvent.charCode;
|
|
|
|
if (charCode) {
|
|
|
|
let char = String.fromCharCode(charCode);
|
|
|
|
if (char == "'" || char == "/" ||
|
|
|
|
Services.prefs.getBoolPref("accessibility.typeaheadfind")) {
|
|
|
|
gFindBar._onBrowserKeypress(aEvent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-13 08:37:17 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
if (!aEvent.metaKey)
|
|
|
|
return;
|
2007-08-21 22:01:10 -07:00
|
|
|
|
2010-05-13 08:37:17 -07:00
|
|
|
var offset = 1;
|
|
|
|
switch (aEvent.charCode) {
|
|
|
|
case '}'.charCodeAt(0):
|
|
|
|
offset = -1;
|
|
|
|
case '{'.charCodeAt(0):
|
|
|
|
if (window.getComputedStyle(this, null).direction == "ltr")
|
|
|
|
offset *= -1;
|
|
|
|
this.tabContainer.advanceSelectedTab(offset, true);
|
2007-08-21 22:01:10 -07:00
|
|
|
aEvent.stopPropagation();
|
|
|
|
aEvent.preventDefault();
|
2007-08-21 22:00:10 -07:00
|
|
|
}
|
2010-05-13 08:37:17 -07:00
|
|
|
#else
|
|
|
|
if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
|
|
|
|
aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
|
2011-11-03 12:14:58 -07:00
|
|
|
!this.mCurrentTab.pinned) {
|
2010-08-06 13:15:18 -07:00
|
|
|
this.removeCurrentTab({animate: true});
|
2010-05-13 08:37:17 -07:00
|
|
|
aEvent.stopPropagation();
|
|
|
|
aEvent.preventDefault();
|
|
|
|
}
|
|
|
|
#endif
|
2010-02-25 23:58:46 -08:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 21:59:21 -07:00
|
|
|
|
2007-08-21 21:59:31 -07:00
|
|
|
<property name="userTypedClear"
|
|
|
|
onget="return this.mCurrentBrowser.userTypedClear;"
|
|
|
|
onset="return this.mCurrentBrowser.userTypedClear = val;"/>
|
|
|
|
|
2007-08-21 21:59:22 -07:00
|
|
|
<property name="userTypedValue"
|
|
|
|
onget="return this.mCurrentBrowser.userTypedValue;"
|
|
|
|
onset="return this.mCurrentBrowser.userTypedValue = val;"/>
|
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
<method name="createTooltip">
|
|
|
|
<parameter name="event"/>
|
2010-03-16 23:36:13 -07:00
|
|
|
<body><![CDATA[
|
|
|
|
event.stopPropagation();
|
|
|
|
var tab = document.tooltipNode;
|
2011-10-26 17:46:58 -07:00
|
|
|
if (tab.localName != "tab") {
|
2010-03-16 23:36:13 -07:00
|
|
|
event.preventDefault();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.target.setAttribute("label", tab.mOverCloseButton ?
|
|
|
|
tab.getAttribute("closetabtext") :
|
|
|
|
tab.getAttribute("label"));
|
|
|
|
]]></body>
|
2007-08-21 22:00:54 -07:00
|
|
|
</method>
|
2007-08-21 21:59:40 -07:00
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
<method name="handleEvent">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
switch (aEvent.type) {
|
|
|
|
case "keypress":
|
|
|
|
this._handleKeyEvent(aEvent);
|
|
|
|
break;
|
2011-07-11 06:14:08 -07:00
|
|
|
case "sizemodechange":
|
|
|
|
if (aEvent.target == window) {
|
|
|
|
this.mCurrentBrowser.docShellIsActive =
|
|
|
|
(window.windowState != window.STATE_MINIMIZED);
|
|
|
|
}
|
|
|
|
break;
|
2010-02-25 23:58:46 -08:00
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2013-04-24 22:29:39 -07:00
|
|
|
<method name="receiveMessage">
|
|
|
|
<parameter name="aMessage"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
let json = aMessage.json;
|
|
|
|
let browser = aMessage.target;
|
|
|
|
|
|
|
|
switch (aMessage.name) {
|
2014-01-13 04:56:28 -08:00
|
|
|
case "DOMTitleChanged": {
|
2013-04-24 22:29:39 -07:00
|
|
|
let tab = this._getTabForBrowser(browser);
|
2014-01-17 08:17:14 -08:00
|
|
|
if (!tab || tab.hasAttribute("pending"))
|
2013-04-24 22:29:39 -07:00
|
|
|
return;
|
|
|
|
let titleChanged = this.setTabTitle(tab);
|
|
|
|
if (titleChanged && !tab.selected && !tab.hasAttribute("busy"))
|
|
|
|
tab.setAttribute("titlechanged", "true");
|
2013-08-06 15:00:07 -07:00
|
|
|
break;
|
2014-01-13 04:56:28 -08:00
|
|
|
}
|
2014-03-18 07:58:02 -07:00
|
|
|
case "DOMWindowClose": {
|
|
|
|
if (this.tabs.length == 1) {
|
|
|
|
window.close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let tab = this._getTabForBrowser(browser);
|
|
|
|
if (tab) {
|
|
|
|
this.removeTab(tab);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2014-01-13 04:56:28 -08:00
|
|
|
case "contextmenu": {
|
2013-08-06 15:00:07 -07:00
|
|
|
gContextMenuContentData = { event: aMessage.objects.event,
|
|
|
|
browser: browser };
|
|
|
|
let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
|
2014-02-28 16:58:52 -08:00
|
|
|
let event = gContextMenuContentData.event;
|
|
|
|
let pos = browser.mapScreenCoordinatesFromContent(event.screenX, event.screenY);
|
|
|
|
popup.openPopupAtScreen(pos.x, pos.y, true);
|
2013-08-06 15:00:07 -07:00
|
|
|
break;
|
2014-01-13 04:56:28 -08:00
|
|
|
}
|
|
|
|
case "DOMWebNotificationClicked": {
|
|
|
|
let tab = this._getTabForBrowser(browser);
|
|
|
|
if (!tab)
|
|
|
|
return;
|
|
|
|
this.selectedTab = tab;
|
2014-01-18 05:30:56 -08:00
|
|
|
window.focus();
|
2014-01-13 04:56:28 -08:00
|
|
|
break;
|
|
|
|
}
|
2013-04-24 22:29:39 -07:00
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<constructor>
|
|
|
|
<![CDATA[
|
2013-04-30 22:27:59 -07:00
|
|
|
let browserStack = document.getAnonymousElementByAttribute(this, "anonid", "browserStack");
|
2013-04-28 20:14:52 -07:00
|
|
|
this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
|
2013-04-30 22:27:59 -07:00
|
|
|
|
2010-03-22 07:12:04 -07:00
|
|
|
this.mCurrentTab = this.tabContainer.firstChild;
|
2010-02-25 23:58:46 -08:00
|
|
|
document.addEventListener("keypress", this, false);
|
2011-07-11 06:14:08 -07:00
|
|
|
window.addEventListener("sizemodechange", this, false);
|
2007-08-21 22:00:10 -07:00
|
|
|
|
2013-09-28 11:07:07 -07:00
|
|
|
var uniqueId = this._generateUniquePanelID();
|
2007-08-21 22:00:10 -07:00
|
|
|
this.mPanelContainer.childNodes[0].id = uniqueId;
|
2010-03-16 23:36:13 -07:00
|
|
|
this.mCurrentTab.linkedPanel = uniqueId;
|
|
|
|
this.mCurrentTab._tPos = 0;
|
2011-04-11 23:50:56 -07:00
|
|
|
this.mCurrentTab._fullyOpen = true;
|
2010-03-16 23:36:13 -07:00
|
|
|
this.mCurrentTab.linkedBrowser = this.mCurrentBrowser;
|
2007-08-21 22:02:41 -07:00
|
|
|
|
|
|
|
// set up the shared autoscroll popup
|
|
|
|
this._autoScrollPopup = this.mCurrentBrowser._createAutoScrollPopup();
|
2009-03-08 12:05:53 -07:00
|
|
|
this._autoScrollPopup.id = "autoscroller";
|
2007-08-21 22:02:41 -07:00
|
|
|
this.appendChild(this._autoScrollPopup);
|
|
|
|
this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id);
|
2013-04-28 20:14:52 -07:00
|
|
|
this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink;
|
2011-01-17 06:35:32 -08:00
|
|
|
this.updateWindowResizers();
|
2011-03-23 04:31:35 -07:00
|
|
|
|
|
|
|
// Hook up the event listeners to the first browser
|
|
|
|
var tabListener = this.mTabProgressListener(this.mCurrentTab, this.mCurrentBrowser, true);
|
|
|
|
const nsIWebProgress = Components.interfaces.nsIWebProgress;
|
|
|
|
const filter = Components.classes["@mozilla.org/appshell/component/browser-status-filter;1"]
|
|
|
|
.createInstance(nsIWebProgress);
|
|
|
|
filter.addProgressListener(tabListener, nsIWebProgress.NOTIFY_ALL);
|
|
|
|
this.mTabListeners[0] = tabListener;
|
|
|
|
this.mTabFilters[0] = filter;
|
2014-02-12 05:52:20 -08:00
|
|
|
this.webProgress.addProgressListener(filter, nsIWebProgress.NOTIFY_ALL);
|
2011-05-04 00:29:31 -07:00
|
|
|
|
|
|
|
this.style.backgroundColor =
|
|
|
|
Services.prefs.getBoolPref("browser.display.use_system_colors") ?
|
|
|
|
"-moz-default-background-color" :
|
|
|
|
Services.prefs.getCharPref("browser.display.background_color");
|
2013-04-24 22:29:39 -07:00
|
|
|
|
2014-02-11 09:01:08 -08:00
|
|
|
let remote = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIWebNavigation)
|
|
|
|
.QueryInterface(Ci.nsILoadContext)
|
|
|
|
.useRemoteTabs;
|
|
|
|
if (remote) {
|
2013-04-24 22:29:39 -07:00
|
|
|
messageManager.addMessageListener("DOMTitleChanged", this);
|
2014-03-18 07:58:02 -07:00
|
|
|
messageManager.addMessageListener("DOMWindowClose", this);
|
2013-08-06 15:00:07 -07:00
|
|
|
messageManager.addMessageListener("contextmenu", this);
|
|
|
|
}
|
2014-01-13 04:56:28 -08:00
|
|
|
messageManager.addMessageListener("DOMWebNotificationClicked", this);
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</constructor>
|
|
|
|
|
2013-09-28 11:07:07 -07:00
|
|
|
<method name="_generateUniquePanelID">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (!this._uniquePanelIDCounter) {
|
|
|
|
this._uniquePanelIDCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
let outerID = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIDOMWindowUtils)
|
|
|
|
.outerWindowID;
|
|
|
|
|
|
|
|
// We want panel IDs to be globally unique, that's why we include the
|
|
|
|
// window ID. We switched to a monotonic counter as Date.now() lead
|
|
|
|
// to random failures because of colliding IDs.
|
|
|
|
return "panel-" + outerID + "-" + (++this._uniquePanelIDCounter);
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2011-03-23 04:31:35 -07:00
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
<destructor>
|
|
|
|
<![CDATA[
|
|
|
|
for (var i = 0; i < this.mTabListeners.length; ++i) {
|
2010-03-26 14:59:02 -07:00
|
|
|
let browser = this.getBrowserAtIndex(i);
|
2010-08-13 18:52:30 -07:00
|
|
|
if (browser.registeredOpenURI) {
|
2010-11-29 03:44:43 -08:00
|
|
|
this._placesAutocomplete.unregisterOpenPage(browser.registeredOpenURI);
|
2010-08-13 18:52:30 -07:00
|
|
|
delete browser.registeredOpenURI;
|
|
|
|
}
|
2010-03-26 14:59:02 -07:00
|
|
|
browser.webProgress.removeProgressListener(this.mTabFilters[i]);
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]);
|
|
|
|
this.mTabFilters[i] = null;
|
2009-10-01 05:31:24 -07:00
|
|
|
this.mTabListeners[i].destroy();
|
2007-08-21 21:58:49 -07:00
|
|
|
this.mTabListeners[i] = null;
|
|
|
|
}
|
2010-02-25 23:58:46 -08:00
|
|
|
document.removeEventListener("keypress", this, false);
|
2011-07-11 06:14:08 -07:00
|
|
|
window.removeEventListener("sizemodechange", this, false);
|
2013-04-24 22:29:39 -07:00
|
|
|
|
2014-02-11 09:01:08 -08:00
|
|
|
if (gMultiProcessBrowser) {
|
2013-04-24 22:29:39 -07:00
|
|
|
messageManager.removeMessageListener("DOMTitleChanged", this);
|
2013-08-06 15:00:07 -07:00
|
|
|
messageManager.removeMessageListener("contextmenu", this);
|
|
|
|
}
|
2007-08-21 21:58:49 -07:00
|
|
|
]]>
|
|
|
|
</destructor>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
|
|
|
<!-- Deprecated stuff, implemented for backwards compatibility. -->
|
2011-03-23 04:31:35 -07:00
|
|
|
<method name="enterTabbedMode">
|
|
|
|
<body>
|
|
|
|
Application.console.log("enterTabbedMode is an obsolete method and " +
|
|
|
|
"will be removed in a future release.");
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
<field name="mTabbedMode" readonly="true">true</field>
|
2010-03-16 23:36:13 -07:00
|
|
|
<method name="setStripVisibilityTo">
|
|
|
|
<parameter name="aShow"/>
|
|
|
|
<body>
|
|
|
|
this.tabContainer.visible = aShow;
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
<method name="getStripVisibility">
|
|
|
|
<body>
|
|
|
|
return this.tabContainer.visible;
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
<property name="mContextTab" readonly="true"
|
2010-03-25 15:02:19 -07:00
|
|
|
onget="return TabContextMenu.contextTab;"/>
|
2010-03-21 02:38:08 -07:00
|
|
|
<property name="mPrefs" readonly="true"
|
|
|
|
onget="return Services.prefs;"/>
|
2010-03-22 07:12:04 -07:00
|
|
|
<property name="mTabContainer" readonly="true"
|
|
|
|
onget="return this.tabContainer;"/>
|
|
|
|
<property name="mTabs" readonly="true"
|
|
|
|
onget="return this.tabs;"/>
|
2010-03-22 10:49:55 -07:00
|
|
|
<!--
|
|
|
|
- Compatibility hack: several extensions depend on this property to
|
|
|
|
- access the tab context menu or tab container, so keep that working for
|
|
|
|
- now. Ideally we can remove this once extensions are using
|
|
|
|
- tabbrowser.tabContextMenu and tabbrowser.tabContainer directly.
|
|
|
|
-->
|
|
|
|
<property name="mStrip" readonly="true">
|
|
|
|
<getter>
|
|
|
|
<![CDATA[
|
|
|
|
return ({
|
|
|
|
self: this,
|
|
|
|
childNodes: [null, this.tabContextMenu, this.tabContainer],
|
|
|
|
firstChild: { nextSibling: this.tabContextMenu },
|
|
|
|
getElementsByAttribute: function (attr, attrValue) {
|
|
|
|
if (attr == "anonid" && attrValue == "tabContextMenu")
|
|
|
|
return [this.self.tabContextMenu];
|
|
|
|
return [];
|
|
|
|
},
|
|
|
|
// Also support adding event listeners (forward to the tab container)
|
|
|
|
addEventListener: function (a,b,c) { this.self.tabContainer.addEventListener(a,b,c); },
|
|
|
|
removeEventListener: function (a,b,c) { this.self.tabContainer.removeEventListener(a,b,c); }
|
|
|
|
});
|
|
|
|
]]>
|
|
|
|
</getter>
|
|
|
|
</property>
|
2007-08-21 21:58:49 -07:00
|
|
|
</implementation>
|
|
|
|
|
|
|
|
<handlers>
|
2007-08-21 22:01:16 -07:00
|
|
|
<handler event="DOMWindowClose" phase="capturing">
|
2007-08-21 21:58:49 -07:00
|
|
|
<![CDATA[
|
2007-08-21 21:59:39 -07:00
|
|
|
if (!event.isTrusted)
|
|
|
|
return;
|
|
|
|
|
2010-03-22 07:12:04 -07:00
|
|
|
if (this.tabs.length == 1)
|
2010-03-21 04:01:01 -07:00
|
|
|
return;
|
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
var tab = this._getTabForContentWindow(event.target);
|
|
|
|
if (tab) {
|
|
|
|
this.removeTab(tab);
|
|
|
|
event.preventDefault();
|
2007-08-21 21:58:49 -07:00
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</handler>
|
2007-08-21 22:01:16 -07:00
|
|
|
<handler event="DOMWillOpenModalDialog" phase="capturing">
|
2007-08-21 21:59:40 -07:00
|
|
|
<![CDATA[
|
|
|
|
if (!event.isTrusted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// We're about to open a modal dialog, make sure the opening
|
|
|
|
// tab is brought to the front.
|
2014-04-04 14:50:42 -07:00
|
|
|
// If this is a same-process modal dialog, then we're given its DOM
|
|
|
|
// window as the event's target. For remote dialogs, we're given the
|
|
|
|
// browser, but that's in the originalTarget.
|
|
|
|
// XXX Why originalTarget for the browser?
|
|
|
|
this.selectedTab = (event.target instanceof Window) ?
|
|
|
|
this._getTabForContentWindow(event.target.top) :
|
|
|
|
this._getTabForBrowser(event.originalTarget);
|
2010-02-25 23:58:46 -08:00
|
|
|
]]>
|
|
|
|
</handler>
|
|
|
|
<handler event="DOMTitleChanged">
|
|
|
|
<![CDATA[
|
|
|
|
if (!event.isTrusted)
|
|
|
|
return;
|
2007-08-21 21:59:40 -07:00
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
var contentWin = event.target.defaultView;
|
|
|
|
if (contentWin != contentWin.top)
|
|
|
|
return;
|
2007-08-21 21:59:40 -07:00
|
|
|
|
2010-02-25 23:58:46 -08:00
|
|
|
var tab = this._getTabForContentWindow(contentWin);
|
2014-01-17 08:17:14 -08:00
|
|
|
if (tab.hasAttribute("pending"))
|
|
|
|
return;
|
|
|
|
|
2010-09-04 09:51:52 -07:00
|
|
|
var titleChanged = this.setTabTitle(tab);
|
2010-09-10 01:05:36 -07:00
|
|
|
if (titleChanged && !tab.selected && !tab.hasAttribute("busy"))
|
2010-09-02 13:08:37 -07:00
|
|
|
tab.setAttribute("titlechanged", "true");
|
2007-08-21 21:59:40 -07:00
|
|
|
]]>
|
|
|
|
</handler>
|
2013-09-03 15:11:22 -07:00
|
|
|
<handler event="oop-browser-crashed">
|
|
|
|
<![CDATA[
|
|
|
|
if (!event.isTrusted)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let browser = event.originalTarget;
|
|
|
|
let title = browser.contentTitle;
|
|
|
|
let uri = browser.currentURI;
|
2013-09-09 08:26:14 -07:00
|
|
|
let icon = browser.mIconURL;
|
2013-09-03 15:11:22 -07:00
|
|
|
|
2014-01-21 09:53:33 -08:00
|
|
|
this.updateBrowserRemoteness(browser, "about:tabcrashed");
|
2013-09-03 15:11:22 -07:00
|
|
|
|
|
|
|
browser.setAttribute("crashedPageTitle", title);
|
|
|
|
browser.docShell.displayLoadError(Cr.NS_ERROR_CONTENT_CRASHED, uri, null);
|
|
|
|
browser.removeAttribute("crashedPageTitle");
|
2013-09-09 08:26:14 -07:00
|
|
|
let tab = this._getTabForBrowser(browser);
|
|
|
|
this.setIcon(tab, icon);
|
2013-09-03 15:11:22 -07:00
|
|
|
]]>
|
|
|
|
</handler>
|
2007-08-21 21:58:49 -07:00
|
|
|
</handlers>
|
|
|
|
</binding>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<binding id="tabbrowser-tabbox"
|
|
|
|
extends="chrome://global/content/bindings/tabbox.xml#tabbox">
|
|
|
|
<implementation>
|
|
|
|
<property name="tabs" readonly="true"
|
|
|
|
onget="return document.getBindingParent(this).tabContainer;"/>
|
|
|
|
</implementation>
|
|
|
|
</binding>
|
|
|
|
|
2007-08-21 22:02:12 -07:00
|
|
|
<binding id="tabbrowser-arrowscrollbox" extends="chrome://global/content/bindings/scrollbox.xml#arrowscrollbox-clicktoscroll">
|
2009-01-25 00:06:45 -08:00
|
|
|
<implementation>
|
|
|
|
<!-- Override scrollbox.xml method, since our scrollbox's children are
|
|
|
|
inherited from the binding parent -->
|
|
|
|
<method name="_getScrollableElements">
|
|
|
|
<body><![CDATA[
|
2010-07-22 15:31:58 -07:00
|
|
|
return Array.filter(document.getBindingParent(this).childNodes,
|
|
|
|
this._canScrollToElement, this);
|
2009-01-25 00:06:45 -08:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2010-06-24 07:29:02 -07:00
|
|
|
<method name="_canScrollToElement">
|
|
|
|
<parameter name="tab"/>
|
2010-07-29 16:39:57 -07:00
|
|
|
<body><![CDATA[
|
|
|
|
return !tab.pinned && !tab.hidden;
|
|
|
|
]]></body>
|
2010-06-24 07:29:02 -07:00
|
|
|
</method>
|
2013-10-22 09:19:30 -07:00
|
|
|
<field name="_tabMarginLeft">null</field>
|
|
|
|
<field name="_tabMarginRight">null</field>
|
|
|
|
<method name="_adjustElementStartAndEnd">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<parameter name="tabStart"/>
|
|
|
|
<parameter name="tabEnd"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
if (this._tabMarginLeft === null || this._tabMarginRight === null) {
|
|
|
|
let tabMiddle = document.getAnonymousElementByAttribute(aTab, "class", "tab-background-middle");
|
|
|
|
let tabMiddleStyle = window.getComputedStyle(tabMiddle, null);
|
|
|
|
this._tabMarginLeft = parseFloat(tabMiddleStyle.marginLeft);
|
|
|
|
this._tabMarginRight = parseFloat(tabMiddleStyle.marginRight);
|
|
|
|
}
|
|
|
|
if (this._tabMarginLeft < 0) {
|
|
|
|
tabStart = tabStart + this._tabMarginLeft;
|
|
|
|
}
|
|
|
|
if (this._tabMarginRight < 0) {
|
|
|
|
tabEnd = tabEnd - this._tabMarginRight;
|
|
|
|
}
|
|
|
|
return [tabStart, tabEnd];
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2009-01-25 00:06:45 -08:00
|
|
|
</implementation>
|
|
|
|
|
2009-02-12 01:18:37 -08:00
|
|
|
<handlers>
|
2011-04-11 23:50:56 -07:00
|
|
|
<handler event="underflow" phase="capturing"><![CDATA[
|
2011-10-26 17:46:58 -07:00
|
|
|
if (event.detail == 0)
|
2011-04-11 23:50:56 -07:00
|
|
|
return; // Ignore vertical events
|
2009-02-12 01:18:37 -08:00
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
var tabs = document.getBindingParent(this);
|
2013-03-17 14:03:08 -07:00
|
|
|
tabs.removeAttribute("overflow");
|
|
|
|
|
|
|
|
if (tabs._lastTabClosedByMouse)
|
|
|
|
tabs._expandSpacerBy(this._scrollButtonDown.clientWidth);
|
2010-08-06 13:15:18 -07:00
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
|
|
|
|
tabs.tabbrowser);
|
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
tabs._positionPinnedTabs();
|
2009-02-12 01:18:37 -08:00
|
|
|
]]></handler>
|
|
|
|
<handler event="overflow"><![CDATA[
|
2011-10-26 17:46:58 -07:00
|
|
|
if (event.detail == 0)
|
2011-04-11 23:50:56 -07:00
|
|
|
return; // Ignore vertical events
|
|
|
|
var tabs = document.getBindingParent(this);
|
2013-08-16 11:10:12 -07:00
|
|
|
var numberOfTabs = tabs.tabbrowser.visibleTabs.length;
|
|
|
|
if (numberOfTabs == 1)
|
|
|
|
return;
|
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
tabs.setAttribute("overflow", "true");
|
|
|
|
tabs._positionPinnedTabs();
|
2012-10-25 10:59:33 -07:00
|
|
|
tabs._handleTabSelect(false);
|
2009-02-12 01:18:37 -08:00
|
|
|
]]></handler>
|
|
|
|
</handlers>
|
2009-01-25 00:06:45 -08:00
|
|
|
</binding>
|
2007-08-21 22:02:12 -07:00
|
|
|
|
2007-08-21 22:00:55 -07:00
|
|
|
<binding id="tabbrowser-tabs"
|
2007-08-21 22:00:54 -07:00
|
|
|
extends="chrome://global/content/bindings/tabbox.xml#tabs">
|
2010-03-16 23:36:13 -07:00
|
|
|
<resources>
|
|
|
|
<stylesheet src="chrome://browser/content/tabbrowser.css"/>
|
|
|
|
</resources>
|
|
|
|
|
2010-03-25 15:02:19 -07:00
|
|
|
<content>
|
2011-02-04 23:57:09 -08:00
|
|
|
<xul:hbox align="end">
|
2010-03-16 23:36:13 -07:00
|
|
|
<xul:image class="tab-drop-indicator" anonid="tab-drop-indicator" collapsed="true"/>
|
|
|
|
</xul:hbox>
|
|
|
|
<xul:arrowscrollbox anonid="arrowscrollbox" orient="horizontal" flex="1"
|
|
|
|
style="min-width: 1px;"
|
2007-11-21 04:04:21 -08:00
|
|
|
#ifndef XP_MACOSX
|
2010-03-16 23:36:13 -07:00
|
|
|
clicktoscroll="true"
|
2007-11-21 04:04:21 -08:00
|
|
|
#endif
|
2010-03-16 23:36:13 -07:00
|
|
|
class="tabbrowser-arrowscrollbox">
|
2009-01-23 16:41:36 -08:00
|
|
|
# This is a hack to circumvent bug 472020, otherwise the tabs show up on the
|
|
|
|
# right of the newtab button.
|
2010-03-16 23:36:13 -07:00
|
|
|
<children includes="tab"/>
|
2009-01-23 16:41:36 -08:00
|
|
|
# This is to ensure anything extensions put here will go before the newtab
|
|
|
|
# button, necessary due to the previous hack.
|
2010-03-16 23:36:13 -07:00
|
|
|
<children/>
|
|
|
|
<xul:toolbarbutton class="tabs-newtab-button"
|
|
|
|
command="cmd_newNavigatorTab"
|
2010-05-26 05:51:04 -07:00
|
|
|
onclick="checkForMiddleClick(this, event);"
|
2013-03-29 14:34:56 -07:00
|
|
|
onmouseover="document.getBindingParent(this)._enterNewTab();"
|
|
|
|
onmouseout="document.getBindingParent(this)._leaveNewTab();"
|
2010-03-16 23:36:13 -07:00
|
|
|
tooltiptext="&newTabButton.tooltip;"/>
|
2013-03-17 14:03:08 -07:00
|
|
|
<xul:spacer class="closing-tabs-spacer" anonid="closing-tabs-spacer"
|
|
|
|
style="width: 0;"/>
|
2010-03-16 23:36:13 -07:00
|
|
|
</xul:arrowscrollbox>
|
2007-08-21 22:00:54 -07:00
|
|
|
</content>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2009-11-05 00:02:12 -08:00
|
|
|
<implementation implements="nsIDOMEventListener">
|
2007-08-21 22:00:54 -07:00
|
|
|
<constructor>
|
2007-08-21 22:01:27 -07:00
|
|
|
<![CDATA[
|
2010-03-21 02:38:08 -07:00
|
|
|
this.mTabClipWidth = Services.prefs.getIntPref("browser.tabs.tabClipWidth");
|
|
|
|
this.mCloseButtons = Services.prefs.getIntPref("browser.tabs.closeButtons");
|
2010-03-22 08:43:20 -07:00
|
|
|
this._closeWindowWithLastTab = Services.prefs.getBoolPref("browser.tabs.closeWindowWithLastTab");
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
var tab = this.firstChild;
|
2013-11-28 16:15:16 -08:00
|
|
|
tab.label = this.tabbrowser.mStringBundle.getString("tabs.emptyTabTitle");
|
2010-03-16 23:36:13 -07:00
|
|
|
tab.setAttribute("crop", "end");
|
|
|
|
tab.setAttribute("onerror", "this.removeAttribute('image');");
|
2007-08-21 22:01:56 -07:00
|
|
|
this.adjustTabstrip();
|
2007-08-21 22:01:25 -07:00
|
|
|
|
2010-07-13 23:50:27 -07:00
|
|
|
Services.prefs.addObserver("browser.tabs.", this._prefObserver, false);
|
2007-08-21 22:02:44 -07:00
|
|
|
window.addEventListener("resize", this, false);
|
2012-03-11 17:59:33 -07:00
|
|
|
window.addEventListener("load", this, false);
|
2013-01-03 18:53:15 -08:00
|
|
|
|
|
|
|
try {
|
|
|
|
this._tabAnimationLoggingEnabled = Services.prefs.getBoolPref("browser.tabs.animationLogging.enabled");
|
|
|
|
} catch (ex) {
|
|
|
|
this._tabAnimationLoggingEnabled = false;
|
|
|
|
}
|
2013-02-07 15:55:39 -08:00
|
|
|
this._browserNewtabpageEnabled = Services.prefs.getBoolPref("browser.newtabpage.enabled");
|
2007-08-21 22:01:27 -07:00
|
|
|
]]>
|
2007-08-21 22:00:54 -07:00
|
|
|
</constructor>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:01:34 -07:00
|
|
|
<destructor>
|
|
|
|
<![CDATA[
|
2010-07-13 23:50:27 -07:00
|
|
|
Services.prefs.removeObserver("browser.tabs.", this._prefObserver);
|
2007-08-21 22:01:34 -07:00
|
|
|
]]>
|
|
|
|
</destructor>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<field name="tabbrowser" readonly="true">
|
|
|
|
document.getElementById(this.getAttribute("tabbrowser"));
|
|
|
|
</field>
|
|
|
|
|
|
|
|
<field name="tabbox" readonly="true">
|
|
|
|
this.tabbrowser.mTabBox;
|
|
|
|
</field>
|
|
|
|
|
2010-03-22 10:49:55 -07:00
|
|
|
<field name="contextMenu" readonly="true">
|
2010-07-17 01:08:43 -07:00
|
|
|
document.getElementById("tabContextMenu");
|
2010-03-22 10:49:55 -07:00
|
|
|
</field>
|
|
|
|
|
2007-08-21 22:01:28 -07:00
|
|
|
<field name="mTabstripWidth">0</field>
|
|
|
|
|
2007-08-21 22:01:25 -07:00
|
|
|
<field name="mTabstrip">
|
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
|
|
|
|
</field>
|
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
<field name="_firstTab">null</field>
|
|
|
|
<field name="_lastTab">null</field>
|
|
|
|
<field name="_afterSelectedTab">null</field>
|
|
|
|
<field name="_beforeHoveredTab">null</field>
|
|
|
|
<field name="_afterHoveredTab">null</field>
|
2013-09-25 07:43:36 -07:00
|
|
|
<field name="_hoveredTab">null</field>
|
2013-03-19 16:41:01 -07:00
|
|
|
|
2013-10-22 09:51:39 -07:00
|
|
|
<property name="_isCustomizing" readonly="true">
|
|
|
|
<getter>
|
|
|
|
let root = document.documentElement;
|
|
|
|
return root.getAttribute("customizing") == "true" ||
|
|
|
|
root.getAttribute("customize-exiting") == "true";
|
|
|
|
</getter>
|
|
|
|
</property>
|
2013-03-19 16:41:01 -07:00
|
|
|
|
|
|
|
<method name="_setPositionalAttributes">
|
|
|
|
<body><![CDATA[
|
|
|
|
let visibleTabs = this.tabbrowser.visibleTabs;
|
|
|
|
|
|
|
|
if (!visibleTabs.length)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let selectedIndex = visibleTabs.indexOf(this.selectedItem);
|
|
|
|
|
|
|
|
let lastVisible = visibleTabs.length - 1;
|
|
|
|
|
|
|
|
if (this._afterSelectedTab)
|
|
|
|
this._afterSelectedTab.removeAttribute("afterselected-visible");
|
|
|
|
if (this.selectedItem.closing || selectedIndex == lastVisible) {
|
|
|
|
this._afterSelectedTab = null;
|
|
|
|
} else {
|
|
|
|
this._afterSelectedTab = visibleTabs[selectedIndex + 1];
|
|
|
|
this._afterSelectedTab.setAttribute("afterselected-visible",
|
|
|
|
"true");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (this._firstTab)
|
|
|
|
this._firstTab.removeAttribute("first-visible-tab");
|
|
|
|
this._firstTab = visibleTabs[0];
|
|
|
|
this._firstTab.setAttribute("first-visible-tab", "true");
|
|
|
|
if (this._lastTab)
|
|
|
|
this._lastTab.removeAttribute("last-visible-tab");
|
|
|
|
this._lastTab = visibleTabs[lastVisible];
|
|
|
|
this._lastTab.setAttribute("last-visible-tab", "true");
|
2013-09-25 07:43:36 -07:00
|
|
|
|
|
|
|
let hoveredTab = this._hoveredTab;
|
|
|
|
if (hoveredTab) {
|
|
|
|
hoveredTab._mouseleave();
|
|
|
|
hoveredTab._mouseenter();
|
|
|
|
}
|
2013-03-19 16:41:01 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<field name="_prefObserver"><![CDATA[({
|
|
|
|
tabContainer: this,
|
|
|
|
|
|
|
|
observe: function (subject, topic, data) {
|
|
|
|
switch (data) {
|
2007-08-21 22:01:25 -07:00
|
|
|
case "browser.tabs.closeButtons":
|
2010-03-21 02:38:08 -07:00
|
|
|
this.tabContainer.mCloseButtons = Services.prefs.getIntPref(data);
|
2010-03-16 23:36:13 -07:00
|
|
|
this.tabContainer.adjustTabstrip();
|
|
|
|
break;
|
2010-03-22 08:43:20 -07:00
|
|
|
case "browser.tabs.closeWindowWithLastTab":
|
|
|
|
this.tabContainer._closeWindowWithLastTab = Services.prefs.getBoolPref(data);
|
|
|
|
this.tabContainer.adjustTabstrip();
|
|
|
|
break;
|
2007-08-21 22:01:25 -07:00
|
|
|
}
|
2007-08-21 22:01:22 -07:00
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
});]]></field>
|
|
|
|
<field name="_blockDblClick">false</field>
|
|
|
|
|
|
|
|
<field name="_tabDropIndicator">
|
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "tab-drop-indicator");
|
|
|
|
</field>
|
|
|
|
|
|
|
|
<field name="_dragOverDelay">350</field>
|
|
|
|
<field name="_dragTime">0</field>
|
|
|
|
|
|
|
|
<field name="_container" readonly="true"><![CDATA[
|
|
|
|
this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this;
|
|
|
|
]]></field>
|
|
|
|
|
2012-03-11 17:59:33 -07:00
|
|
|
<field name="_propagatedVisibilityOnce">false</field>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<property name="visible"
|
|
|
|
onget="return !this._container.collapsed;">
|
|
|
|
<setter><![CDATA[
|
2012-03-11 17:59:33 -07:00
|
|
|
if (val == this.visible &&
|
|
|
|
this._propagatedVisibilityOnce)
|
2011-01-07 12:28:02 -08:00
|
|
|
return val;
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
this._container.collapsed = !val;
|
|
|
|
|
2012-01-06 05:19:57 -08:00
|
|
|
this._propagateVisibility();
|
2012-03-11 17:59:33 -07:00
|
|
|
this._propagatedVisibilityOnce = true;
|
2011-01-07 12:28:02 -08:00
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
return val;
|
|
|
|
]]></setter>
|
|
|
|
</property>
|
|
|
|
|
2013-03-19 16:41:01 -07:00
|
|
|
<method name="_enterNewTab">
|
|
|
|
<body><![CDATA[
|
|
|
|
let visibleTabs = this.tabbrowser.visibleTabs;
|
|
|
|
let candidate = visibleTabs[visibleTabs.length - 1];
|
|
|
|
if (!candidate.selected) {
|
|
|
|
this._beforeHoveredTab = candidate;
|
|
|
|
candidate.setAttribute("beforehovered", "true");
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_leaveNewTab">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (this._beforeHoveredTab) {
|
|
|
|
this._beforeHoveredTab.removeAttribute("beforehovered");
|
|
|
|
this._beforeHoveredTab = null;
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2012-01-06 05:19:57 -08:00
|
|
|
<method name="_propagateVisibility">
|
|
|
|
<body><![CDATA[
|
|
|
|
let visible = this.visible;
|
|
|
|
|
|
|
|
document.getElementById("menu_closeWindow").hidden = !visible;
|
|
|
|
document.getElementById("menu_close").setAttribute("label",
|
|
|
|
this.tabbrowser.mStringBundle.getString(visible ? "tabs.closeTab" : "tabs.close"));
|
|
|
|
|
2012-01-16 05:37:21 -08:00
|
|
|
TabsInTitlebar.allowedBy("tabs-visible", visible);
|
2012-01-06 05:19:57 -08:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<method name="updateVisibility">
|
|
|
|
<body><![CDATA[
|
2011-03-31 01:12:10 -07:00
|
|
|
if (this.childNodes.length - this.tabbrowser._removingTabs.length == 1)
|
2013-03-27 17:54:59 -07:00
|
|
|
this.visible = window.toolbar.visible;
|
2010-03-16 23:36:13 -07:00
|
|
|
else
|
|
|
|
this.visible = true;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 22:01:25 -07:00
|
|
|
|
|
|
|
<method name="adjustTabstrip">
|
2007-08-21 22:00:54 -07:00
|
|
|
<body><![CDATA[
|
2013-06-03 10:36:01 -07:00
|
|
|
let numTabs = this.childNodes.length -
|
|
|
|
this.tabbrowser._removingTabs.length;
|
2007-08-21 22:01:25 -07:00
|
|
|
// modes for tabstrip
|
2011-01-07 16:35:33 -08:00
|
|
|
// 0 - button on active tab only
|
|
|
|
// 1 - close buttons on all tabs
|
|
|
|
// 2 - no close buttons at all
|
|
|
|
// 3 - close button at the end of the tabstrip
|
2007-08-21 22:01:25 -07:00
|
|
|
switch (this.mCloseButtons) {
|
|
|
|
case 0:
|
2013-06-03 10:36:01 -07:00
|
|
|
if (numTabs == 1 && this._closeWindowWithLastTab)
|
2011-01-07 16:35:33 -08:00
|
|
|
this.setAttribute("closebuttons", "hidden");
|
2010-03-22 08:43:20 -07:00
|
|
|
else
|
|
|
|
this.setAttribute("closebuttons", "activetab");
|
2007-08-21 22:01:25 -07:00
|
|
|
break;
|
|
|
|
case 1:
|
2013-06-03 10:36:01 -07:00
|
|
|
if (numTabs == 1) {
|
2010-08-25 11:06:49 -07:00
|
|
|
if (this._closeWindowWithLastTab)
|
2011-01-07 16:35:33 -08:00
|
|
|
this.setAttribute("closebuttons", "hidden");
|
2010-08-25 11:06:49 -07:00
|
|
|
else
|
|
|
|
this.setAttribute("closebuttons", "alltabs");
|
2013-06-03 10:36:01 -07:00
|
|
|
} else if (numTabs == 2) {
|
|
|
|
// This is an optimization to avoid layout flushes by calling
|
|
|
|
// getBoundingClientRect() when we just opened a second tab. In
|
|
|
|
// this case it's highly unlikely that the tab width is smaller
|
|
|
|
// than mTabClipWidth and the tab close button obscures too much
|
|
|
|
// of the tab's label. In the edge case of the window being too
|
|
|
|
// narrow (or if tabClipWidth has been set to a way higher value),
|
|
|
|
// we'll correct the 'closebuttons' attribute after the tabopen
|
|
|
|
// animation has finished.
|
|
|
|
this.setAttribute("closebuttons", "alltabs");
|
2010-08-25 11:06:49 -07:00
|
|
|
} else {
|
2010-08-16 13:43:04 -07:00
|
|
|
let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs];
|
2010-06-24 07:29:02 -07:00
|
|
|
if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
|
|
|
|
this.setAttribute("closebuttons", "alltabs");
|
|
|
|
else
|
|
|
|
this.setAttribute("closebuttons", "activetab");
|
|
|
|
}
|
2007-08-21 22:01:25 -07:00
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
case 3:
|
2011-01-07 16:35:33 -08:00
|
|
|
this.setAttribute("closebuttons", "never");
|
2007-08-21 22:01:25 -07:00
|
|
|
break;
|
|
|
|
}
|
2010-04-27 09:57:19 -07:00
|
|
|
var tabstripClosebutton = document.getElementById("tabs-closebutton");
|
|
|
|
if (tabstripClosebutton && tabstripClosebutton.parentNode == this._container)
|
|
|
|
tabstripClosebutton.collapsed = this.mCloseButtons != 3;
|
2007-08-21 22:01:25 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2009-01-15 04:30:43 -08:00
|
|
|
|
2007-08-21 22:01:25 -07:00
|
|
|
<method name="_handleTabSelect">
|
2012-10-25 10:59:33 -07:00
|
|
|
<parameter name="aSmoothScroll"/>
|
2007-08-21 22:01:25 -07:00
|
|
|
<body><![CDATA[
|
2012-10-25 10:59:33 -07:00
|
|
|
if (this.getAttribute("overflow") == "true")
|
|
|
|
this.mTabstrip.ensureElementIsVisible(this.selectedItem, aSmoothScroll);
|
2007-08-21 22:01:25 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 22:01:54 -07:00
|
|
|
|
2009-01-15 04:30:43 -08:00
|
|
|
<method name="_fillTrailingGap">
|
|
|
|
<body><![CDATA[
|
|
|
|
try {
|
|
|
|
// if we're at the right side (and not the logical end,
|
|
|
|
// which is why this works for both LTR and RTL)
|
|
|
|
// of the tabstrip, we need to ensure that we stay
|
|
|
|
// completely scrolled to the right side
|
|
|
|
var tabStrip = this.mTabstrip;
|
2010-05-27 02:00:48 -07:00
|
|
|
if (tabStrip.scrollPosition + tabStrip.scrollClientSize >
|
2009-07-10 02:13:10 -07:00
|
|
|
tabStrip.scrollSize)
|
2009-01-15 04:30:43 -08:00
|
|
|
tabStrip.scrollByPixels(-1);
|
|
|
|
} catch (e) {}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
<field name="_closingTabsSpacer">
|
|
|
|
document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer");
|
|
|
|
</field>
|
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
<field name="_tabDefaultMaxWidth">NaN</field>
|
|
|
|
<field name="_lastTabClosedByMouse">false</field>
|
|
|
|
<field name="_hasTabTempMaxWidth">false</field>
|
2011-04-11 23:50:56 -07:00
|
|
|
|
|
|
|
<!-- Try to keep the active tab's close button under the mouse cursor -->
|
|
|
|
<method name="_lockTabSizing">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
var tabs = this.tabbrowser.visibleTabs;
|
|
|
|
if (!tabs.length)
|
|
|
|
return;
|
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
var isEndTab = (aTab._tPos > tabs[tabs.length-1]._tPos);
|
|
|
|
var tabWidth = aTab.getBoundingClientRect().width;
|
2011-04-11 23:50:56 -07:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
if (!this._tabDefaultMaxWidth)
|
|
|
|
this._tabDefaultMaxWidth =
|
|
|
|
parseFloat(window.getComputedStyle(aTab).maxWidth);
|
|
|
|
this._lastTabClosedByMouse = true;
|
2013-02-21 16:55:47 -08:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
if (this.getAttribute("overflow") == "true") {
|
|
|
|
// Don't need to do anything if we're in overflow mode and aren't scrolled
|
|
|
|
// all the way to the right, or if we're closing the last tab.
|
|
|
|
if (isEndTab || !this.mTabstrip._scrollButtonDown.disabled)
|
2013-02-21 16:55:47 -08:00
|
|
|
return;
|
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
// If the tab has an owner that will become the active tab, the owner will
|
|
|
|
// be to the left of it, so we actually want the left tab to slide over.
|
|
|
|
// This can't be done as easily in non-overflow mode, so we don't bother.
|
|
|
|
if (aTab.owner)
|
|
|
|
return;
|
2011-04-11 23:50:56 -07:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
this._expandSpacerBy(tabWidth);
|
|
|
|
} else { // non-overflow mode
|
|
|
|
// Locking is neither in effect nor needed, so let tabs expand normally.
|
|
|
|
if (isEndTab && !this._hasTabTempMaxWidth)
|
|
|
|
return;
|
2013-01-29 18:14:45 -08:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
let numPinned = this.tabbrowser._numPinnedTabs;
|
|
|
|
// Force tabs to stay the same width, unless we're closing the last tab,
|
|
|
|
// which case we need to let them expand just enough so that the overall
|
|
|
|
// tabbar width is the same.
|
|
|
|
if (isEndTab) {
|
|
|
|
let numNormalTabs = tabs.length - numPinned;
|
|
|
|
tabWidth = tabWidth * (numNormalTabs + 1) / numNormalTabs;
|
|
|
|
if (tabWidth > this._tabDefaultMaxWidth)
|
|
|
|
tabWidth = this._tabDefaultMaxWidth;
|
2013-01-29 18:14:45 -08:00
|
|
|
}
|
2013-03-17 14:03:08 -07:00
|
|
|
tabWidth += "px";
|
|
|
|
for (let i = numPinned; i < tabs.length; i++) {
|
|
|
|
let tab = tabs[i];
|
|
|
|
tab.style.setProperty("max-width", tabWidth, "important");
|
|
|
|
if (!isEndTab) { // keep tabs the same width
|
|
|
|
tab.style.transition = "none";
|
|
|
|
tab.clientTop; // flush styles to skip animation; see bug 649247
|
|
|
|
tab.style.transition = "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this._hasTabTempMaxWidth = true;
|
|
|
|
this.tabbrowser.addEventListener("mousemove", this, false);
|
|
|
|
window.addEventListener("mouseout", this, false);
|
2013-01-29 18:14:45 -08:00
|
|
|
}
|
2011-04-11 23:50:56 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
<method name="_expandSpacerBy">
|
|
|
|
<parameter name="pixels"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
let spacer = this._closingTabsSpacer;
|
|
|
|
spacer.style.width = parseFloat(spacer.style.width) + pixels + "px";
|
|
|
|
this.setAttribute("using-closing-tabs-spacer", "true");
|
|
|
|
this.tabbrowser.addEventListener("mousemove", this, false);
|
|
|
|
window.addEventListener("mouseout", this, false);
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2011-04-11 23:50:56 -07:00
|
|
|
<method name="_unlockTabSizing">
|
|
|
|
<body><![CDATA[
|
2011-10-26 17:46:58 -07:00
|
|
|
this.tabbrowser.removeEventListener("mousemove", this, false);
|
|
|
|
window.removeEventListener("mouseout", this, false);
|
2012-01-03 21:15:00 -08:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
if (this._hasTabTempMaxWidth) {
|
|
|
|
this._hasTabTempMaxWidth = false;
|
|
|
|
let tabs = this.tabbrowser.visibleTabs;
|
|
|
|
for (let i = 0; i < tabs.length; i++)
|
|
|
|
tabs[i].style.maxWidth = "";
|
|
|
|
}
|
2013-01-29 18:14:45 -08:00
|
|
|
|
2013-03-17 14:03:08 -07:00
|
|
|
if (this.hasAttribute("using-closing-tabs-spacer")) {
|
|
|
|
this.removeAttribute("using-closing-tabs-spacer");
|
|
|
|
this._closingTabsSpacer.style.width = 0;
|
2013-01-29 18:14:45 -08:00
|
|
|
}
|
2011-04-11 23:50:56 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2012-10-25 10:59:33 -07:00
|
|
|
<field name="_lastNumPinned">0</field>
|
2010-06-24 07:29:02 -07:00
|
|
|
<method name="_positionPinnedTabs">
|
|
|
|
<body><![CDATA[
|
2011-01-07 12:27:17 -08:00
|
|
|
var numPinned = this.tabbrowser._numPinnedTabs;
|
2011-01-17 00:38:19 -08:00
|
|
|
var doPosition = this.getAttribute("overflow") == "true" &&
|
2011-05-24 17:57:31 -07:00
|
|
|
numPinned > 0;
|
2010-11-09 11:41:37 -08:00
|
|
|
|
2011-01-17 00:38:19 -08:00
|
|
|
if (doPosition) {
|
|
|
|
this.setAttribute("positionpinnedtabs", "true");
|
|
|
|
|
2012-06-21 06:36:57 -07:00
|
|
|
let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width;
|
2011-01-17 00:38:19 -08:00
|
|
|
let paddingStart = this.mTabstrip.scrollboxPaddingStart;
|
|
|
|
let width = 0;
|
|
|
|
|
|
|
|
for (let i = numPinned - 1; i >= 0; i--) {
|
|
|
|
let tab = this.childNodes[i];
|
2012-06-21 06:36:57 -07:00
|
|
|
width += tab.getBoundingClientRect().width;
|
2010-11-24 01:50:20 -08:00
|
|
|
tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px";
|
2011-01-17 00:38:19 -08:00
|
|
|
}
|
|
|
|
|
2012-08-29 22:51:06 -07:00
|
|
|
this.style.MozPaddingStart = width + paddingStart + "px";
|
2011-01-17 00:38:19 -08:00
|
|
|
|
|
|
|
} else {
|
|
|
|
this.removeAttribute("positionpinnedtabs");
|
|
|
|
|
|
|
|
for (let i = 0; i < numPinned; i++) {
|
|
|
|
let tab = this.childNodes[i];
|
|
|
|
tab.style.MozMarginStart = "";
|
|
|
|
}
|
|
|
|
|
2012-08-29 22:51:06 -07:00
|
|
|
this.style.MozPaddingStart = "";
|
2011-01-17 00:38:19 -08:00
|
|
|
}
|
|
|
|
|
2012-10-25 10:59:33 -07:00
|
|
|
if (this._lastNumPinned != numPinned) {
|
|
|
|
this._lastNumPinned = numPinned;
|
|
|
|
this._handleTabSelect(false);
|
|
|
|
}
|
2010-06-24 07:29:02 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
<method name="_animateTabMove">
|
|
|
|
<parameter name="event"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
let draggedTab = event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
|
|
|
|
|
|
|
|
if (this.getAttribute("movingtab") != "true") {
|
|
|
|
this.setAttribute("movingtab", "true");
|
|
|
|
this.selectedItem = draggedTab;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!("animLastScreenX" in draggedTab._dragData))
|
|
|
|
draggedTab._dragData.animLastScreenX = draggedTab._dragData.screenX;
|
|
|
|
|
|
|
|
let screenX = event.screenX;
|
|
|
|
if (screenX == draggedTab._dragData.animLastScreenX)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let draggingRight = screenX > draggedTab._dragData.animLastScreenX;
|
|
|
|
draggedTab._dragData.animLastScreenX = screenX;
|
|
|
|
|
|
|
|
let rtl = (window.getComputedStyle(this).direction == "rtl");
|
|
|
|
let pinned = draggedTab.pinned;
|
|
|
|
let numPinned = this.tabbrowser._numPinnedTabs;
|
|
|
|
let tabs = this.tabbrowser.visibleTabs
|
|
|
|
.slice(pinned ? 0 : numPinned,
|
|
|
|
pinned ? numPinned : undefined);
|
|
|
|
if (rtl)
|
|
|
|
tabs.reverse();
|
|
|
|
let tabWidth = draggedTab.getBoundingClientRect().width;
|
|
|
|
|
|
|
|
// Move the dragged tab based on the mouse position.
|
|
|
|
|
|
|
|
let leftTab = tabs[0];
|
|
|
|
let rightTab = tabs[tabs.length - 1];
|
|
|
|
let tabScreenX = draggedTab.boxObject.screenX;
|
|
|
|
let translateX = screenX - draggedTab._dragData.screenX;
|
|
|
|
if (!pinned)
|
|
|
|
translateX += this.mTabstrip.scrollPosition - draggedTab._dragData.scrollX;
|
|
|
|
let leftBound = leftTab.boxObject.screenX - tabScreenX;
|
|
|
|
let rightBound = (rightTab.boxObject.screenX + rightTab.boxObject.width) -
|
|
|
|
(tabScreenX + tabWidth);
|
|
|
|
translateX = Math.max(translateX, leftBound);
|
|
|
|
translateX = Math.min(translateX, rightBound);
|
|
|
|
draggedTab.style.transform = "translateX(" + translateX + "px)";
|
|
|
|
|
|
|
|
// Determine what tab we're dragging over.
|
|
|
|
// * Point of reference is the center of the dragged tab. If that
|
|
|
|
// point touches a background tab, the dragged tab would take that
|
|
|
|
// tab's position when dropped.
|
|
|
|
// * We're doing a binary search in order to reduce the amount of
|
|
|
|
// tabs we need to check.
|
|
|
|
|
|
|
|
let tabCenter = tabScreenX + translateX + tabWidth / 2;
|
|
|
|
let newIndex = -1;
|
|
|
|
let oldIndex = "animDropIndex" in draggedTab._dragData ?
|
|
|
|
draggedTab._dragData.animDropIndex : draggedTab._tPos;
|
|
|
|
let low = 0;
|
|
|
|
let high = tabs.length - 1;
|
|
|
|
while (low <= high) {
|
|
|
|
let mid = Math.floor((low + high) / 2);
|
|
|
|
if (tabs[mid] == draggedTab &&
|
|
|
|
++mid > high)
|
|
|
|
break;
|
|
|
|
let boxObject = tabs[mid].boxObject;
|
|
|
|
let screenX = boxObject.screenX + getTabShift(tabs[mid], oldIndex);
|
|
|
|
if (screenX > tabCenter) {
|
|
|
|
high = mid - 1;
|
|
|
|
} else if (screenX + boxObject.width < tabCenter) {
|
|
|
|
low = mid + 1;
|
|
|
|
} else {
|
|
|
|
newIndex = tabs[mid]._tPos;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (newIndex >= oldIndex)
|
|
|
|
newIndex++;
|
|
|
|
if (newIndex < 0 || newIndex == oldIndex)
|
|
|
|
return;
|
|
|
|
draggedTab._dragData.animDropIndex = newIndex;
|
|
|
|
|
|
|
|
// Shift background tabs to leave a gap where the dragged tab
|
|
|
|
// would currently be dropped.
|
|
|
|
|
|
|
|
for (let tab of tabs) {
|
|
|
|
if (tab != draggedTab) {
|
|
|
|
let shift = getTabShift(tab, newIndex);
|
|
|
|
tab.style.transform = shift ? "translateX(" + shift + "px)" : "";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getTabShift(tab, dropIndex) {
|
|
|
|
if (tab._tPos < draggedTab._tPos && tab._tPos >= dropIndex)
|
|
|
|
return rtl ? -tabWidth : tabWidth;
|
|
|
|
if (tab._tPos > draggedTab._tPos && tab._tPos < dropIndex)
|
|
|
|
return rtl ? tabWidth : -tabWidth;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_finishAnimateTabMove">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (this.getAttribute("movingtab") != "true")
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (let tab of this.tabbrowser.visibleTabs)
|
|
|
|
tab.style.transform = "";
|
|
|
|
|
|
|
|
this.removeAttribute("movingtab");
|
2012-09-03 00:24:15 -07:00
|
|
|
|
|
|
|
this._handleTabSelect();
|
2012-08-27 10:44:00 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2007-08-21 22:01:54 -07:00
|
|
|
<method name="handleEvent">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
switch (aEvent.type) {
|
2012-03-11 17:59:33 -07:00
|
|
|
case "load":
|
|
|
|
this.updateVisibility();
|
|
|
|
break;
|
2007-08-21 22:02:44 -07:00
|
|
|
case "resize":
|
2010-11-16 01:19:00 -08:00
|
|
|
if (aEvent.target != window)
|
|
|
|
break;
|
2012-07-26 06:27:32 -07:00
|
|
|
|
2013-02-14 07:59:13 -08:00
|
|
|
TabsInTitlebar.updateAppearance();
|
2012-07-26 06:27:32 -07:00
|
|
|
|
2013-08-16 11:10:12 -07:00
|
|
|
if (this.tabbrowser.visibleTabs.length > 1) {
|
|
|
|
var width = this.mTabstrip.boxObject.width;
|
|
|
|
if (width != this.mTabstripWidth) {
|
|
|
|
this.adjustTabstrip();
|
|
|
|
this._fillTrailingGap();
|
|
|
|
this._handleTabSelect();
|
|
|
|
this.mTabstripWidth = width;
|
|
|
|
}
|
2007-08-21 22:02:44 -07:00
|
|
|
}
|
2012-07-26 06:27:32 -07:00
|
|
|
|
2011-01-25 11:21:56 -08:00
|
|
|
this.tabbrowser.updateWindowResizers();
|
2007-08-21 22:02:44 -07:00
|
|
|
break;
|
2011-04-11 23:50:56 -07:00
|
|
|
case "mouseout":
|
2011-10-26 17:46:58 -07:00
|
|
|
// If the "related target" (the node to which the pointer went) is not
|
|
|
|
// a child of the current document, the mouse just left the window.
|
|
|
|
let relatedTarget = aEvent.relatedTarget;
|
|
|
|
if (relatedTarget && relatedTarget.ownerDocument == document)
|
2011-04-11 23:50:56 -07:00
|
|
|
break;
|
2011-07-26 22:26:14 -07:00
|
|
|
case "mousemove":
|
2011-10-26 17:46:58 -07:00
|
|
|
if (document.getElementById("tabContextMenu").state != "open")
|
|
|
|
this._unlockTabSizing();
|
2011-07-26 22:26:14 -07:00
|
|
|
break;
|
2007-08-21 22:01:54 -07:00
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2009-10-13 12:57:48 -07:00
|
|
|
<field name="_animateElement">
|
|
|
|
this.mTabstrip._scrollButtonDown;
|
2007-08-21 22:02:12 -07:00
|
|
|
</field>
|
2010-07-17 01:08:43 -07:00
|
|
|
|
2007-08-21 22:01:34 -07:00
|
|
|
<method name="_notifyBackgroundTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
2010-06-24 07:29:02 -07:00
|
|
|
if (aTab.pinned)
|
|
|
|
return;
|
|
|
|
|
2009-07-10 02:13:10 -07:00
|
|
|
var scrollRect = this.mTabstrip.scrollClientRect;
|
|
|
|
var tab = aTab.getBoundingClientRect();
|
2007-08-21 22:01:34 -07:00
|
|
|
|
2008-03-04 03:24:41 -08:00
|
|
|
// Is the new tab already completely visible?
|
2009-07-10 02:13:10 -07:00
|
|
|
if (scrollRect.left <= tab.left && tab.right <= scrollRect.right)
|
2008-03-04 03:24:41 -08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (this.mTabstrip.smoothScroll) {
|
2010-08-19 13:22:33 -07:00
|
|
|
let selected = !this.selectedItem.pinned &&
|
|
|
|
this.selectedItem.getBoundingClientRect();
|
2008-03-04 03:24:41 -08:00
|
|
|
|
|
|
|
// Can we make both the new tab and the selected tab completely visible?
|
2010-08-19 13:22:33 -07:00
|
|
|
if (!selected ||
|
|
|
|
Math.max(tab.right - selected.left, selected.right - tab.left) <=
|
|
|
|
scrollRect.width) {
|
2008-03-04 03:24:41 -08:00
|
|
|
this.mTabstrip.ensureElementIsVisible(aTab);
|
|
|
|
return;
|
|
|
|
}
|
2007-08-21 22:01:34 -07:00
|
|
|
|
2009-04-13 10:38:09 -07:00
|
|
|
this.mTabstrip._smoothScrollByPixels(this.mTabstrip._isRTLScrollbox ?
|
2009-07-10 02:13:10 -07:00
|
|
|
selected.right - scrollRect.right :
|
|
|
|
selected.left - scrollRect.left);
|
2007-08-21 22:01:34 -07:00
|
|
|
}
|
2008-03-04 03:24:41 -08:00
|
|
|
|
2009-11-05 00:02:12 -08:00
|
|
|
if (!this._animateElement.hasAttribute("notifybgtab")) {
|
|
|
|
this._animateElement.setAttribute("notifybgtab", "true");
|
|
|
|
setTimeout(function (ele) {
|
|
|
|
ele.removeAttribute("notifybgtab");
|
|
|
|
}, 150, this._animateElement);
|
|
|
|
}
|
2007-08-21 22:01:34 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
|
|
|
<method name="_getDragTargetTab">
|
|
|
|
<parameter name="event"/>
|
|
|
|
<body><![CDATA[
|
2010-09-02 13:08:05 -07:00
|
|
|
let tab = event.target.localName == "tab" ? event.target : null;
|
|
|
|
if (tab &&
|
|
|
|
(event.type == "drop" || event.type == "dragover") &&
|
|
|
|
event.dataTransfer.dropEffect == "link") {
|
|
|
|
let boxObject = tab.boxObject;
|
|
|
|
if (event.screenX < boxObject.screenX + boxObject.width * .25 ||
|
|
|
|
event.screenX > boxObject.screenX + boxObject.width * .75)
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return tab;
|
2010-03-16 23:36:13 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_getDropIndex">
|
|
|
|
<parameter name="event"/>
|
|
|
|
<body><![CDATA[
|
2011-10-26 17:46:58 -07:00
|
|
|
var tabs = this.childNodes;
|
|
|
|
var tab = this._getDragTargetTab(event);
|
|
|
|
if (window.getComputedStyle(this, null).direction == "ltr") {
|
|
|
|
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
|
|
|
|
if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
|
|
|
|
return i;
|
|
|
|
} else {
|
|
|
|
for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
|
|
|
|
if (event.screenX > tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
|
|
|
|
return i;
|
2010-03-16 23:36:13 -07:00
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
return tabs.length;
|
2010-03-16 23:36:13 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_setEffectAllowedForDataTransfer">
|
|
|
|
<parameter name="event"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
var dt = event.dataTransfer;
|
|
|
|
// Disallow dropping multiple items
|
|
|
|
if (dt.mozItemCount > 1)
|
|
|
|
return dt.effectAllowed = "none";
|
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
var types = dt.mozTypesAt(0);
|
|
|
|
var sourceNode = null;
|
|
|
|
// tabs are always added as the first type
|
|
|
|
if (types[0] == TAB_DROP_TYPE) {
|
|
|
|
var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
|
|
|
if (sourceNode instanceof XULElement &&
|
|
|
|
sourceNode.localName == "tab" &&
|
2012-08-27 10:44:00 -07:00
|
|
|
sourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
|
|
|
|
sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" &&
|
|
|
|
sourceNode.ownerDocument.defaultView.gBrowser.tabContainer == sourceNode.parentNode) {
|
2012-12-02 12:57:06 -08:00
|
|
|
// Do not allow transfering a private tab to a non-private window
|
|
|
|
// and vice versa.
|
|
|
|
if (PrivateBrowsingUtils.isWindowPrivate(window) !=
|
|
|
|
PrivateBrowsingUtils.isWindowPrivate(sourceNode.ownerDocument.defaultView))
|
|
|
|
return dt.effectAllowed = "none";
|
|
|
|
|
2014-02-28 17:00:21 -08:00
|
|
|
if (window.gMultiProcessBrowser !=
|
|
|
|
sourceNode.ownerDocument.defaultView.gMultiProcessBrowser)
|
|
|
|
return dt.effectAllowed = "none";
|
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
#ifdef XP_MACOSX
|
|
|
|
return dt.effectAllowed = event.altKey ? "copy" : "move";
|
|
|
|
#else
|
|
|
|
return dt.effectAllowed = event.ctrlKey ? "copy" : "move";
|
|
|
|
#endif
|
2011-10-26 17:46:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-05-26 08:28:25 -07:00
|
|
|
if (browserDragAndDrop.canDropLink(event)) {
|
|
|
|
// Here we need to do this manually
|
|
|
|
return dt.effectAllowed = dt.dropEffect = "link";
|
2010-03-16 23:36:13 -07:00
|
|
|
}
|
|
|
|
return dt.effectAllowed = "none";
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2010-06-14 01:10:54 -07:00
|
|
|
<method name="_handleNewTab">
|
|
|
|
<parameter name="tab"/>
|
|
|
|
<body><![CDATA[
|
2011-05-09 23:42:39 -07:00
|
|
|
if (tab.parentNode != this)
|
2010-06-14 01:10:54 -07:00
|
|
|
return;
|
2011-09-08 02:02:05 -07:00
|
|
|
tab._fullyOpen = true;
|
2010-06-14 01:10:54 -07:00
|
|
|
|
2010-08-19 13:24:07 -07:00
|
|
|
this.adjustTabstrip();
|
|
|
|
|
2010-06-14 01:10:54 -07:00
|
|
|
if (tab.getAttribute("selected") == "true") {
|
|
|
|
this._fillTrailingGap();
|
|
|
|
this._handleTabSelect();
|
|
|
|
} else {
|
|
|
|
this._notifyBackgroundTab(tab);
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXXmano: this is a temporary workaround for bug 345399
|
|
|
|
// We need to manually update the scroll buttons disabled state
|
|
|
|
// if a tab was inserted to the overflow area or removed from it
|
|
|
|
// without any scrolling and when the tabbar has already
|
|
|
|
// overflowed.
|
|
|
|
this.mTabstrip._updateScrollButtonsDisabledState();
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2011-04-11 23:50:56 -07:00
|
|
|
|
2010-08-25 06:16:33 -07:00
|
|
|
<method name="_canAdvanceToTab">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
2011-05-24 23:50:44 -07:00
|
|
|
return !aTab.closing;
|
2010-08-25 06:16:33 -07:00
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
2010-06-14 01:10:54 -07:00
|
|
|
|
2013-02-07 15:55:39 -08:00
|
|
|
<method name="_handleTabTelemetryStart">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<parameter name="aURI"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
// Animation-smoothness telemetry/logging
|
2013-03-11 04:47:46 -07:00
|
|
|
if (Services.telemetry.canRecord || this._tabAnimationLoggingEnabled) {
|
2013-02-07 15:55:39 -08:00
|
|
|
if (aURI == "about:newtab" && (aTab._tPos == 1 || aTab._tPos == 2)) {
|
|
|
|
// Indicate newtab page animation where other tabs are unaffected
|
|
|
|
// (for which case, the 2nd or 3rd tabs are good representatives, even if not absolute)
|
|
|
|
aTab._recordingTabOpenPlain = true;
|
|
|
|
}
|
|
|
|
aTab._recordingHandle = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIDOMWindowUtils)
|
|
|
|
.startFrameTimeRecording();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Overall animation duration
|
|
|
|
aTab._animStartTime = Date.now();
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_handleTabTelemetryEnd">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body>
|
|
|
|
<![CDATA[
|
|
|
|
if (!aTab._animStartTime) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Services.telemetry.getHistogramById(aTab.closing ?
|
|
|
|
"FX_TAB_ANIM_CLOSE_MS" :
|
|
|
|
"FX_TAB_ANIM_OPEN_MS")
|
|
|
|
.add(Date.now() - aTab._animStartTime);
|
|
|
|
aTab._animStartTime = 0;
|
|
|
|
|
|
|
|
// Handle tab animation smoothness telemetry/logging of frame intervals and paint times
|
|
|
|
if (!("_recordingHandle" in aTab)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let intervals = window.QueryInterface(Ci.nsIInterfaceRequestor)
|
|
|
|
.getInterface(Ci.nsIDOMWindowUtils)
|
2013-11-26 23:32:19 -08:00
|
|
|
.stopFrameTimeRecording(aTab._recordingHandle);
|
2013-02-07 15:55:39 -08:00
|
|
|
delete aTab._recordingHandle;
|
|
|
|
let frameCount = intervals.length;
|
|
|
|
|
|
|
|
if (this._tabAnimationLoggingEnabled) {
|
2013-11-26 23:32:19 -08:00
|
|
|
let msg = "Tab " + (aTab.closing ? "close" : "open") + " (Frame-interval):\n";
|
2013-02-07 15:55:39 -08:00
|
|
|
for (let i = 0; i < frameCount; i++) {
|
2013-11-26 23:32:19 -08:00
|
|
|
msg += Math.round(intervals[i]) + "\n";
|
2013-02-07 15:55:39 -08:00
|
|
|
}
|
|
|
|
Services.console.logStringMessage(msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
// For telemetry, the first frame interval is not useful since it may represent an interval
|
|
|
|
// to a relatively old frame (prior to recording start). So we'll ignore it for the average.
|
2013-11-26 23:32:19 -08:00
|
|
|
if (frameCount > 1) {
|
2013-02-07 15:55:39 -08:00
|
|
|
let averageInterval = 0;
|
|
|
|
for (let i = 1; i < frameCount; i++) {
|
|
|
|
averageInterval += intervals[i];
|
|
|
|
};
|
2013-11-26 23:32:19 -08:00
|
|
|
averageInterval = averageInterval / (frameCount - 1);
|
2013-02-07 15:55:39 -08:00
|
|
|
|
|
|
|
Services.telemetry.getHistogramById("FX_TAB_ANIM_ANY_FRAME_INTERVAL_MS").add(averageInterval);
|
|
|
|
|
|
|
|
if (aTab._recordingTabOpenPlain) {
|
|
|
|
delete aTab._recordingTabOpenPlain;
|
|
|
|
// While we do have a telemetry probe NEWTAB_PAGE_ENABLED to monitor newtab preview, it'll be
|
|
|
|
// easier to overview the data without slicing by it. Hence the additional histograms with _PREVIEW.
|
|
|
|
let preview = this._browserNewtabpageEnabled ? "_PREVIEW" : "";
|
|
|
|
Services.telemetry.getHistogramById("FX_TAB_ANIM_OPEN" + preview + "_FRAME_INTERVAL_MS").add(averageInterval);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]]>
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2010-04-27 09:57:19 -07:00
|
|
|
<!-- Deprecated stuff, implemented for backwards compatibility. -->
|
|
|
|
<property name="mTabstripClosebutton" readonly="true"
|
|
|
|
onget="return document.getElementById('tabs-closebutton');"/>
|
|
|
|
<property name="mAllTabsPopup" readonly="true"
|
|
|
|
onget="return document.getElementById('alltabs-popup');"/>
|
2007-08-21 22:01:34 -07:00
|
|
|
</implementation>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
<handlers>
|
2007-08-21 22:01:28 -07:00
|
|
|
<handler event="TabSelect" action="this._handleTabSelect();"/>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2010-06-14 01:10:54 -07:00
|
|
|
<handler event="transitionend"><![CDATA[
|
2010-08-06 13:15:18 -07:00
|
|
|
if (event.propertyName != "max-width")
|
|
|
|
return;
|
|
|
|
|
|
|
|
var tab = event.target;
|
|
|
|
|
2013-02-07 15:55:39 -08:00
|
|
|
this._handleTabTelemetryEnd(tab);
|
2011-12-16 20:11:57 -08:00
|
|
|
|
2011-09-08 02:02:05 -07:00
|
|
|
if (tab.getAttribute("fadein") == "true") {
|
|
|
|
if (tab._fullyOpen)
|
|
|
|
this.adjustTabstrip();
|
|
|
|
else
|
|
|
|
this._handleNewTab(tab);
|
|
|
|
} else if (tab.closing) {
|
2010-08-06 13:15:18 -07:00
|
|
|
this.tabbrowser._endRemoveTab(tab);
|
2011-09-08 02:02:05 -07:00
|
|
|
}
|
2010-06-14 01:10:54 -07:00
|
|
|
]]></handler>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<handler event="dblclick"><![CDATA[
|
2011-06-15 15:46:12 -07:00
|
|
|
#ifndef XP_MACOSX
|
|
|
|
// When the tabbar has an unified appearance with the titlebar
|
|
|
|
// and menubar, a double-click in it should have the same behavior
|
|
|
|
// as double-clicking the titlebar
|
2013-06-04 15:08:55 -07:00
|
|
|
if (TabsInTitlebar.enabled || this.parentNode._dragBindingAlive)
|
2011-02-23 12:07:35 -08:00
|
|
|
return;
|
|
|
|
#endif
|
2011-06-15 15:46:12 -07:00
|
|
|
|
|
|
|
if (event.button != 0 ||
|
|
|
|
event.originalTarget.localName != "box")
|
|
|
|
return;
|
|
|
|
|
2011-02-23 12:07:35 -08:00
|
|
|
// See hack note in the tabbrowser-close-tab-button binding
|
2011-06-15 15:46:12 -07:00
|
|
|
if (!this._blockDblClick)
|
2010-03-16 23:36:13 -07:00
|
|
|
BrowserOpenTab();
|
2011-06-15 15:46:12 -07:00
|
|
|
|
|
|
|
event.preventDefault();
|
2010-03-16 23:36:13 -07:00
|
|
|
]]></handler>
|
|
|
|
|
2013-10-10 13:27:15 -07:00
|
|
|
<handler event="click" button="0" phase="capturing"><![CDATA[
|
|
|
|
/* Catches extra clicks meant for the in-tab close button.
|
|
|
|
* Placed here to avoid leaking (a temporary handler added from the
|
|
|
|
* in-tab close button binding would close over the tab and leak it
|
|
|
|
* until the handler itself was removed). (bug 897751)
|
|
|
|
*
|
|
|
|
* The only sequence in which a second click event (i.e. dblclik)
|
|
|
|
* can be dispatched on an in-tab close button is when it is shown
|
|
|
|
* after the first click (i.e. the first click event was dispatched
|
|
|
|
* on the tab). This happens when we show the close button only on
|
|
|
|
* the active tab. (bug 352021)
|
|
|
|
* The only sequence in which a third click event can be dispatched
|
|
|
|
* on an in-tab close button is when the tab was opened with a
|
|
|
|
* double click on the tabbar. (bug 378344)
|
|
|
|
* In both cases, it is most likely that the close button area has
|
|
|
|
* been accidentally clicked, therefore we do not close the tab.
|
|
|
|
*
|
|
|
|
* We don't want to ignore processing of more than one click event,
|
|
|
|
* though, since the user might actually be repeatedly clicking to
|
|
|
|
* close many tabs at once.
|
|
|
|
*/
|
|
|
|
let target = event.originalTarget;
|
2013-06-19 06:57:00 -07:00
|
|
|
if (target.classList.contains('tab-close-button')) {
|
2013-10-10 13:27:15 -07:00
|
|
|
// We preemptively set this to allow the closing-multiple-tabs-
|
|
|
|
// in-a-row case.
|
|
|
|
if (this._blockDblClick) {
|
|
|
|
target._ignoredCloseButtonClicks = true;
|
|
|
|
} else if (event.detail > 1 && !target._ignoredCloseButtonClicks) {
|
|
|
|
target._ignoredCloseButtonClicks = true;
|
|
|
|
event.stopPropagation();
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
// Reset the "ignored click" flag
|
|
|
|
target._ignoredCloseButtonClicks = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Protects from close-tab-button errant doubleclick:
|
|
|
|
* Since we're removing the event target, if the user
|
|
|
|
* double-clicks the button, the dblclick event will be dispatched
|
|
|
|
* with the tabbar as its event target (and explicit/originalTarget),
|
|
|
|
* which treats that as a mouse gesture for opening a new tab.
|
|
|
|
* In this context, we're manually blocking the dblclick event
|
|
|
|
* (see tabbrowser-close-tab-button dblclick handler).
|
|
|
|
*/
|
|
|
|
if (this._blockDblClick) {
|
|
|
|
if (!("_clickedTabBarOnce" in this)) {
|
|
|
|
this._clickedTabBarOnce = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete this._clickedTabBarOnce;
|
|
|
|
this._blockDblClick = false;
|
|
|
|
}
|
|
|
|
]]></handler>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<handler event="click"><![CDATA[
|
2010-06-21 23:28:15 -07:00
|
|
|
if (event.button != 1)
|
2010-03-16 23:36:13 -07:00
|
|
|
return;
|
|
|
|
|
2010-06-21 23:28:15 -07:00
|
|
|
if (event.target.localName == "tab") {
|
|
|
|
if (this.childNodes.length > 1 || !this._closeWindowWithLastTab)
|
2011-04-11 23:50:56 -07:00
|
|
|
this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true});
|
2010-06-21 23:28:15 -07:00
|
|
|
} else if (event.originalTarget.localName == "box") {
|
|
|
|
BrowserOpenTab();
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
]]></handler>
|
|
|
|
|
2010-05-13 08:37:17 -07:00
|
|
|
<handler event="keypress"><![CDATA[
|
|
|
|
if (event.altKey || event.shiftKey ||
|
|
|
|
#ifdef XP_MACOSX
|
|
|
|
!event.metaKey)
|
|
|
|
#else
|
|
|
|
!event.ctrlKey || event.metaKey)
|
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (event.keyCode) {
|
|
|
|
case KeyEvent.DOM_VK_UP:
|
|
|
|
this.tabbrowser.moveTabBackward();
|
|
|
|
break;
|
|
|
|
case KeyEvent.DOM_VK_DOWN:
|
|
|
|
this.tabbrowser.moveTabForward();
|
|
|
|
break;
|
|
|
|
case KeyEvent.DOM_VK_RIGHT:
|
|
|
|
case KeyEvent.DOM_VK_LEFT:
|
|
|
|
this.tabbrowser.moveTabOver(event);
|
|
|
|
break;
|
|
|
|
case KeyEvent.DOM_VK_HOME:
|
|
|
|
this.tabbrowser.moveTabToStart();
|
|
|
|
break;
|
|
|
|
case KeyEvent.DOM_VK_END:
|
|
|
|
this.tabbrowser.moveTabToEnd();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
// Stop the keypress event for the above keyboard
|
|
|
|
// shortcuts only.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
|
|
|
event.preventDefault();
|
|
|
|
]]></handler>
|
|
|
|
|
2010-03-16 23:36:13 -07:00
|
|
|
<handler event="dragstart"><![CDATA[
|
|
|
|
var tab = this._getDragTargetTab(event);
|
2013-10-22 09:51:39 -07:00
|
|
|
if (!tab || this._isCustomizing)
|
2010-03-16 23:36:13 -07:00
|
|
|
return;
|
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
let dt = event.dataTransfer;
|
|
|
|
dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
|
2012-09-20 06:16:28 -07:00
|
|
|
let browser = tab.linkedBrowser;
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
// We must not set text/x-moz-url or text/plain data here,
|
|
|
|
// otherwise trying to deatch the tab by dropping it on the desktop
|
|
|
|
// may result in an "internet shortcut"
|
2012-09-20 06:16:28 -07:00
|
|
|
dt.mozSetDataAt("text/x-moz-text-internal", browser.currentURI.spec, 0);
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
// Set the cursor to an arrow during tab drags.
|
|
|
|
dt.mozCursor = "default";
|
|
|
|
|
2012-08-08 23:46:17 -07:00
|
|
|
// Create a canvas to which we capture the current tab.
|
2012-09-29 04:36:09 -07:00
|
|
|
// Until canvas is HiDPI-aware (bug 780362), we need to scale the desired
|
|
|
|
// canvas size (in CSS pixels) to the window's backing resolution in order
|
|
|
|
// to get a full-resolution drag image for use on HiDPI displays.
|
|
|
|
let windowUtils = window.getInterface(Ci.nsIDOMWindowUtils);
|
|
|
|
let scale = windowUtils.screenPixelsPerCSSPixel / windowUtils.fullZoom;
|
2012-08-08 23:46:17 -07:00
|
|
|
let canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
|
2012-08-27 10:44:00 -07:00
|
|
|
canvas.mozOpaque = true;
|
2012-09-29 04:36:09 -07:00
|
|
|
canvas.width = 160 * scale;
|
|
|
|
canvas.height = 90 * scale;
|
2012-08-08 23:46:17 -07:00
|
|
|
PageThumbs.captureToCanvas(browser.contentWindow, canvas);
|
2012-09-29 04:36:09 -07:00
|
|
|
dt.setDragImage(canvas, -16 * scale, -16 * scale);
|
2011-10-26 17:46:58 -07:00
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
// _dragData.offsetX/Y give the coordinates that the mouse should be
|
2011-10-26 17:46:58 -07:00
|
|
|
// positioned relative to the corner of the new window created upon
|
|
|
|
// dragend such that the mouse appears to have the same position
|
|
|
|
// relative to the corner of the dragged tab.
|
|
|
|
function clientX(ele) ele.getBoundingClientRect().left;
|
2012-09-20 06:16:28 -07:00
|
|
|
let tabOffsetX = clientX(tab) - clientX(this);
|
2012-08-27 10:44:00 -07:00
|
|
|
tab._dragData = {
|
|
|
|
offsetX: event.screenX - window.screenX - tabOffsetX,
|
|
|
|
offsetY: event.screenY - window.screenY,
|
|
|
|
scrollX: this.mTabstrip.scrollPosition,
|
|
|
|
screenX: event.screenX
|
|
|
|
};
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
event.stopPropagation();
|
|
|
|
]]></handler>
|
|
|
|
|
|
|
|
<handler event="dragover"><![CDATA[
|
|
|
|
var effects = this._setEffectAllowedForDataTransfer(event);
|
|
|
|
|
|
|
|
var ind = this._tabDropIndicator;
|
|
|
|
if (effects == "" || effects == "none") {
|
|
|
|
ind.collapsed = true;
|
2011-07-28 21:26:38 -07:00
|
|
|
return;
|
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
event.preventDefault();
|
|
|
|
event.stopPropagation();
|
2011-07-28 21:26:38 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
var tabStrip = this.mTabstrip;
|
|
|
|
var ltr = (window.getComputedStyle(this, null).direction == "ltr");
|
|
|
|
|
|
|
|
// autoscroll the tab strip if we drag over the scroll
|
|
|
|
// buttons, even if we aren't dragging a tab, but then
|
|
|
|
// return to avoid drawing the drop indicator
|
|
|
|
var pixelsToScroll = 0;
|
|
|
|
if (this.getAttribute("overflow") == "true") {
|
|
|
|
var targetAnonid = event.originalTarget.getAttribute("anonid");
|
|
|
|
switch (targetAnonid) {
|
|
|
|
case "scrollbutton-up":
|
|
|
|
pixelsToScroll = tabStrip.scrollIncrement * -1;
|
|
|
|
break;
|
|
|
|
case "scrollbutton-down":
|
|
|
|
pixelsToScroll = tabStrip.scrollIncrement;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (pixelsToScroll)
|
|
|
|
tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll);
|
|
|
|
}
|
2011-07-04 03:51:47 -07:00
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
if (effects == "move" &&
|
|
|
|
this == event.dataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0).parentNode) {
|
|
|
|
ind.collapsed = true;
|
|
|
|
this._animateTabMove(event);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-09-03 00:24:15 -07:00
|
|
|
this._finishAnimateTabMove();
|
2012-08-27 10:44:00 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
if (effects == "link") {
|
|
|
|
let tab = this._getDragTargetTab(event);
|
|
|
|
if (tab) {
|
|
|
|
if (!this._dragTime)
|
|
|
|
this._dragTime = Date.now();
|
|
|
|
if (Date.now() >= this._dragTime + this._dragOverDelay)
|
|
|
|
this.selectedItem = tab;
|
|
|
|
ind.collapsed = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2012-09-03 09:10:30 -07:00
|
|
|
var rect = tabStrip.getBoundingClientRect();
|
2011-10-26 17:46:58 -07:00
|
|
|
var newMargin;
|
|
|
|
if (pixelsToScroll) {
|
|
|
|
// if we are scrolling, put the drop indicator at the edge
|
|
|
|
// so that it doesn't jump while scrolling
|
2012-09-10 03:24:29 -07:00
|
|
|
let scrollRect = tabStrip.scrollClientRect;
|
|
|
|
let minMargin = scrollRect.left - rect.left;
|
|
|
|
let maxMargin = Math.min(minMargin + scrollRect.width,
|
|
|
|
scrollRect.right);
|
|
|
|
if (!ltr)
|
|
|
|
[minMargin, maxMargin] = [this.clientWidth - maxMargin,
|
|
|
|
this.clientWidth - minMargin];
|
2011-10-26 17:46:58 -07:00
|
|
|
newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
|
|
|
|
}
|
|
|
|
else {
|
2012-09-06 08:59:57 -07:00
|
|
|
let newIndex = this._getDropIndex(event);
|
2011-10-26 17:46:58 -07:00
|
|
|
if (newIndex == this.childNodes.length) {
|
|
|
|
let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
|
|
|
|
if (ltr)
|
|
|
|
newMargin = tabRect.right - rect.left;
|
|
|
|
else
|
|
|
|
newMargin = rect.right - tabRect.left;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let tabRect = this.childNodes[newIndex].getBoundingClientRect();
|
|
|
|
if (ltr)
|
|
|
|
newMargin = tabRect.left - rect.left;
|
|
|
|
else
|
|
|
|
newMargin = rect.right - tabRect.right;
|
|
|
|
}
|
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
ind.collapsed = false;
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
newMargin += ind.clientWidth / 2;
|
|
|
|
if (!ltr)
|
|
|
|
newMargin *= -1;
|
2010-08-09 00:43:24 -07:00
|
|
|
|
2012-07-16 08:10:27 -07:00
|
|
|
ind.style.transform = "translate(" + Math.round(newMargin) + "px)";
|
2011-10-26 17:46:58 -07:00
|
|
|
ind.style.MozMarginStart = (-ind.clientWidth) + "px";
|
|
|
|
]]></handler>
|
2010-08-09 00:43:24 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
<handler event="drop"><![CDATA[
|
|
|
|
var dt = event.dataTransfer;
|
|
|
|
var dropEffect = dt.dropEffect;
|
|
|
|
var draggedTab;
|
|
|
|
if (dropEffect != "link") { // copy or move
|
|
|
|
draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
|
|
|
// not our drop then
|
|
|
|
if (!draggedTab)
|
|
|
|
return;
|
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
this._tabDropIndicator.collapsed = true;
|
|
|
|
event.stopPropagation();
|
2012-08-27 10:44:00 -07:00
|
|
|
if (draggedTab && dropEffect == "copy") {
|
|
|
|
// copy the dropped tab (wherever it's from)
|
2011-10-26 17:46:58 -07:00
|
|
|
let newIndex = this._getDropIndex(event);
|
2012-08-27 10:44:00 -07:00
|
|
|
let newTab = this.tabbrowser.duplicateTab(draggedTab);
|
|
|
|
this.tabbrowser.moveTabTo(newTab, newIndex);
|
|
|
|
if (draggedTab.parentNode != this || event.shiftKey)
|
|
|
|
this.selectedItem = newTab;
|
|
|
|
} else if (draggedTab && draggedTab.parentNode == this) {
|
2012-12-06 02:42:07 -08:00
|
|
|
this._finishAnimateTabMove();
|
|
|
|
|
2012-09-03 00:24:15 -07:00
|
|
|
// actually move the dragged tab
|
|
|
|
if ("animDropIndex" in draggedTab._dragData) {
|
|
|
|
let newIndex = draggedTab._dragData.animDropIndex;
|
|
|
|
if (newIndex > draggedTab._tPos)
|
|
|
|
newIndex--;
|
|
|
|
this.tabbrowser.moveTabTo(draggedTab, newIndex);
|
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
} else if (draggedTab) {
|
|
|
|
// swap the dropped tab with a new one we create and then close
|
|
|
|
// it in the other window (making it seem to have moved between
|
|
|
|
// windows)
|
2011-07-26 22:26:14 -07:00
|
|
|
let newIndex = this._getDropIndex(event);
|
2011-10-26 17:46:58 -07:00
|
|
|
let newTab = this.tabbrowser.addTab("about:blank");
|
|
|
|
let newBrowser = this.tabbrowser.getBrowserForTab(newTab);
|
|
|
|
// Stop the about:blank load
|
|
|
|
newBrowser.stop();
|
|
|
|
// make sure it has a docshell
|
|
|
|
newBrowser.docShell;
|
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
let numPinned = this.tabbrowser._numPinnedTabs;
|
|
|
|
if (newIndex < numPinned || draggedTab.pinned && newIndex == numPinned)
|
|
|
|
this.tabbrowser.pinTab(newTab);
|
2011-07-26 22:26:14 -07:00
|
|
|
this.tabbrowser.moveTabTo(newTab, newIndex);
|
2011-10-26 17:46:58 -07:00
|
|
|
|
2013-03-15 06:13:52 -07:00
|
|
|
// We need to select the tab before calling swapBrowsersAndCloseOther
|
|
|
|
// so that window.content in chrome windows points to the right tab
|
|
|
|
// when pagehide/show events are fired.
|
|
|
|
this.tabbrowser.selectedTab = newTab;
|
|
|
|
|
2012-08-29 22:50:28 -07:00
|
|
|
draggedTab.parentNode._finishAnimateTabMove();
|
2011-10-26 17:46:58 -07:00
|
|
|
this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
|
|
|
|
|
2013-03-15 06:13:52 -07:00
|
|
|
// Call updateCurrentBrowser to make sure the URL bar is up to date
|
|
|
|
// for our new tab after we've done swapBrowsersAndCloseOther.
|
2013-03-19 02:14:41 -07:00
|
|
|
this.tabbrowser.updateCurrentBrowser(true);
|
2010-03-16 23:36:13 -07:00
|
|
|
} else {
|
2012-02-14 15:08:35 -08:00
|
|
|
// Pass true to disallow dropping javascript: or data: urls
|
|
|
|
let url;
|
|
|
|
try {
|
|
|
|
url = browserDragAndDrop.drop(event, { }, true);
|
|
|
|
} catch (ex) {}
|
2011-10-26 17:46:58 -07:00
|
|
|
|
2013-03-27 08:49:02 -07:00
|
|
|
if (!url)
|
2010-03-16 23:36:13 -07:00
|
|
|
return;
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
|
|
|
|
|
|
|
|
if (event.shiftKey)
|
|
|
|
bgLoad = !bgLoad;
|
|
|
|
|
|
|
|
let tab = this._getDragTargetTab(event);
|
|
|
|
if (!tab || dropEffect == "copy") {
|
|
|
|
// We're adding a new tab.
|
|
|
|
let newIndex = this._getDropIndex(event);
|
2013-03-27 08:49:02 -07:00
|
|
|
let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true});
|
2011-10-26 17:46:58 -07:00
|
|
|
this.tabbrowser.moveTabTo(newTab, newIndex);
|
|
|
|
} else {
|
|
|
|
// Load in an existing tab.
|
|
|
|
try {
|
2014-01-12 12:02:27 -08:00
|
|
|
let webNav = Ci.nsIWebNavigation;
|
|
|
|
let flags = webNav.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
|
|
|
|
webNav.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
|
|
|
|
this.tabbrowser.getBrowserForTab(tab).loadURIWithFlags(url, flags);
|
2011-10-26 17:46:58 -07:00
|
|
|
if (!bgLoad)
|
|
|
|
this.selectedItem = tab;
|
|
|
|
} catch(ex) {
|
|
|
|
// Just ignore invalid urls
|
|
|
|
}
|
2010-03-16 23:36:13 -07:00
|
|
|
}
|
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
|
2012-02-14 15:08:32 -08:00
|
|
|
if (draggedTab) {
|
2012-08-27 10:44:00 -07:00
|
|
|
delete draggedTab._dragData;
|
2012-02-14 15:08:32 -08:00
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
]]></handler>
|
|
|
|
|
|
|
|
<handler event="dragend"><![CDATA[
|
|
|
|
// Note: while this case is correctly handled here, this event
|
|
|
|
// isn't dispatched when the tab is moved within the tabstrip,
|
|
|
|
// see bug 460801.
|
|
|
|
|
2012-09-03 00:24:15 -07:00
|
|
|
this._finishAnimateTabMove();
|
2012-08-27 10:44:00 -07:00
|
|
|
|
2011-10-26 17:46:58 -07:00
|
|
|
var dt = event.dataTransfer;
|
2012-08-27 10:44:00 -07:00
|
|
|
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
2013-10-22 09:51:39 -07:00
|
|
|
if (dt.mozUserCancelled || dt.dropEffect != "none" || this._isCustomizing) {
|
2012-08-27 10:44:00 -07:00
|
|
|
delete draggedTab._dragData;
|
2011-10-26 17:46:58 -07:00
|
|
|
return;
|
2012-08-27 10:44:00 -07:00
|
|
|
}
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
// Disable detach within the browser toolbox
|
|
|
|
var eX = event.screenX;
|
|
|
|
var eY = event.screenY;
|
|
|
|
var wX = window.screenX;
|
|
|
|
// check if the drop point is horizontally within the window
|
|
|
|
if (eX > wX && eX < (wX + window.outerWidth)) {
|
|
|
|
let bo = this.mTabstrip.boxObject;
|
|
|
|
// also avoid detaching if the the tab was dropped too close to
|
|
|
|
// the tabbar (half a tab)
|
|
|
|
let endScreenY = bo.screenY + 1.5 * bo.height;
|
|
|
|
if (eY < endScreenY && eY > window.screenY)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// screen.availLeft et. al. only check the screen that this window is on,
|
|
|
|
// but we want to look at the screen the tab is being dropped onto.
|
|
|
|
var sX = {}, sY = {}, sWidth = {}, sHeight = {};
|
|
|
|
Cc["@mozilla.org/gfx/screenmanager;1"]
|
|
|
|
.getService(Ci.nsIScreenManager)
|
|
|
|
.screenForRect(eX, eY, 1, 1)
|
|
|
|
.GetAvailRect(sX, sY, sWidth, sHeight);
|
|
|
|
// ensure new window entirely within screen
|
|
|
|
var winWidth = Math.min(window.outerWidth, sWidth.value);
|
|
|
|
var winHeight = Math.min(window.outerHeight, sHeight.value);
|
2012-08-27 10:44:00 -07:00
|
|
|
var left = Math.min(Math.max(eX - draggedTab._dragData.offsetX, sX.value),
|
2011-10-26 17:46:58 -07:00
|
|
|
sX.value + sWidth.value - winWidth);
|
2012-08-27 10:44:00 -07:00
|
|
|
var top = Math.min(Math.max(eY - draggedTab._dragData.offsetY, sY.value),
|
2011-10-26 17:46:58 -07:00
|
|
|
sY.value + sHeight.value - winHeight);
|
|
|
|
|
2012-08-27 10:44:00 -07:00
|
|
|
delete draggedTab._dragData;
|
2011-10-26 17:46:58 -07:00
|
|
|
|
|
|
|
if (this.tabbrowser.tabs.length == 1) {
|
|
|
|
// resize _before_ move to ensure the window fits the new screen. if
|
|
|
|
// the window is too large for its screen, the window manager may do
|
|
|
|
// automatic repositioning.
|
|
|
|
window.resizeTo(winWidth, winHeight);
|
|
|
|
window.moveTo(left, top);
|
|
|
|
window.focus();
|
|
|
|
} else {
|
|
|
|
this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left,
|
|
|
|
screenY: top,
|
|
|
|
#ifndef XP_WIN
|
|
|
|
outerWidth: winWidth,
|
|
|
|
outerHeight: winHeight
|
|
|
|
#endif
|
|
|
|
});
|
|
|
|
}
|
|
|
|
event.stopPropagation();
|
2010-03-16 23:36:13 -07:00
|
|
|
]]></handler>
|
|
|
|
|
2010-12-03 08:19:55 -08:00
|
|
|
<handler event="dragexit"><![CDATA[
|
2010-03-16 23:36:13 -07:00
|
|
|
this._dragTime = 0;
|
|
|
|
|
|
|
|
// This does not work at all (see bug 458613)
|
|
|
|
var target = event.relatedTarget;
|
|
|
|
while (target && target != this)
|
|
|
|
target = target.parentNode;
|
|
|
|
if (target)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this._tabDropIndicator.collapsed = true;
|
|
|
|
event.stopPropagation();
|
|
|
|
]]></handler>
|
2007-08-21 22:01:34 -07:00
|
|
|
</handlers>
|
|
|
|
</binding>
|
|
|
|
|
2007-08-21 22:01:33 -07:00
|
|
|
<!-- close-tab-button binding
|
|
|
|
This binding relies on the structure of the tabbrowser binding.
|
2007-08-21 22:01:34 -07:00
|
|
|
Therefore it should only be used as a child of the tab or the tabs
|
2007-08-21 22:01:33 -07:00
|
|
|
element (in both cases, when they are anonymous nodes of <tabbrowser>).
|
|
|
|
-->
|
|
|
|
<binding id="tabbrowser-close-tab-button"
|
2007-08-21 22:02:01 -07:00
|
|
|
extends="chrome://global/content/bindings/toolbarbutton.xml#toolbarbutton-image">
|
2007-08-21 22:01:33 -07:00
|
|
|
<handlers>
|
2007-08-21 22:02:09 -07:00
|
|
|
<handler event="click" button="0"><![CDATA[
|
2007-08-21 22:01:33 -07:00
|
|
|
var bindingParent = document.getBindingParent(this);
|
2010-04-27 09:57:19 -07:00
|
|
|
var tabContainer = bindingParent.parentNode;
|
2011-04-11 23:50:56 -07:00
|
|
|
tabContainer.tabbrowser.removeTab(bindingParent, {animate: true, byMouse: true});
|
2013-10-10 13:27:15 -07:00
|
|
|
// This enables double-click protection for the tab container
|
|
|
|
// (see tabbrowser-tabs 'click' handler).
|
2010-06-14 01:09:55 -07:00
|
|
|
tabContainer._blockDblClick = true;
|
2007-08-21 22:01:33 -07:00
|
|
|
]]></handler>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
2007-08-21 22:02:09 -07:00
|
|
|
<handler event="dblclick" button="0" phase="capturing">
|
2007-08-21 22:01:33 -07:00
|
|
|
// for the one-close-button case
|
|
|
|
event.stopPropagation();
|
|
|
|
</handler>
|
2010-03-16 23:36:13 -07:00
|
|
|
|
|
|
|
<handler event="dragstart">
|
|
|
|
event.stopPropagation();
|
|
|
|
</handler>
|
2007-08-21 22:01:33 -07:00
|
|
|
</handlers>
|
|
|
|
</binding>
|
|
|
|
|
2007-11-21 04:04:21 -08:00
|
|
|
<binding id="tabbrowser-tab" display="xul:hbox"
|
2007-08-21 22:00:54 -07:00
|
|
|
extends="chrome://global/content/bindings/tabbox.xml#tab">
|
2010-03-16 23:36:13 -07:00
|
|
|
<resources>
|
|
|
|
<stylesheet src="chrome://browser/content/tabbrowser.css"/>
|
|
|
|
</resources>
|
|
|
|
|
2010-07-17 01:08:43 -07:00
|
|
|
<content context="tabContextMenu" closetabtext="&closeTab.label;">
|
2010-09-15 00:28:37 -07:00
|
|
|
<xul:stack class="tab-stack" flex="1">
|
2013-11-19 01:41:49 -08:00
|
|
|
<xul:hbox xbl:inherits="pinned,selected,titlechanged,fadein"
|
2010-11-29 06:18:40 -08:00
|
|
|
class="tab-background">
|
|
|
|
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
|
|
|
|
class="tab-background-start"/>
|
|
|
|
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
|
|
|
|
class="tab-background-middle"/>
|
|
|
|
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
|
|
|
|
class="tab-background-end"/>
|
|
|
|
</xul:hbox>
|
|
|
|
<xul:hbox xbl:inherits="pinned,selected,titlechanged"
|
|
|
|
class="tab-content" align="center">
|
2010-10-11 20:47:59 -07:00
|
|
|
<xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
|
|
|
|
class="tab-throbber"
|
2012-09-24 13:31:48 -07:00
|
|
|
role="presentation"
|
|
|
|
layer="true" />
|
2013-02-16 02:11:29 -08:00
|
|
|
<xul:image xbl:inherits="src=image,fadein,pinned,selected"
|
2014-01-13 07:28:18 -08:00
|
|
|
anonid="tab-icon-image"
|
2010-09-15 00:28:37 -07:00
|
|
|
class="tab-icon-image"
|
2013-02-16 02:11:29 -08:00
|
|
|
validate="never"
|
2010-09-15 00:28:37 -07:00
|
|
|
role="presentation"/>
|
|
|
|
<xul:label flex="1"
|
2013-11-28 16:15:16 -08:00
|
|
|
anonid="tab-label"
|
|
|
|
xbl:inherits="value=visibleLabel,crop,accesskey,fadein,pinned,selected"
|
2010-09-15 00:28:37 -07:00
|
|
|
class="tab-text tab-label"
|
|
|
|
role="presentation"/>
|
|
|
|
<xul:toolbarbutton anonid="close-button"
|
|
|
|
xbl:inherits="fadein,pinned,selected"
|
2013-06-05 12:39:36 -07:00
|
|
|
class="tab-close-button close-icon"/>
|
2010-09-15 00:28:37 -07:00
|
|
|
</xul:hbox>
|
|
|
|
</xul:stack>
|
2007-08-21 22:00:54 -07:00
|
|
|
</content>
|
2007-08-21 22:00:55 -07:00
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
<implementation>
|
2013-11-28 16:15:16 -08:00
|
|
|
<property name="label">
|
|
|
|
<getter>
|
|
|
|
return this.getAttribute("label");
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
this.setAttribute("label", val);
|
|
|
|
let event = new CustomEvent("TabLabelModified", {
|
|
|
|
bubbles: true,
|
|
|
|
cancelable: true
|
|
|
|
});
|
|
|
|
this.dispatchEvent(event);
|
|
|
|
|
|
|
|
// Let listeners prevent synchronizing the actual label to the
|
|
|
|
// visible label (allowing them to override the visible label).
|
|
|
|
if (!event.defaultPrevented)
|
|
|
|
this.visibleLabel = val;
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
<property name="visibleLabel">
|
|
|
|
<getter>
|
|
|
|
return this.getAttribute("visibleLabel");
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
this.setAttribute("visibleLabel", val);
|
|
|
|
</setter>
|
|
|
|
</property>
|
2010-06-24 07:29:02 -07:00
|
|
|
<property name="pinned" readonly="true">
|
|
|
|
<getter>
|
|
|
|
return this.getAttribute("pinned") == "true";
|
|
|
|
</getter>
|
|
|
|
</property>
|
2010-10-11 10:27:05 -07:00
|
|
|
<property name="hidden" readonly="true">
|
|
|
|
<getter>
|
|
|
|
return this.getAttribute("hidden") == "true";
|
|
|
|
</getter>
|
|
|
|
</property>
|
2010-06-24 07:29:02 -07:00
|
|
|
|
2014-02-06 08:28:54 -08:00
|
|
|
<property name="lastAccessed">
|
|
|
|
<getter>
|
|
|
|
return this.selected ? Date.now() : this._lastAccessed;
|
|
|
|
</getter>
|
|
|
|
<setter>
|
|
|
|
this._lastAccessed = val;
|
|
|
|
</setter>
|
|
|
|
</property>
|
|
|
|
<field name="_lastAccessed">0</field>
|
|
|
|
|
2007-08-21 22:00:54 -07:00
|
|
|
<field name="mOverCloseButton">false</field>
|
2009-07-10 11:34:46 -07:00
|
|
|
<field name="mCorrespondingMenuitem">null</field>
|
2011-05-24 23:50:44 -07:00
|
|
|
<field name="closing">false</field>
|
2013-09-25 07:43:36 -07:00
|
|
|
|
|
|
|
<method name="_mouseenter">
|
|
|
|
<body><![CDATA[
|
|
|
|
if (this.closing)
|
|
|
|
return;
|
|
|
|
|
|
|
|
let tabContainer = this.parentNode;
|
|
|
|
let visibleTabs = tabContainer.tabbrowser.visibleTabs;
|
|
|
|
let tabIndex = visibleTabs.indexOf(this);
|
|
|
|
if (tabIndex == 0) {
|
|
|
|
tabContainer._beforeHoveredTab = null;
|
|
|
|
} else {
|
|
|
|
let candidate = visibleTabs[tabIndex - 1];
|
|
|
|
if (!candidate.selected) {
|
|
|
|
tabContainer._beforeHoveredTab = candidate;
|
|
|
|
candidate.setAttribute("beforehovered", "true");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (tabIndex == visibleTabs.length - 1) {
|
|
|
|
tabContainer._afterHoveredTab = null;
|
|
|
|
} else {
|
|
|
|
let candidate = visibleTabs[tabIndex + 1];
|
|
|
|
if (!candidate.selected) {
|
|
|
|
tabContainer._afterHoveredTab = candidate;
|
|
|
|
candidate.setAttribute("afterhovered", "true");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
tabContainer._hoveredTab = this;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_mouseleave">
|
|
|
|
<body><![CDATA[
|
|
|
|
let tabContainer = this.parentNode;
|
|
|
|
if (tabContainer._beforeHoveredTab) {
|
|
|
|
tabContainer._beforeHoveredTab.removeAttribute("beforehovered");
|
|
|
|
tabContainer._beforeHoveredTab = null;
|
|
|
|
}
|
|
|
|
if (tabContainer._afterHoveredTab) {
|
|
|
|
tabContainer._afterHoveredTab.removeAttribute("afterhovered");
|
|
|
|
tabContainer._afterHoveredTab = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
tabContainer._hoveredTab = null;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2007-08-21 22:00:54 -07:00
|
|
|
</implementation>
|
|
|
|
|
|
|
|
<handlers>
|
2013-03-29 14:34:56 -07:00
|
|
|
<handler event="mouseover"><![CDATA[
|
|
|
|
let anonid = event.originalTarget.getAttribute("anonid");
|
2007-08-21 22:00:54 -07:00
|
|
|
if (anonid == "close-button")
|
|
|
|
this.mOverCloseButton = true;
|
2013-03-29 14:34:56 -07:00
|
|
|
|
2013-09-25 07:43:36 -07:00
|
|
|
this._mouseenter();
|
2013-03-19 16:41:01 -07:00
|
|
|
]]></handler>
|
2013-03-29 14:34:56 -07:00
|
|
|
<handler event="mouseout"><![CDATA[
|
|
|
|
let anonid = event.originalTarget.getAttribute("anonid");
|
|
|
|
if (anonid == "close-button")
|
|
|
|
this.mOverCloseButton = false;
|
|
|
|
|
2013-09-25 07:43:36 -07:00
|
|
|
this._mouseleave();
|
2013-03-19 16:41:01 -07:00
|
|
|
]]></handler>
|
2009-03-09 10:43:44 -07:00
|
|
|
<handler event="dragstart" phase="capturing">
|
|
|
|
this.style.MozUserFocus = '';
|
|
|
|
</handler>
|
2011-09-06 07:22:57 -07:00
|
|
|
<handler event="mousedown" phase="capturing">
|
2007-08-21 22:00:54 -07:00
|
|
|
<![CDATA[
|
2011-08-30 08:30:41 -07:00
|
|
|
if (this.selected) {
|
2009-03-09 10:43:44 -07:00
|
|
|
this.style.MozUserFocus = 'ignore';
|
|
|
|
this.clientTop; // just using this to flush style updates
|
2011-09-06 07:22:57 -07:00
|
|
|
} else if (this.mOverCloseButton) {
|
|
|
|
// Prevent tabbox.xml from selecting the tab.
|
|
|
|
event.stopPropagation();
|
2009-03-09 10:43:44 -07:00
|
|
|
}
|
2007-08-21 22:00:54 -07:00
|
|
|
]]>
|
2009-03-09 10:43:44 -07:00
|
|
|
</handler>
|
|
|
|
<handler event="mouseup">
|
|
|
|
this.style.MozUserFocus = '';
|
|
|
|
</handler>
|
2007-08-21 22:00:54 -07:00
|
|
|
</handlers>
|
|
|
|
</binding>
|
2007-08-21 21:58:49 -07:00
|
|
|
|
2009-07-10 11:34:46 -07:00
|
|
|
<binding id="tabbrowser-alltabs-popup"
|
|
|
|
extends="chrome://global/content/bindings/popup.xml#popup">
|
|
|
|
<implementation implements="nsIDOMEventListener">
|
|
|
|
<method name="_tabOnAttrModified">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
2009-12-12 11:31:21 -08:00
|
|
|
var tab = aEvent.target;
|
2012-01-23 16:39:49 -08:00
|
|
|
if (tab.mCorrespondingMenuitem)
|
|
|
|
this._setMenuitemAttributes(tab.mCorrespondingMenuitem, tab);
|
2009-07-10 11:34:46 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_tabOnTabClose">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
2012-01-23 16:39:49 -08:00
|
|
|
var tab = aEvent.target;
|
|
|
|
if (tab.mCorrespondingMenuitem)
|
|
|
|
this.removeChild(tab.mCorrespondingMenuitem);
|
2009-07-10 11:34:46 -07:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="handleEvent">
|
|
|
|
<parameter name="aEvent"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
switch (aEvent.type) {
|
2009-12-12 11:31:21 -08:00
|
|
|
case "TabAttrModified":
|
2009-07-10 11:34:46 -07:00
|
|
|
this._tabOnAttrModified(aEvent);
|
|
|
|
break;
|
|
|
|
case "TabClose":
|
|
|
|
this._tabOnTabClose(aEvent);
|
|
|
|
break;
|
|
|
|
case "scroll":
|
|
|
|
this._updateTabsVisibilityStatus();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_updateTabsVisibilityStatus">
|
|
|
|
<body><![CDATA[
|
2010-04-27 09:57:19 -07:00
|
|
|
var tabContainer = gBrowser.tabContainer;
|
2009-07-10 11:34:46 -07:00
|
|
|
// We don't want menu item decoration unless there is overflow.
|
|
|
|
if (tabContainer.getAttribute("overflow") != "true")
|
|
|
|
return;
|
|
|
|
|
|
|
|
var tabstripBO = tabContainer.mTabstrip.scrollBoxObject;
|
|
|
|
for (var i = 0; i < this.childNodes.length; i++) {
|
2011-04-28 22:21:13 -07:00
|
|
|
let curTab = this.childNodes[i].tab;
|
|
|
|
if (!curTab) // "Tab Groups" menuitem and its menuseparator
|
|
|
|
continue;
|
|
|
|
let curTabBO = curTab.boxObject;
|
2009-07-10 11:34:46 -07:00
|
|
|
if (curTabBO.screenX >= tabstripBO.screenX &&
|
|
|
|
curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width)
|
2011-05-24 23:50:44 -07:00
|
|
|
this.childNodes[i].setAttribute("tabIsVisible", "true");
|
2009-07-10 11:34:46 -07:00
|
|
|
else
|
|
|
|
this.childNodes[i].removeAttribute("tabIsVisible");
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_createTabMenuItem">
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
var menuItem = document.createElementNS(
|
2011-05-24 23:50:44 -07:00
|
|
|
"http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
|
2009-07-10 11:34:46 -07:00
|
|
|
"menuitem");
|
|
|
|
|
2010-04-27 09:57:19 -07:00
|
|
|
menuItem.setAttribute("class", "menuitem-iconic alltabs-item menuitem-with-favicon");
|
2009-07-10 11:34:46 -07:00
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
this._setMenuitemAttributes(menuItem, aTab);
|
2009-07-10 11:34:46 -07:00
|
|
|
|
|
|
|
aTab.mCorrespondingMenuitem = menuItem;
|
|
|
|
menuItem.tab = aTab;
|
|
|
|
|
|
|
|
this.appendChild(menuItem);
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2009-12-12 11:31:21 -08:00
|
|
|
|
|
|
|
<method name="_setMenuitemAttributes">
|
|
|
|
<parameter name="aMenuitem"/>
|
|
|
|
<parameter name="aTab"/>
|
|
|
|
<body><![CDATA[
|
|
|
|
aMenuitem.setAttribute("label", aTab.label);
|
|
|
|
aMenuitem.setAttribute("crop", aTab.getAttribute("crop"));
|
|
|
|
|
2011-09-16 10:42:32 -07:00
|
|
|
if (aTab.hasAttribute("busy")) {
|
2009-12-12 11:31:21 -08:00
|
|
|
aMenuitem.setAttribute("busy", aTab.getAttribute("busy"));
|
2011-09-16 10:42:32 -07:00
|
|
|
aMenuitem.removeAttribute("image");
|
|
|
|
} else {
|
|
|
|
aMenuitem.setAttribute("image", aTab.getAttribute("image"));
|
2009-12-12 11:31:21 -08:00
|
|
|
aMenuitem.removeAttribute("busy");
|
2011-09-16 10:42:32 -07:00
|
|
|
}
|
2009-12-12 11:31:21 -08:00
|
|
|
|
2011-09-27 01:39:22 -07:00
|
|
|
if (aTab.hasAttribute("pending"))
|
|
|
|
aMenuitem.setAttribute("pending", aTab.getAttribute("pending"));
|
|
|
|
else
|
|
|
|
aMenuitem.removeAttribute("pending");
|
|
|
|
|
2009-12-12 11:31:21 -08:00
|
|
|
if (aTab.selected)
|
|
|
|
aMenuitem.setAttribute("selected", "true");
|
|
|
|
else
|
|
|
|
aMenuitem.removeAttribute("selected");
|
|
|
|
]]></body>
|
|
|
|
</method>
|
2009-07-10 11:34:46 -07:00
|
|
|
</implementation>
|
|
|
|
|
|
|
|
<handlers>
|
|
|
|
<handler event="popupshowing">
|
|
|
|
<![CDATA[
|
2010-04-27 09:57:19 -07:00
|
|
|
var tabcontainer = gBrowser.tabContainer;
|
2009-07-10 11:34:46 -07:00
|
|
|
|
|
|
|
// Listen for changes in the tab bar.
|
2009-12-12 11:31:21 -08:00
|
|
|
tabcontainer.addEventListener("TabAttrModified", this, false);
|
|
|
|
tabcontainer.addEventListener("TabClose", this, false);
|
2009-07-10 11:34:46 -07:00
|
|
|
tabcontainer.mTabstrip.addEventListener("scroll", this, false);
|
|
|
|
|
2012-01-23 16:39:49 -08:00
|
|
|
let tabs = gBrowser.visibleTabs;
|
2009-07-10 11:34:46 -07:00
|
|
|
for (var i = 0; i < tabs.length; i++) {
|
2012-01-23 16:39:49 -08:00
|
|
|
if (!tabs[i].pinned)
|
|
|
|
this._createTabMenuItem(tabs[i]);
|
2009-07-10 11:34:46 -07:00
|
|
|
}
|
|
|
|
this._updateTabsVisibilityStatus();
|
|
|
|
]]></handler>
|
|
|
|
|
2009-12-11 14:04:02 -08:00
|
|
|
<handler event="popuphidden">
|
2009-07-10 11:34:46 -07:00
|
|
|
<![CDATA[
|
|
|
|
// clear out the menu popup and remove the listeners
|
2011-02-19 02:35:02 -08:00
|
|
|
for (let i = this.childNodes.length - 1; i > 0; i--) {
|
|
|
|
let menuItem = this.childNodes[i];
|
2011-04-28 22:21:13 -07:00
|
|
|
if (menuItem.tab) {
|
2011-02-19 02:35:02 -08:00
|
|
|
menuItem.tab.mCorrespondingMenuitem = null;
|
|
|
|
this.removeChild(menuItem);
|
|
|
|
}
|
2009-07-10 11:34:46 -07:00
|
|
|
}
|
2010-04-27 09:57:19 -07:00
|
|
|
var tabcontainer = gBrowser.tabContainer;
|
2009-07-10 11:34:46 -07:00
|
|
|
tabcontainer.mTabstrip.removeEventListener("scroll", this, false);
|
2009-12-12 11:31:21 -08:00
|
|
|
tabcontainer.removeEventListener("TabAttrModified", this, false);
|
|
|
|
tabcontainer.removeEventListener("TabClose", this, false);
|
2009-07-10 11:34:46 -07:00
|
|
|
]]></handler>
|
|
|
|
|
|
|
|
<handler event="DOMMenuItemActive">
|
|
|
|
<![CDATA[
|
|
|
|
var tab = event.target.tab;
|
|
|
|
if (tab) {
|
2010-10-12 09:30:57 -07:00
|
|
|
let overLink = tab.linkedBrowser.currentURI.spec;
|
|
|
|
if (overLink == "about:blank")
|
|
|
|
overLink = "";
|
|
|
|
XULBrowserWindow.setOverLink(overLink, null);
|
2009-07-10 11:34:46 -07:00
|
|
|
}
|
|
|
|
]]></handler>
|
|
|
|
|
|
|
|
<handler event="DOMMenuItemInactive">
|
|
|
|
<![CDATA[
|
2009-07-20 21:25:59 -07:00
|
|
|
XULBrowserWindow.setOverLink("", null);
|
2009-07-10 11:34:46 -07:00
|
|
|
]]></handler>
|
|
|
|
|
2012-01-23 16:39:49 -08:00
|
|
|
<handler event="command"><![CDATA[
|
|
|
|
if (event.target.tab)
|
|
|
|
gBrowser.selectedTab = event.target.tab;
|
|
|
|
]]></handler>
|
|
|
|
|
2009-07-10 11:34:46 -07:00
|
|
|
</handlers>
|
|
|
|
</binding>
|
|
|
|
|
2011-01-28 05:35:49 -08:00
|
|
|
<binding id="statuspanel" display="xul:hbox">
|
|
|
|
<content>
|
|
|
|
<xul:hbox class="statuspanel-inner">
|
|
|
|
<xul:label class="statuspanel-label"
|
2011-01-27 22:48:28 -08:00
|
|
|
role="status"
|
2013-03-22 08:45:26 -07:00
|
|
|
aria-live="off"
|
2011-02-28 03:58:44 -08:00
|
|
|
xbl:inherits="value=label,crop,mirror"
|
2011-01-28 05:35:49 -08:00
|
|
|
flex="1"
|
|
|
|
crop="end"/>
|
|
|
|
</xul:hbox>
|
|
|
|
</content>
|
|
|
|
|
2011-03-02 16:48:58 -08:00
|
|
|
<implementation implements="nsIDOMEventListener">
|
|
|
|
<constructor><![CDATA[
|
2012-01-12 13:24:44 -08:00
|
|
|
window.addEventListener("resize", this, false);
|
2011-03-02 16:48:58 -08:00
|
|
|
]]></constructor>
|
|
|
|
|
|
|
|
<destructor><![CDATA[
|
2012-01-12 13:24:44 -08:00
|
|
|
window.removeEventListener("resize", this, false);
|
|
|
|
MousePosTracker.removeListener(this);
|
2011-03-02 16:48:58 -08:00
|
|
|
]]></destructor>
|
|
|
|
|
2011-01-28 05:35:49 -08:00
|
|
|
<property name="label">
|
2011-02-09 13:40:13 -08:00
|
|
|
<setter><![CDATA[
|
2012-04-12 01:00:56 -07:00
|
|
|
if (!this.label) {
|
2012-02-15 14:28:26 -08:00
|
|
|
this.removeAttribute("mirror");
|
2012-04-12 01:00:56 -07:00
|
|
|
this.removeAttribute("sizelimit");
|
|
|
|
}
|
2011-02-09 13:40:13 -08:00
|
|
|
|
|
|
|
this.style.minWidth = this.getAttribute("type") == "status" &&
|
|
|
|
this.getAttribute("previoustype") == "status"
|
|
|
|
? getComputedStyle(this).width : "";
|
|
|
|
|
2011-09-27 00:51:56 -07:00
|
|
|
if (val) {
|
|
|
|
this.setAttribute("label", val);
|
|
|
|
this.removeAttribute("inactive");
|
2012-01-12 13:24:44 -08:00
|
|
|
this._calcMouseTargetRect();
|
|
|
|
MousePosTracker.addListener(this);
|
2011-09-27 00:51:56 -07:00
|
|
|
} else {
|
|
|
|
this.setAttribute("inactive", "true");
|
2012-01-12 13:24:44 -08:00
|
|
|
MousePosTracker.removeListener(this);
|
2011-09-27 00:51:56 -07:00
|
|
|
}
|
|
|
|
|
2011-01-28 05:35:49 -08:00
|
|
|
return val;
|
2011-02-09 13:40:13 -08:00
|
|
|
]]></setter>
|
2011-01-28 05:35:49 -08:00
|
|
|
<getter>
|
2011-09-27 00:51:56 -07:00
|
|
|
return this.hasAttribute("inactive") ? "" : this.getAttribute("label");
|
2011-01-28 05:35:49 -08:00
|
|
|
</getter>
|
|
|
|
</property>
|
2011-02-04 00:07:45 -08:00
|
|
|
|
2012-01-12 13:24:44 -08:00
|
|
|
<method name="getMouseTargetRect">
|
|
|
|
<body><![CDATA[
|
|
|
|
return this._mouseTargetRect;
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="onMouseEnter">
|
|
|
|
<body>
|
|
|
|
this._mirror();
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="onMouseLeave">
|
|
|
|
<body>
|
|
|
|
this._mirror();
|
|
|
|
</body>
|
|
|
|
</method>
|
|
|
|
|
2011-03-02 16:48:58 -08:00
|
|
|
<method name="handleEvent">
|
|
|
|
<parameter name="event"/>
|
|
|
|
<body><![CDATA[
|
2012-01-12 13:24:44 -08:00
|
|
|
if (!this.label)
|
|
|
|
return;
|
|
|
|
|
|
|
|
switch (event.type) {
|
|
|
|
case "resize":
|
|
|
|
this._calcMouseTargetRect();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
|
|
|
<method name="_calcMouseTargetRect">
|
|
|
|
<body><![CDATA[
|
2013-09-24 03:09:44 -07:00
|
|
|
let container = this.parentNode;
|
|
|
|
let alignRight = (getComputedStyle(container).direction == "rtl");
|
|
|
|
let panelRect = this.getBoundingClientRect();
|
|
|
|
let containerRect = container.getBoundingClientRect();
|
2012-01-12 13:24:44 -08:00
|
|
|
|
|
|
|
this._mouseTargetRect = {
|
2013-09-24 03:09:44 -07:00
|
|
|
top: panelRect.top,
|
|
|
|
bottom: panelRect.bottom,
|
|
|
|
left: alignRight ? containerRect.right - panelRect.width : containerRect.left,
|
|
|
|
right: alignRight ? containerRect.right : containerRect.left + panelRect.width
|
2012-01-12 13:24:44 -08:00
|
|
|
};
|
2011-03-02 16:48:58 -08:00
|
|
|
]]></body>
|
|
|
|
</method>
|
|
|
|
|
2011-02-04 00:07:45 -08:00
|
|
|
<method name="_mirror">
|
|
|
|
<body>
|
|
|
|
if (this.hasAttribute("mirror"))
|
|
|
|
this.removeAttribute("mirror");
|
|
|
|
else
|
|
|
|
this.setAttribute("mirror", "true");
|
2012-04-12 01:00:56 -07:00
|
|
|
|
|
|
|
if (!this.hasAttribute("sizelimit")) {
|
|
|
|
this.setAttribute("sizelimit", "true");
|
|
|
|
this._calcMouseTargetRect();
|
|
|
|
}
|
2011-02-04 00:07:45 -08:00
|
|
|
</body>
|
|
|
|
</method>
|
2011-01-28 05:35:49 -08:00
|
|
|
</implementation>
|
|
|
|
</binding>
|
|
|
|
|
2007-08-21 21:58:49 -07:00
|
|
|
</bindings>
|