From 49ee0794b5d912db1f95dce6eb52d781dc210db5 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 03:35:06 -0500 Subject: Add Pale Moon --- application/palemoon/base/content/tabbrowser.xml | 4960 ++++++++++++++++++++++ 1 file changed, 4960 insertions(+) create mode 100644 application/palemoon/base/content/tabbrowser.xml (limited to 'application/palemoon/base/content/tabbrowser.xml') diff --git a/application/palemoon/base/content/tabbrowser.xml b/application/palemoon/base/content/tabbrowser.xml new file mode 100644 index 000000000..b8d5f3e41 --- /dev/null +++ b/application/palemoon/base/content/tabbrowser.xml @@ -0,0 +1,4960 @@ + + + + + +%tabBrowserDTD; +]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + document.getElementById(this.getAttribute("tabcontainer")); + + + this.tabContainer.childNodes; + + + + + + + ({ ALL: 0, OTHER: 1, TO_END: 2 }); + + null + + + Components.classes["@mozilla.org/docshell/urifixup;1"] + .getService(Components.interfaces.nsIURIFixup); + + + Components.classes["@mozilla.org/browser/favicon-service;1"] + .getService(Components.interfaces.nsIFaviconService); + + + Components.classes["@mozilla.org/autocomplete/search;1?name=history"] + .getService(Components.interfaces.mozIPlacesAutoComplete); + + + document.getAnonymousElementByAttribute(this, "anonid", "tabbox"); + + + document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer"); + + + document.getAnonymousElementByAttribute(this, "anonid", "tbstringbundle"); + + + null + + + null + + + null + + + [] + + + [] + + + [] + + + [] + + + false + + + new Map(); + + +#ifdef XP_MACOSX + true +#else + false +#endif + + + + null + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + real JS array + let prompts = Array.slice(els); + return prompts; + }, + }; + + return promptBox; + ]]> + + + + + + + + + + + + + + + + + + + 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; + } + + if (aStateFlags & nsIWebProgressListener.STATE_START && + aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { + // It's okay to clear what the user typed when we start + // 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) + // We need to add 2 because loadURIWithFlags may have + // cancelled a pending load which would have cleared + // its anchor scroll detection temporary increment. + if (aWebProgress.isTopLevel) + this.mBrowser.userTypedClear += 2; + + if (this._shouldShowProgress(aRequest)) { + if (!(aStateFlags & nsIWebProgressListener.STATE_RESTORING)) { + this.mTab.setAttribute("busy", "true"); + if (!gMultiProcessBrowser) { + if (aWebProgress.isTopLevel && + !(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_RELOAD)) + this.mTabBrowser.setTabTitleLoading(this.mTab); + } + } + + if (this.mTab.selected) + this.mTabBrowser.mIsBusy = true; + } + } + else if (aStateFlags & nsIWebProgressListener.STATE_STOP && + aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) { + + 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"); + + if (aWebProgress.isTopLevel) { + 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; + + var location = aRequest.QueryInterface(nsIChannel).URI; + + // For keyword URIs clear the user typed value since they will be changed into real URIs + if (location.scheme == "keyword") + this.mBrowser.userTypedValue = null; + + if (this.mTab.label == this.mTabBrowser.mStringBundle.getString("tabs.connecting")) + this.mTabBrowser.setTabTitle(this.mTab); + + if (this.mTab.selected) + this.mTabBrowser.mIsBusy = false; + } + + if (oldBlank) { + this._callProgressListeners("onUpdateCurrentBrowser", + [aStateFlags, aStatus, "", 0], + true, false); + } else { + this._callProgressListeners("onStateChange", + [aWebProgress, aRequest, aStateFlags, aStatus], + true, false); + } + + this._callProgressListeners("onStateChange", + [aWebProgress, aRequest, aStateFlags, aStatus], + false); + + 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; + }, + + onLocationChange: function (aWebProgress, aRequest, aLocation, + aFlags) { + // OnLocationChange is called for both the top-level content + // and the subframes. + let topLevel = aWebProgress.isTopLevel; + + if (topLevel) { + // 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). + if (this.mBrowser.userTypedClear > 0 || + ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) && + aLocation.spec != "about:blank")) + this.mBrowser.userTypedValue = null; + + // Don't clear the favicon if this onLocationChange was + // triggered by a pushState or a replaceState. See bug 550565. + if (!gMultiProcessBrowser) { + if (aWebProgress.isLoadingDocument && + !(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE)) + this.mBrowser.mIconURL = null; + } + + let autocomplete = this.mTabBrowser._placesAutocomplete; + if (this.mBrowser.registeredOpenURI) { + autocomplete.unregisterOpenPage(this.mBrowser.registeredOpenURI); + delete this.mBrowser.registeredOpenURI; + } + // Tabs in private windows aren't registered as "Open" so + // that they don't appear as switch-to-tab candidates. + if (!isBlankPageURL(aLocation.spec) && + (!PrivateBrowsingUtils.isWindowPrivate(window) || + PrivateBrowsingUtils.permanentPrivateBrowsing)) { + autocomplete.registerOpenPage(aLocation); + this.mBrowser.registeredOpenURI = aLocation; + } + } + + if (!this.mBlank) { + this._callProgressListeners("onLocationChange", + [aWebProgress, aRequest, aLocation, + aFlags]); + } + + if (topLevel) + this.mBrowser.lastURI = aLocation; + }, + + onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) { + if (this.mBlank) + return; + + this._callProgressListeners("onStatusChange", + [aWebProgress, aRequest, aStatus, aMessage]); + + this.mMessage = aMessage; + }, + + onSecurityChange: function (aWebProgress, aRequest, aState) { + this._callProgressListeners("onSecurityChange", + [aWebProgress, aRequest, aState]); + }, + + onRefreshAttempted: function (aWebProgress, aURI, aDelay, aSameURI) { + return this._callProgressListeners("onRefreshAttempted", + [aWebProgress, aURI, aDelay, aSameURI]); + }, + + QueryInterface: function (aIID) { + if (aIID.equals(Components.interfaces.nsIWebProgressListener) || + aIID.equals(Components.interfaces.nsIWebProgressListener2) || + aIID.equals(Components.interfaces.nsISupportsWeakReference) || + aIID.equals(Components.interfaces.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + } + }); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + let req = browser.contentDocument.imageRequest; + let sz = Services.prefs.getIntPref("browser.chrome.image_icons.max_size"); + if (browser.contentDocument instanceof ImageDocument && + req && req.image) { + if (Services.prefs.getBoolPref("browser.chrome.site_icons") && sz) { + try { + + var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas"); + var tabImg = document.getAnonymousElementByAttribute(aTab, "anonid", "tab-icon"); + var w = tabImg.boxObject.width; + var h = tabImg.boxObject.height; + canvas.width = w; + canvas.height = h; + var ctx = canvas.getContext('2d'); + ctx.drawImage(browser.contentDocument.body.firstChild, 0, 0, w, h); + icon = canvas.toDataURL(); + } + catch (e) { + + try { + + if (req && + req.image && + req.image.width <= sz && + req.image.height <= sz) + icon = browser.currentURI; + } + catch (e) { + + } + } + } + } + // Use documentURIObject in the check for shouldLoadFavIcon so that we + // do the right thing with about:-style error pages. Bug 453442 + else if (this.shouldLoadFavIcon(docURIObject)) { + let url = docURIObject.prePath + "/favicon.ico"; + if (!this.isFailedIcon(url)) + icon = url; + } + this.setIcon(aTab, icon); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + oldBrowser.finder.removeResultListener(l)); + } + + var updateBlockedPopups = false; + if (!oldBrowser || + (oldBrowser.blockedPopups && !newBrowser.blockedPopups) || + (!oldBrowser.blockedPopups && newBrowser.blockedPopups)) + updateBlockedPopups = true; + + newBrowser.setAttribute("type", "content-primary"); + newBrowser.docShellIsActive = + (window.windowState != window.STATE_MINIMIZED); + this.mCurrentBrowser = newBrowser; + this.mCurrentTab = this.tabContainer.selectedItem; + this.finder.mListeners.forEach(l => this.mCurrentBrowser.finder.addResultListener(l)); + this.showTab(this.mCurrentTab); + + var backForwardContainer = document.getElementById("unified-back-forward-button"); + if (backForwardContainer) { + backForwardContainer.setAttribute("switchingtabs", "true"); + window.addEventListener("MozAfterPaint", function removeSwitchingtabsAttr() { + window.removeEventListener("MozAfterPaint", removeSwitchingtabsAttr); + backForwardContainer.removeAttribute("switchingtabs"); + }); + } + + if (updateBlockedPopups) + this.mCurrentBrowser.updateBlockedPopups(); + + // Update the URL bar. + var loc = this.mCurrentBrowser.currentURI; + + // Bug 666809 - SecurityUI support for e10s + var webProgress = this.mCurrentBrowser.webProgress; + var securityUI = this.mCurrentBrowser.securityUI; + + this._callProgressListeners(null, "onLocationChange", + [webProgress, null, loc, 0], true, + false); + + if (securityUI) { + this._callProgressListeners(null, "onSecurityChange", + [webProgress, null, securityUI.state], true, false); + } + + 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); + } + + if (!this._previewMode) { + this.mCurrentTab.removeAttribute("unread"); + this.selectedTab.lastAccessed = Date.now(); + + // Bug 666816 - TypeAheadFind support for e10s + if (!gMultiProcessBrowser) + this._fastFind.setDocShell(this.mCurrentBrowser.docShell); + + this.updateTitlebar(); + + this.mCurrentTab.removeAttribute("titlechanged"); + } + + // 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; + this._callProgressListeners(null, "onStateChange", + [webProgress, null, + nsIWebProgressListener.STATE_START | + nsIWebProgressListener.STATE_IS_NETWORK, 0], + true, false); + } + + // 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; + this._callProgressListeners(null, "onStateChange", + [webProgress, null, + nsIWebProgressListener.STATE_STOP | + nsIWebProgressListener.STATE_IS_NETWORK, 0], + true, false); + } + + this._setCloseKeyState(!this.mCurrentTab.pinned); + + // 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. + let event = new CustomEvent("TabSelect", { + bubbles: true, + cancelable: false, + detail: { + previousTab: oldTab + } + }); + this.mCurrentTab.dispatchEvent(event); + + this._tabAttrModified(oldTab); + this._tabAttrModified(this.mCurrentTab); + + // Adjust focus + oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused); + do { + // 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; + } + + // 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; + } + + // 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) { + + // Explicitly close the popup if the URL bar retains focus + gURLBar.closePopup(); + + if (!window.fullScreen) { + gURLBar.focus(); + break; + } else if (isTabEmpty(this.mCurrentTab)) { + focusAndSelectUrlBar(); + break; + } + } + + // If the find bar is focused, keep it focused. + if (gFindBarInitialized && + !gFindBar.hidden && + gFindBar.getElement("findbar-textbox").getAttribute("focused") == "true") + break; + + // Otherwise, focus the content area. + let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); + let focusFlags = fm.FLAG_NOSCROLL; + + 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; + } + fm.setFocus(newBrowser, focusFlags); + } while (false); + } + + this.tabContainer._setPositionalAttributes(); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 false/true NO + var multiple = aURIs.length > 1; + var owner = multiple || aLoadInBackground ? null : this.selectedTab; + var firstTabAdded = null; + + 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. + } + } + else + firstTabAdded = this.addTab(aURIs[0], {ownerTab: owner, skipAnimation: multiple}); + + var tabNum = this.tabContainer.selectedIndex; + for (let i = 1; i < aURIs.length; ++i) { + let tab = this.addTab(aURIs[i], {skipAnimation: true}); + if (aReplace) + this.moveTabTo(tab, ++tabNum); + } + + if (!aLoadInBackground) { + if (firstTabAdded) { + // .selectedTab setter focuses the content area + this.selectedTab = firstTabAdded; + } + else + this.selectedBrowser.focus(); + } + ]]> + + + + + + + + + + + is inserted + // into the DOM. We thus have to register the new outerWindowID + // for non-remote browsers after we have called browser.loadURI(). + // + // Note: Only do this of we still have a docShell. The TabOpen + // event was dispatched above and a gBrowser.removeTab() call from + // one of its listeners could cause us to fail here. + if (Services.prefs.getPrefType("browser.tabs.remote") == Services.prefs.PREF_BOOL && + !Services.prefs.getBoolPref("browser.tabs.remote") + && b.docShell) { + this._outerWindowIDBrowserMap.set(b.outerWindowID, b); + } + + // 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. + if ((aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent) && + Services.prefs.getBoolPref("browser.tabs.insertRelatedAfterCurrent")) { + let newTabPos = (this._lastRelatedTab || + this.selectedTab)._tPos + 1; + if (this._lastRelatedTab) + this._lastRelatedTab.owner = null; + else + t.owner = this.selectedTab; + this.moveTabTo(t, newTabPos); + this._lastRelatedTab = t; + } + + if (animate) { + 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. + if (this.tabs.length - this._removingTabs.length == 2) + this.tabContainer.adjustTabstrip(); + }.bind(this)); + } + + return t; + ]]> + + + + + + + + + + + + + + + = 0; --i) { + tabsToEnd.push(tabs[i]); + } + return tabsToEnd.reverse(); + ]]> + + + + + + + = 0; --i) { + this.removeTab(tabs[i], {animate: true}); + } + } + ]]> + + + + + + + = 0; --i) { + if (tabs[i] != aTab && !tabs[i].pinned) + this.removeTab(tabs[i]); + } + } + ]]> + + + + + + + + + + + + [] + + + + + + + 3 /* don't want lots of concurrent animations */ || + aTab.getAttribute("fadein") != "true" /* fade-in transition hasn't been triggered yet */ || + window.getComputedStyle(aTab).maxWidth == "0.1px" /* fade-in transition hasn't moved yet */ || + !Services.prefs.getBoolPref("browser.tabs.animate")) { + this._endRemoveTab(aTab); + return; + } + + this.tabContainer._handleTabTelemetryStart(aTab); + + this._blurTab(aTab); + aTab.style.maxWidth = ""; // ensure that fade-out transition happens + aTab.removeAttribute("fadein"); + + 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(); + } + + setTimeout(function (tab, tabbrowser) { + if (tab.parentNode && + window.getComputedStyle(tab).maxWidth == "0.1px") { + NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)"); + tabbrowser._endRemoveTab(tab); + } + }, 3000, aTab, this); + ]]> + + + + + + false + + + + + + + + + + + + + + + + 1) { + // let newPos = this.selectedTab._tPos - 1; + // this.selectedTab = this.tabs[newPos]; + // } + //} + + // update tab positional properties and attributes + this.selectedTab._selected = true; + this.tabContainer._setPositionalAttributes(); + + // 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. + + var panel = this.getNotificationBox(browser); + + // 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.). + browser.parentNode.removeChild(browser); + + // Release the browser in case something is erroneously holding a + // reference to the tab after its removal. + this._tabForBrowser.delete(aTab.linkedBrowser); + aTab.linkedBrowser = null; + + // As the browser is removed, the removal of a dependent document can + // cause the whole window to close. So at this point, it's possible + // that the binding is destructed. + 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; + } + + if (aCloseWindow) + this._windowIsClosing = closeWindow(true, window.warnAboutClosingWindow); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + this.mTabsProgressListeners.push(aListener); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + = 0 && aIndex < tabs.length) + this.selectedTab = tabs[aIndex]; + + if (aEvent) { + aEvent.preventDefault(); + aEvent.stopPropagation(); + } + ]]> + + + + + + return this.mCurrentTab; + + + + + + + + + + + + + + null + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0) + this.moveTabTo(this.mCurrentTab, 0); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + null + + + + + + + null + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + if (this.browsers[0].contentWindow == subject) { + Services.obs.removeObserver(obs, topic); + this._addProgressListenerForInitialTab(); + } + }; + + // We use content-document-global-created as an approximation for + // "docShell is initialized". We can do this because in the + // mTabProgressListener we care most about the STATE_STOP notification + // that will reset mBlank. That means it's important to at least add + // the progress listener before the initial about:blank load stops + // if we can't do it before the load starts. + Services.obs.addObserver(obs, "content-document-global-created", false); + ]]> + + + + + + + + + + Application.console.log("enterTabbedMode is an obsolete method and " + + "will be removed in a future release."); + + + true + + + + this.tabContainer.visible = aShow; + + + + + return this.tabContainer.visible; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# This is a hack to circumvent bug 472020, otherwise the tabs show up on the +# right of the newtab button. + +# This is to ensure anything extensions put here will go before the newtab +# button, necessary due to the previous hack. + + + + + + + + + + + + + + + + + document.getElementById(this.getAttribute("tabbrowser")); + + + + this.tabbrowser.mTabBox; + + + + document.getElementById("tabContextMenu"); + + + 0 + + + document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox"); + + + null + null + null + null + null + + + + + + + false + + + document.getAnonymousElementByAttribute(this, "anonid", "tab-drop-indicator"); + + + 350 + 0 + + + + false + + + + + + + + + + + + + + + + + + + + + + + this.mTabClipWidth) + this.setAttribute("closebuttons", "alltabs"); + else + this.setAttribute("closebuttons", "activetab"); + } + break; + case 2: + case 3: + this.setAttribute("closebuttons", "never"); + break; + } + var tabstripClosebutton = document.getElementById("tabs-closebutton"); + if (tabstripClosebutton && tabstripClosebutton.parentNode == this._container) + tabstripClosebutton.collapsed = this.mCloseButtons != 3; + ]]> + + + + + + + + + + tabStrip.scrollSize) + tabStrip.scrollByPixels(-1); + } catch (e) {} + ]]> + + + + document.getAnonymousElementByAttribute(this, "anonid", "closing-tabs-spacer"); + + + NaN + false + false + + + + + tabs[tabs.length-1]._tPos); + var tabWidth = aTab.getBoundingClientRect().width; + + if (!this._tabDefaultMaxWidth) + this._tabDefaultMaxWidth = + parseFloat(window.getComputedStyle(aTab).maxWidth); + this._lastTabClosedByMouse = true; + + if (this.getAttribute("overflow") == "true") { +#ifdef XP_WIN + // Don't need to do anything if we're in overflow mode and we're closing + // the last tab. + if (isEndTab) +#else + // 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) +#endif + return; + + // 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; + + // Resize immediately if preffed + // XXX: we may want to make this a three-state pref to disable this early + // exit if people prefer a mix of behavior (don't resize in overflow, + // but resize if not overflowing) + if (Services.prefs.getBoolPref("browser.tabs.resize_immediately")) + return; + + this._expandSpacerBy(tabWidth); + } else { // non-overflow mode + // Locking is neither in effect nor needed, so let tabs expand normally. + if (isEndTab && !this._hasTabTempMaxWidth) + return; + + // Resize immediately if preffed + // XXX: we may want to make this a three-state pref to disable this early + // exit if people prefer a mix of behavior (don't resize in overflow, + // but resize if not overflowing) + if (Services.prefs.getBoolPref("browser.tabs.resize_immediately")) + return; + + 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; + } + 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); + } + ]]> + + + + + + + + + + + + 0 + + 0; + + if (doPosition) { + this.setAttribute("positionpinnedtabs", "true"); + + let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width; + let paddingStart = this.mTabstrip.scrollboxPaddingStart; + let width = 0; + + for (let i = numPinned - 1; i >= 0; i--) { + let tab = this.childNodes[i]; + width += tab.getBoundingClientRect().width; + tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px"; + } + + this.style.MozPaddingStart = width + paddingStart + "px"; + + } else { + this.removeAttribute("positionpinnedtabs"); + + for (let i = 0; i < numPinned; i++) { + let tab = this.childNodes[i]; + tab.style.MozMarginStart = ""; + } + + this.style.MozPaddingStart = ""; + } + + if (this._lastNumPinned != numPinned) { + this._lastNumPinned = numPinned; + this._handleTabSelect(false); + } + ]]> + + + + + 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; + } + ]]> + + + + + + + + + + + + + this.mTabstrip._scrollButtonDown; + + + + + + + + + + boxObject.screenX + boxObject.width * .75) + return null; + } + return tab; + ]]> + + + + + tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2) + return i; + } + return tabs.length; + ]]> + + + + + 1) + return dt.effectAllowed = "none"; + + 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" && + sourceNode.ownerDocument.defaultView instanceof ChromeWindow && + sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser" && + sourceNode.ownerDocument.defaultView.gBrowser.tabContainer == sourceNode.parentNode) { + // 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"; + +#ifdef XP_MACOSX + return dt.effectAllowed = event.altKey ? "copy" : "move"; +#else + return dt.effectAllowed = event.ctrlKey ? "copy" : "move"; +#endif + } + } + + if (browserDragAndDrop.canDropLink(event)) { + // Here we need to do this manually + return dt.effectAllowed = dt.dropEffect = "link"; + } + return dt.effectAllowed = "none"; + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + 0) { + let averageInterval = 0; + let averagePaint = paints[0]; + for (let i = 1; i < frameCount; i++) { + averageInterval += intervals[i]; + averagePaint += paints[i]; + }; + averagePaint /= frameCount; + averageInterval = (frameCount == 1) + ? averagePaint + : averageInterval / (frameCount - 1); + + if (aTab._recordingTabOpenPlain) { + delete aTab._recordingTabOpenPlain; + } + } + ]]> + + + + + + + + + + + + + + + + 1 || !this._closeWindowWithLastTab) + this.tabbrowser.removeTab(event.target, {animate: true, byMouse: true}); + } else if (event.originalTarget.localName == "box") { + BrowserOpenTab(); + } else { + return; + } + + event.stopPropagation(); + ]]> + + + + + + = this._dragTime + this._dragOverDelay) + this.selectedItem = tab; + ind.collapsed = true; + return; + } + } + + var rect = tabStrip.getBoundingClientRect(); + var newMargin; + if (pixelsToScroll) { + // if we are scrolling, put the drop indicator at the edge + // so that it doesn't jump while scrolling + 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]; + newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin; + } + else { + let newIndex = this._getDropIndex(event); + 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; + } + } + + ind.collapsed = false; + + newMargin += ind.clientWidth / 2; + if (!ltr) + newMargin *= -1; + + ind.style.transform = "translate(" + Math.round(newMargin) + "px)"; + ind.style.MozMarginStart = (-ind.clientWidth) + "px"; + ]]> + + draggedTab._tPos) + newIndex--; + this.tabbrowser.moveTabTo(draggedTab, newIndex); + } + } 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) + let newIndex = this._getDropIndex(event); + 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; + + let numPinned = this.tabbrowser._numPinnedTabs; + if (newIndex < numPinned || draggedTab.pinned && newIndex == numPinned) + this.tabbrowser.pinTab(newTab); + this.tabbrowser.moveTabTo(newTab, newIndex); + + // 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; + + draggedTab.parentNode._finishAnimateTabMove(); + this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab); + + // Call updateCurrentBrowser to make sure the URL bar is up to date + // for our new tab after we've done swapBrowsersAndCloseOther. + this.tabbrowser.updateCurrentBrowser(true); + } else { + // Pass true to disallow dropping javascript: or data: urls + let url; + try { + url = browserDragAndDrop.drop(event, { }, true); + } catch (ex) {} + +// // valid urls don't contain spaces ' '; if we have a space it isn't a valid url. +// if (!url || url.includes(" ")) //PMed + if (!url) //FF + return; + + 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); + let newTab = this.tabbrowser.loadOneTab(url, {inBackground: bgLoad, allowThirdPartyFixup: true}); + this.tabbrowser.moveTabTo(newTab, newIndex); + } else { + // Load in an existing tab. + try { + 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); + if (!bgLoad) + this.selectedItem = tab; + } catch(ex) { + // Just ignore invalid urls + } + } + } + + if (draggedTab) { + delete draggedTab._dragData; + } + ]]> + + 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); + var left = Math.min(Math.max(eX - draggedTab._dragData.offsetX, sX.value), + sX.value + sWidth.value - winWidth); + var top = Math.min(Math.max(eY - draggedTab._dragData.offsetY, sY.value), + sY.value + sHeight.value - winHeight); + + delete draggedTab._dragData; + + 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(); + ]]> + + + + + + + + + 1 && !this._ignoredClick) { + this._ignoredClick = true; + return; + } + + // Reset the "ignored click" flag + this._ignoredClick = false; + + tabContainer.tabbrowser.removeTab(bindingParent, {animate: true, byMouse: true}); + tabContainer._blockDblClick = true; + + /* XXXmano hack (see bug 343628): + * Since we're removing the event target, if the user + * double-clicks this 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 dblclick handler). + */ + var clickedOnce = false; + function enableDblClick(event) { + var target = event.originalTarget; + if (target.className == 'tab-close-button') + target._ignoredClick = true; + if (!clickedOnce) { + clickedOnce = true; + return; + } + tabContainer._blockDblClick = false; + tabContainer.removeEventListener("click", enableDblClick, true); + } + tabContainer.addEventListener("click", enableDblClick, true); + ]]> + + + // for the one-close-button case + event.stopPropagation(); + + + + event.stopPropagation(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + return this.getAttribute("pinned") == "true"; + + + + + return this.getAttribute("hidden") == "true"; + + + + false + null + false + 0 + + + + + + + this.style.MozUserFocus = ''; + + + + + + this.style.MozUserFocus = ''; + + + + + + + + + + + + + + + + + + + + + + + = tabstripBO.screenX && + curTabBO.screenX + curTabBO.width <= tabstripBO.screenX + tabstripBO.width) + this.childNodes[i].setAttribute("tabIsVisible", "true"); + else + this.childNodes[i].removeAttribute("tabIsVisible"); + } + ]]> + + + + + + + + + + + + + + + + + + + + = 0; i--) { + let menuItem = this.childNodes[i]; + if (menuItem.tab) { + menuItem.tab.mCorrespondingMenuitem = null; + this.removeChild(menuItem); + } + } + var tabcontainer = gBrowser.tabContainer; + tabcontainer.mTabstrip.removeEventListener("scroll", this, false); + tabcontainer.removeEventListener("TabAttrModified", this, false); + tabcontainer.removeEventListener("TabClose", this, false); + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + return this.hasAttribute("inactive") ? "" : this.getAttribute("label"); + + + + + + + + + + this._mirror(); + + + + + + this._mirror(); + + + + + + + + + + + + + + + if (this.hasAttribute("mirror")) + this.removeAttribute("mirror"); + else + this.setAttribute("mirror", "true"); + + if (!this.hasAttribute("sizelimit")) { + this.setAttribute("sizelimit", "true"); + this._calcMouseTargetRect(); + } + + + + + + -- cgit v1.2.3